BUUCTF_WEB_[CISCN 2019 初赛]Love Math 题解
[CISCN 2019 初赛]Love Math
1.打开网页发现是PHP代码:
1 |
|
2.代码审计:
1 |
|
函数介绍:
issert:
1 |
|
show_source(filename,return):
1 |
|
int preg_match ( string $pattern , string $subject [, array &$matches [, int $flags = 0 [, int $offset = 0 ]]] ):
in_array(search,array,type)
3.分析:
由于我们需要利用最后eval()函数执行恶意代码,所以最后content的值应该为:
system(“ls /“)
测试代码:
1 |
|
输出:
而content的值又是GET(‘c’)进行获取
payload:
1 |
|
这是因为我们输入的内容中含有黑名单字符:”,空格
在PHP代码中没有””命令依然可以被执行:
测试:
1 |
|
输出:
由于eval()可以执行正确语法的PHP代码,所以我们可以在eval()中构造一个PHP代码,即用变量保存函数和参数:
1 |
|
所以最后构造的payload:
1 |
|
GET()函数中也可以不需要单引号’’,并且[]可以使用{}代替
1 |
|
测试:
1 |
|
payload:
1 |
|
输出:
在题目的网页中输入后显示:

这时已经绕过第一层判断,来到第二层判断:
4.对第二层判断进行绕过:
函数介绍:
base_convert()函数(属于数学函数):
hex2bin(String) 函数(属于字符串函数):
dechex() 函数(属于数学函数):
现在的payload:
1 |
|
由于函数:
1 |
|
对该正则表达式的解释:
1 |
|
所以提取的是content字符串中所有的单词,所以最终content会被提取成:GET,a,b
这些单词都不包含在白名单中,所以要将这些单词进行替换(内部函数名可以被用作是参数名)a=>abs,b=>atan,GET由于是要函数执行,所以无法被替换:
payload:
1 |
|
我们可以利用数学函数对$_GET进行转码
36进制介绍(同理17-35进制,就是少了一些字母):
1 |
|
实例:
1 |
|
我们可以发现通过十进制转36进制可以被0-9和a-z的字符进行表示输出36进制字符串,所以我们可以构造一个特定的十进制值使其被转化为36进制时刚好是字符串函数hex2bin:
将36进制(36进制包含所有非特殊字符,可以用于表示所有不含特殊字符的函数)hex2bin转化为10进制:
1 |
|
由于$_GET函数含有特殊字符,所以必须使用hex2bin将16进制转化为ASCII码的形式进行代换
将字符串转化为16进制:
1 |
|
输出:
1 |
|
发现16进制表示中含有字母,所以会被preg_match_all()函数提取,所以要将该16进制转化为10进制,再由dechex() 将10进制转回给16进制
16进制转10进制:
1 |
|
_GET的payload的构造:
1 |
|
所以$_GET{}:
1 |
|
5.构造payload
原来的payload:
1 |
|
转换payload:
1 |
|
由于c的长度太长所以必须简化payload
测试:
1 |
|
输出:
发现系统命令没有被执行,所以直接应用的方式是错误的,我们需要采用间接引用字符串的方式:
测试:
1 |
|
payload:
1 |
|
发生了输出,说明system(dir)在没有echo的情况下依然可以输出内容
所以我们可以构造多句合法PHP代码使其存在于eval()函数中,使该函数执行多条PHP代码,然后我们在对其进行注入(类似于插入一句话木马)
1 |
|
输出:
6.用间接引用简化payload(使用pi作为参数是因为它既是白名单字符串,同时也很短):
在PHP函数的参数中string类型都可以不用加双引号或单引号,PHP会自动进行解析,同时用GET或POST方法传输内容时也不需要””和’’:
1 |
|
发现flag文件,将其打开查看:
payload:
1 |
|
flag = flag{26bb1d2a-6719-409c-88f7-14461687b994}