Jinja2 的自动转义到底保护哪些位置?哪些位置它不管?|safe、Markup、属性不加引号、JS 上下文、href 各自会怎样?这篇用 9 种输出位置的攻击载荷,在真实的 Chrome 里逐个看脚本到底有没有执行。
正文里 {{ q }}(自动转义) 载荷 '<script>window.__x=1</script>'
服务端输出的 HTML: <div><script>window.__x=1</script></div>
浏览器结果:没有执行
正文里 {{ q|safe }} 载荷 '<script>window.__x=1</script>'
服务端输出的 HTML: <div><script>window.__x=1</script></div>
浏览器结果:XSS 执行了
属性不加引号 value={{ q }} 载荷 'x onfocus=window.__x=1 autofocus'
服务端输出的 HTML: <input value=x onfocus=window.__x=1 autofocus>
浏览器结果:XSS 执行了
属性加引号 value="{{ q }}" 载荷 '" onfocus="window.__x=1" autofocus'
服务端输出的 HTML: <input value="" onfocus="window.__x=1" autofocus="">
浏览器结果:没有执行
脚本里的字符串 "{{ q }}" 载荷 '";window.__x=1;//'
服务端输出的 HTML: <script>var name = "";window.__x=1;//";</script>
浏览器结果:没有执行
脚本里直接 {{ q }}(没有引号) 载荷 '1;window.__x=1'
服务端输出的 HTML: <script>var n = 1;window.__x=1;</script>
浏览器结果:XSS 执行了
脚本里 {{ q|tojson }} 载荷 '1;window.__x=1'
服务端输出的 HTML: <script>var n = "1;window.__x=1";</script>
浏览器结果:没有执行
href="{{ q }}"(页面自动点击链接) 载荷 'javascript:window.__x=1'
服务端输出的 HTML: <a id=l href="javascript:window.__x=1">click</a><script>document.getElementById("l").click()</script>
浏览器结果:XSS 执行了
Markup("<b>" + q + "</b>") 拼接后输出 载荷 '<img src=x onerror=window.__x=1>'
服务端输出的 HTML: <div><b><img src=x onerror=window.__x=1></b></div>
浏览器结果:XSS 执行了上一篇:CSRF 防护;下一篇:SQL Injection 与参数化查询。
浏览器是本机的 Google Chrome 无头模式。「脚本是否执行」的判断是载荷里把 window.__x 置位、页面末尾读取它,没有弹窗。