flawopen.com/跨站脚本攻击/Python

跨站脚本攻击 in Python

高危 CWE-79 Draft — pending review
Language: English Português (Brasil) Español Français Deutsch Русский 简体中文 日本語 हिन्दी 한국어 Bahasa Indonesia
通俗解释 (ELI5)

Imagine a guestbook where a visitor writes a note containing hidden script tags that execute in the browser of the next person who opens the page.

核心概念
output encoding
Converting special markup characters into safe entities so browsers display them as text rather than script.

原理解析

跨站脚本攻击 in Python occurs when untrusted input is formatted directly into HTML strings instead of using template auto-escaping.

真实安全事件

In 2005, the Samy XSS worm infected over 1 million user profiles on MySpace in under 20 hours, forcing the platform offline.

Documented historical AppSec case study.

缺陷代码 vs 修复方案

VULNERABLE
# username inserted with no escaping
@app.route("/welcome")
def welcome():
  name = request.args.get("name")
  return f"
Welcome, {name}
"
FIXED
# Jinja2 template auto-escapes by default
@app.route("/welcome")
def welcome():
  name = request.args.get("name")
  return render_template("welcome.html", name=name)

修复原理

Template engines like Jinja2 and Django auto-escape HTML entities by default, rendering markup inert.

语言专属陷阱

Django mark_safe() and Jinja2 | safe

Marking untrusted data as safe disables all escaping, reopening stored and reflected XSS.

f-strings bypass templates

Python f-strings execute before template rendering, bypassing auto-escaping entirely.

常见认知误区

"f-strings are safe inside templates"

f-strings evaluate before template escaping happens, leaving user input completely raw.

如何检测与排查

grep -rn "render_template_string(.*f\"" --include="*.py" . grep -rn "mark_safe(" --include="*.py" .
Run Bandit with rule B701 (jinja2_autoescape_false) in CI to catch unescaped templates automatically.

防御自查清单

常见问题 (FAQ)

Does Flask escape by default?

Yes, for .html, .htm, and .xml template extensions rendered with render_template().

参考规范

相关漏洞: SQL Injection Command InjectionPath Traversal