Web安全实习: 跨站请求伪造 (CSRF) 😱🛡️
Source: Dev.to
引言
大家好,亲爱的同学们!欢迎来到关于 Cross‑Site Request Forgery (CSRF) 的实践课程,这是最狡猾的网络攻击之一。想象一下,你正在登录网银,然后打开另一个标签页访问恶意网站。你不知情的情况下,恶意网站可以“强迫”你的浏览器向银行发送请求,将钱转给黑客,而你并没有点击任何东西。这是因为浏览器会自动在向其他域发送请求时附带身份验证 cookie。
CSRF 是 伪造请求,利用浏览器对会话 cookie 的信任,从其他站点发起请求。
CSRF 工作原理
主要条件
- 用户已登录 – 有有效的会话 cookie。
- 重要操作(例如转账、修改密码、删除账户)使用 GET 或 POST 方法且没有防护。
- 浏览器在每次请求时会自动向原始域发送 cookie。
攻击流程(经典示例)
- 受害者 已登录目标站点后访问恶意站点。
- 恶意站点加载元素(例如图片或隐藏表单),向目标站点发送请求。
- 受害者的浏览器连同会话 cookie 一起发送请求,从而在受害者不知情的情况下执行危险操作。

Source: …
示例漏洞
1. 使用 GET 的银行转账
GET http://bank.com/transfer?jumlah=1000000&rekening_tujuan=12345678 HTTP/1.1
Host: bank.com
Cookie: session=abcd1234
恶意网站 可以插入隐藏图片:

当受害者打开恶意页面时,浏览器会自动向黑客账户发送转账请求。
2. 脆弱表单(POST 未加保护)
<form action="/ubah-email" method="POST">
<input type="email" name="email" value="hacker@example.com">
<button type="submit">Simpan</button>
</form>
恶意网站:
<script>
document.getElementById('jahat').submit();
</script>
打开恶意页面的受害者会自动提交该表单,从而把账户邮箱改为黑客所有。
3. 使用 GET 的 “点赞” 操作
示例请求:GET /post?id=123&action=like。
恶意网站可以添加图片标签:

保护机制
CSRF Token(最常用且强大)
- 服务器 为每个会话或每个表单生成唯一 token。
- Token 作为隐藏字段或自定义 header 放入表单中。
- 服务器 在处理请求前验证 token。
<form action="/simpan" method="POST">
<input type="hidden" name="csrf_token" value="RANDOM_TOKEN">
<button type="submit">Simpan</button>
</form>
如果 token 不匹配或不存在,服务器会拒绝请求。
SameSite Cookie
设置 cookie 时使用 SameSite=Lax 或 SameSite=Strict,使浏览器在跨站请求时 不发送 cookie。
Set-Cookie: session=abcd1234; SameSite=Strict; Secure; HttpOnly
其他最佳实践
- 使用 POST 进行会改变状态的操作,避免使用 GET。
- 双提交 Cookie:将 token 同时作为 cookie 和表单参数发送。
- 利用 框架自带的防护(Laravel、Django、Spring Security 等),它们会自动添加并验证 token。
附加:CSRF vs XSS 🆚
| 方面 | CSRF | XSS |
|---|---|---|
| 目标 | 浏览器对 Cookie 的信任 | 在页面中插入脚本 |
| 工作原理 | 强制使用有效 Cookie 发起请求 | 注入在受害者浏览器中执行的脚本 |
| 常见影响 | 不期望的操作(转账、数据更改) | 数据窃取、会话劫持、页面篡改 |
| 主要缓解措施 | CSRF Token、SameSite Cookie、POST | 输入过滤、CSP、HttpOnly Cookie |
实践与实验
- 在 PHP 中创建易受攻击的转账表单,并使用图片标签测试 CSRF 攻击。
- 添加 手动 CSRF 令牌 并重新测试;请求应当失败。
- 在 PortSwigger Web Security Academy(搜索 “CSRF”)尝试免费实验。
讨论
- 为什么许多银行将 token CSRF 与 OTP 结合使用?
- 如何确保所有状态更改的端点都受到保护?
祝实践愉快!通过了解 CSRF 并实施适当的防护,你的 Web 应用将像银行金库一样安全。始终保护会改变状态的操作,并持续养成安全编码的习惯。 🎉🔐