---
id: cs.web-security.common-attacks
title: Web 安全基础:XSS、CSRF、SQL 注入、CORS、SSRF 的原理、防御和在 AI 应用中的新形态
type: lesson
domain: cs
stack: [web-security]
tags: [XSS, CSRF, SQL 注入, CORS, SSRF, CSP, SameSite, 参数化查询, OWASP]
level: basic
prerequisites: [cs.network-os.http-tcp]
est_hours: 3
related: [cs.web-security.scenario.ai-app-security, ai.prompt-engineering.scenario.injection-defense, cs.web-security.interview]
week: [7, 14, 16]
order: 1
---
# Web 安全基础:XSS、CSRF、SQL 注入、CORS、SSRF 的原理、防御和在 AI 应用中的新形态
> BOSS直聘 2026-10-23 的调研中有岗位提到 Web 安全基础。AI 应用让老问题出现了新入口:模型输出可能包含恶意 HTML(XSS),Agent 的抓取工具可能被诱导访问内网(SSRF),用户输入可能拼接进模型生成的 SQL。参考:OWASP Top 10(https://owasp.org/www-project-top-ten/)。
## 解释说明
| 攻击 | 原理 | 防御 |
| --- | --- | --- |
| **XSS**(跨站脚本) | 攻击者的脚本被当作页面的一部分执行,可以窃取数据、冒充用户操作 | 输出时按上下文转义(框架默认转义,慎用 `v-html` / `dangerouslySetInnerHTML`);富文本用白名单清洗;CSP;Cookie 设 HttpOnly |
| **CSRF**(跨站请求伪造) | 用户已登录,恶意网站让浏览器带着 Cookie 向目标站点发请求 | Cookie `SameSite=Lax/Strict`;CSRF Token(同步令牌或双重提交);校验 Origin;改变状态的操作不用 GET |
| **SQL 注入** | 用户输入被拼接成 SQL 执行 | **参数化查询**;ORM;最小权限的数据库账号;不能参数化的部分(表名、排序字段)用白名单 |
| **CORS 配置错误** | CORS 是浏览器放宽同源策略的机制;配置成“任意来源 + 允许凭证”或反射请求的 Origin,等于允许任何网站读取用户数据 | 来源白名单;带凭证时不能用 `*`;只开放需要的方法和请求头 |
| **SSRF**(服务端请求伪造) | 诱导服务器访问内网地址(数据库、管理接口、云元数据 `169.254.169.254`) | 协议白名单;解析域名后检查所有 IP 是否为公网;禁止或逐跳校验重定向;网络层出口限制 |
**注意**:CORS 不是安全防护,而是对同源策略的“放宽”;服务端仍然必须做鉴权。CORS 也不能防 CSRF(简单请求照样会发出,只是读不到响应)。
### AI 应用中的新形态
- 模型输出渲染成 HTML / Markdown 时的 XSS:Markdown 中的原始 HTML、`javascript:` 链接、图片链接外带数据(``)。
- 提示词注入诱导 Agent 调用工具:抓取内网地址(SSRF)、执行越权操作。见[提示词注入防护](../../ai/prompt-engineering/scenarios/injection-defense.md)。
- Text-to-SQL:模型生成的 SQL 要用只读账号、白名单表、限制行数,并在执行前做语法分析。
## 案例
AI 客服页面把模型回答作为 Markdown 渲染。有人在知识库文档中埋入 `
`,模型在回答中原样引用,所有看到回答的用户都执行了这段脚本。修复:渲染前清洗(禁用原始 HTML,过滤危险协议的链接)、CSP 禁止内联脚本、会话 Cookie 设 HttpOnly。
## 代码示例
[examples/secure-api](examples/secure-api/)(FastAPI + sqlite3,13 个测试通过;每类问题都先证明“错误写法可被利用”,再证明“正确写法能防住”):
```python
# SQL 注入:拼接 vs 参数化
db.execute(f"... WHERE tenant = '{tenant}' AND id LIKE '%{keyword}%'") # keyword = "x' OR 1=1 --" 读到其他租户
db.execute("... WHERE tenant = ? AND id LIKE ?", (tenant, f"%{keyword}%")) # 安全
# SSRF:解析后检查所有 IP
for info in socket.getaddrinfo(host, port):
if not ipaddress.ip_address(info[4][0]).is_global:
raise ValueError("禁止访问内网地址")
```
CORS 白名单 + CSRF 双重提交:
```python
app.add_middleware(CORSMiddleware, allow_origins=["https://app.example.com"], allow_credentials=True, ...)
if not secrets.compare_digest(csrf_cookie, x_csrf_token): # 跨站页面读不到 csrf_token Cookie,无法设置请求头
raise HTTPException(403, "CSRF 校验失败")
```
## 易错点
- 只在前端校验输入。
- 用黑名单过滤 XSS(`replace("