攻击原理与前提
CSRF 攻击之所以成立,依赖于 Web 浏览器的两项默认行为:
浏览器自动携带 Cookie。HTTP 是无状态协议,服务端通过 Cookie 中的 Session ID 识别用户身份。浏览器在发出请求时,会自动附加目标域名下存储的所有 Cookie——无论请求是从目标站点自身发出,还是从第三方域的页面中发出。攻击者利用这一点,在恶意页面中嵌入一个指向目标站点的表单或 AJAX 请求,当受害者打开该页面时,浏览器「忠实」地携带目标站点的 Cookie 发出请求,服务端看到合法 Session 便照单执行。
攻击者无需读取响应。由于浏览器的同源策略(Same-Origin Policy)阻止跨域读取响应内容,CSRF 属于「盲攻击」——攻击者不知道请求被执行后的具体结果。但这对攻击者无关紧要:如果目标是修改受害者的密码,攻击者不需要看到「密码修改成功」的页面,操作已经在服务端生效。
CSRF 攻击的必要前提:
- 受害者在目标网站上拥有有效的认证会话(已登录)。
- 目标网站存在可通过固定请求触发的状态变更操作(转账、修改密码、修改绑定邮箱等)。
- 目标网站未实施 CSRF 防护(无 Token 校验、未校验 Origin/Referer、Cookie 未设置 SameSite 属性)。
典型的 CSRF 攻击载荷可以是一个自动提交的隐藏表单,或一个通过 <img> 标签触发 GET 请求(仅适用于错误地将状态变更操作暴露为 GET 的端点)。
防御机制详解
CSRF 有三层递进的防御手段,通常建议多层叠加使用:
第一层:Anti-CSRF Token(同步器令牌模式)
服务端为每个用户会话或每个表单生成一个不可预测的随机令牌(Token),嵌入表单的隐藏字段或自定义 HTTP 请求头中。提交时服务端验证 Token 是否与会话匹配。攻击者无法从第三方域读取目标站点的页面内容(同源策略),因此无法获取有效的 Token——这是 CSRF 防御最核心的密码学基础。
Token 必须具有以下特性:每次请求唯一(或每会话唯一)、足够的熵(避免暴力猜测)、与用户会话绑定。OWASP 推荐使用加密强度的随机数生成器(如 Java 的 SecureRandom、Node.js 的 crypto.randomBytes)。