前端安全中最常见的两种攻击类型:XSS(跨站脚本攻击)和 XSRF(跨站请求伪造)。了解攻击原理和防御措施,是前端开发的安全底线。
XSS(跨站脚本攻击)
原理
攻击者在目标网站上注入恶意脚本。典型攻击链:
- 用户在博客评论区输入
<script>恶意代码</script> - 网站未做过滤,直接将这段内容渲染到页面
- 其他用户访问时,恶意脚本在浏览器中执行
攻击目标:获取 cookie → 发送到攻击者服务器(配合跨域)→ 冒充用户登录
XSS 的三种类型
| 类型 | 说明 | 场景 |
|---|---|---|
| 存储型 | 恶意脚本被存到数据库,每次访问页面都执行 | 评论、留言板 |
| 反射型 | 恶意脚本在 URL 参数中,点击恶意链接触发 | 搜索结果页、错误提示页 |
| DOM 型 | 纯前端漏洞,通过修改 DOM 注入 | innerHTML、document.write |
防御
核心思路:转义特殊字符,让脚本代码变成不可执行的纯文本。
< → <
> → >
" → "
' → ' (或 ')
& → &
输入:<script>alert('xss')</script>
转义:<script>alert('xss')</script>
显示:<script>alert('xss')</script> ← 纯文本,不执行
必须前后端都做转义:
- 前端:提交时转义,使用
textContent(自动转义)代替innerHTML;必须用innerHTML时用DOMPurify等库做净化;React 的 JSX 自动转义了{}中的内容 - 后端:存入数据库前或输出到 HTML 时转义
其他防御手段:
- CSP(Content Security Policy):通过 HTTP 头或
<meta>标签限制可执行的脚本来源Content-Security-Policy: script-src 'self'; object-src 'none' - HttpOnly Cookie:禁止 JS 读取 cookie,即使 XSS 成功也无法窃取敏感 cookie
- 输入验证:前端验证体验,后端验证安全——所有输入都要在后端做二次校验
XSRF(跨站请求伪造)
原理
利用用户在 A 网站已登录的身份,在用户不知情时发起恶意请求:
- 用户登录了 A 网站(浏览器存有有效的 cookie)
- 攻击者向用户发送邮件,邮件中隐藏
<img src="https://A.com/pay?id=200"> - 用户打开邮件,浏览器自动对 A 发起请求,携带 cookie
- 服务端以为这是合法用户的操作
防御
| 措施 | 说明 |
|---|---|
| 关键操作用 POST | GET 请求容易通过 <img>、<script> 标签触发。但 POST 也不绝对安全——<form> 也可以跨域 POST |
| CSRF Token | 服务端生成随机 token,嵌入页面表单。每次请求必须携带,服务端校验。攻击者无法获取到 token |
| SameSite Cookie | SameSite=Strict:完全禁止跨站请求携带 cookie。SameSite=Lax:仅顶级导航(如链接跳转)携带,<img> 和 iframe 不携带 |
| 验证 Referer/Origin | 检查请求头中的 Origin 或 Referer 是否来自受信任的域名 |
| 二次验证 | 敏感操作(支付、修改密码)要求输入密码、短信验证码或生物识别 |
| 自定义 Header | 添加自定义请求头(如 X-Requested-With: XMLHttpRequest),服务端校验。简单跨域请求无法携带自定义头 |
防御 XSRF 时,
SameSite=Lax(Chrome 的默认值)覆盖了 90% 的场景。结合 CSRF Token 可以进一步加固。
XSS 与 XSRF 对比
| 维度 | XSS | XSRF |
|---|---|---|
| 攻击目标 | 窃取用户信息 / 执行恶意脚本 | 冒充用户执行操作 |
| 利用手段 | 注入脚本代码 | 伪造跨站请求 |
| 依赖条件 | 输入过滤不严 | 用户已登录 + 无请求验证 |
| 防御核心 | 转义特殊字符 + CSP | CSRF Token + SameSite Cookie |
| 攻击影响域 | 当前页面(可跨域发送数据) | 当前域(利用同源 cookie) |