Web 安全
Web 漏洞的共同主题是**"数据与代码的边界":几乎所有的注入类漏洞都源于把不可信数据当成了代码**。本章讲 SQL 注入、XSS、CSRF、同源策略与 CORS、点击劫持——每一类都回到这条边界。
注入:数据变代码
Section titled “注入:数据变代码”SQL 注入
Section titled “SQL 注入”# 危险:字符串拼接——数据成了 SQL 代码cursor.execute(f"SELECT * FROM users WHERE name = '{name}'")# name = "x' OR '1'='1" → 全表返回;"x'; DROP TABLE users; --" → 任意执行
# 正确:参数化——数据永远是数据cursor.execute("SELECT * FROM users WHERE name = %s", (name,))注入的根治是参数化,不是过滤:
- 参数化查询(prepared statement):SQL 结构与数据分离——数据永远是数据,这是唯一根治;
- 过滤/转义是补丁:黑名单遗漏、编码绕过——作为纵深可以,作为防线不够;
- 最小权限的数据库账号:应用账号不给 DROP/FILE 权限——注入的爆炸半径控制(→ 认证与授权)。
同样的边界问题在每种"解释器"前重现:命令注入(shell 拼接)、模板注入(SSTI)、LDAP/XPath 注入——根治都是结构化参数或 API,不是字符串拼接。
XSS:浏览器里的注入
Section titled “XSS:浏览器里的注入”跨站脚本(XSS):不可信数据进入浏览器执行的代码(HTML/JS)——"把数据当成了前端代码"。三类:
| 类型 | 注入点 | 特点 |
|---|---|---|
| 存储型 | 服务器存下的恶意内容(评论、简介) | 每个访问者都中,危害最大 |
| 反射型 | URL 参数回显进页面 | 钓鱼链接诱导 |
| DOM 型 | 前端 JS 处理不可信数据(innerHTML) | 不经过服务器 |
XSS 的后果:以受害者身份执行任意操作(读 Cookie/令牌、发请求、改页面)——比 SQL 注入更贴近"完全接管"(受害者是活着的用户)。
- 输出编码:进入 HTML/属性/JS/URL 各有各的编码——上下文敏感(HTML 实体 ≠ JS 转义 ≠ URL 编码);
- 模板引擎默认转义 + 别用
innerHTML/dangerouslySetInnerHTML塞不可信内容; - HttpOnly Cookie:JS 读不到会话 Cookie——令牌窃取的主路径被切断;
- CSP(内容安全策略):CSP 是 XSS 的纵深防御——白名单脚本来源、禁内联脚本:编码被绕过时,注入的脚本也执行不了。
同源策略与 CORS
Section titled “同源策略与 CORS”同源策略(SOP)是浏览器安全的基石:不同源(协议+域+端口)的脚本不能读彼此的数据——evil.com 的 JS 不能读 bank.com 的响应。它隔离的是读取,不是发送(跨站请求可以发出去,见 CSRF)。
CORS 是放宽同源策略的受控机制——不是"安全开关",是"显式允许":
- 服务器返回
Access-Control-Allow-Origin声明允许的源; - 预检(preflight):非简单请求先发 OPTIONS 问许可;
- 凭据模式:带 Cookie 的跨站请求要求显式
Allow-Credentials+ 非通配源。
常见错误:Access-Control-Allow-Origin: * 配合凭据(浏览器会拒绝,但代理/自写客户端会漏);用 CORS"隐藏" API(它不保护——非浏览器客户端不受 SOP 约束)。服务端授权校验才是防线,CORS 只是浏览器的规则。
CSRF:借你的身份发请求
Section titled “CSRF:借你的身份发请求”跨站请求伪造(CSRF):利用"浏览器自动带 Cookie"——evil.com 的页面发一个 <img src="https://bank.com/transfer?to=attacker&amount=100">,浏览器带着你在 bank.com 的 Cookie 发出,服务器以为是本人操作。
同源策略不防 CSRF:SOP 不让 evil.com 读响应,但请求已经发出去了(副作用已发生)。
防御:
- CSRF token:表单带随机令牌,服务端校验——跨站拿不到令牌;
- SameSite Cookie(
Lax/Strict):跨站请求不带 Cookie——现代浏览器默认 Lax,已挡住大半; - 校验 Origin/Referer 头;
- GET 无副作用:改变状态的请求用 POST + token(GET 被 img/link 触发)。
点击劫持(clickjacking):透明 iframe 叠在诱饵上——受害者点击"领奖",实际点的是"授权/删除"。防御:X-Frame-Options: DENY / CSP frame-ancestors(禁止被嵌入 iframe)。
| 漏洞 | 边界被破坏的地方 | 根治 |
|---|---|---|
| SQL 注入 | 数据 → SQL 代码 | 参数化 |
| XSS | 数据 → 浏览器代码 | 输出编码 + CSP |
| 命令注入 | 数据 → shell 代码 | 结构化 exec |
| 模板注入 | 数据 → 模板代码 | 数据与模板分离 |
漏洞几乎都源于把不可信数据当成了代码——审查任何新接口时问一句:"这条数据流到解释器/执行器那里了吗?边界在哪里?"
- 共同主题:数据与代码的边界;注入的根治是参数化,不是过滤
- XSS 三类(存储/反射/DOM);防御 = 输出编码(上下文敏感)+ HttpOnly + CSP 纵深
- 同源策略是浏览器安全的基石;CORS 是受控放宽,不是防线
- CSRF 利用浏览器自动带 Cookie;防御 = SameSite + token + GET 无副作用
- 点击劫持靠 frame-ancestors 防御