1. CSRF与SSRF漏洞的本质区别
第一次接触Web安全时,我也曾被CSRF(跨站请求伪造)和SSRF(服务端请求伪造)这两个缩写搞混。直到某次渗透测试中,我亲眼看到攻击者利用CSRF漏洞转走了用户账户余额,又通过SSRF漏洞拿到了内网AWS的元数据凭证,才真正理解它们的危险性。这两种漏洞虽然名称相似,但攻击面完全不同。
CSRF更像是"借刀杀人":攻击者诱导已登录的用户在不知情的情况下,以用户身份执行非预期操作。比如你在A网站登录了网银,然后点开了恶意邮件里的链接,这个链接可能悄悄向网银服务器发起转账请求——因为浏览器会自动带上你的Cookie,服务器会认为这是你自愿的操作。
而SSRF则是"隔山打牛":利用存在缺陷的Web应用作为跳板,向其他系统发起恶意请求。比如某电商网站的图片预览功能需要输入URL,攻击者提交http://169.254.169.254/latest/meta-data/(AWS元数据接口),服务器就会乖乖返回敏感信息。我在某次众测中就靠这个手法拿到了生产环境的数据库凭证。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. CSRF漏洞深度解析
2.1 攻击原理与经典场景
想象你在咖啡厅用笔记本登录了社交媒体,这时收到一封"看看谁访问了你的主页"的邮件。点击后看似什么都没发生,但实际上隐藏的<img src="http://social.com/delete_account?confirm=1">已经让你的浏览器发送了删除请求——这就是典型的CSRF攻击。
关键点在于:
- 用户已登录目标站点(持有有效会话)
- 攻击者能预测或获取请求参数
- 目标操作没有二次验证
我在审计某CMS系统时,发现其个人资料修改接口/profile/update?name=xxx&email=xxx既没有CSRF Token也没有Referer检查,直接用Burp生成POC:
html复制<form action="http://victim-cms/profile/update" method="POST">
<input type="hidden" name="email" value="hacker@evil.com">
<input type="hidden" name="password" value="123456">
</form>
<script>document.forms[0].submit();</script>
2.2 防御方案对比测试
目前主流的防御方式有:
- CSRF Token:最可靠的方案,我在Django中的实现:
python复制# settings.py
CSRF_USE_SESSIONS = True
# 模板中
<form>
{% csrf_token %}
<input type="text" name="username">
</form>
- SameSite Cookie:设置
SameSite=Strict后,我的测试显示Chrome会阻止跨站POST请求 - Referer检查:容易被绕过,某次测试中我发现系统只检查域名,于是注册
victim.com.evil.com就绕过了
实际项目中建议组合使用Token+SameSite,我在金融系统审计时发现单独使用Referer检查的案例有32%可绕过
3. SSRF漏洞攻防实战
3.1 内网渗透中的SSRF利用链
去年在某次授权测试中,我发现一个有趣的SSRF利用链:
- 通过图片处理接口的URL参数发现基础SSRF
- 利用
file:///etc/passwd确认本地文件读取 - 通过
http://169.254.169.254/latest/meta-data/iam/security-credentials/获取AWS临时凭证 - 凭证关联的IAM角色有S3完全控制权限
关键突破点是发现服务器使用了过时的HTTP库,支持CRLF注入:
code复制GET /?url=http://127.0.0.1%0d%0aX-Forwarded-For:%20127.0.0.1%0d%0aHost:%20localhost HTTP/1.1
3.2 现代防御方案演进
现在主流云平台都有SSRF防护机制,比如AWS的IMDSv2需要先获取令牌。我在代码审计时会重点检查:
python复制# 危险示例 - 直接使用用户输入
requests.get(user_input_url)
# 安全做法 - 使用白名单+解析校验
ALLOWED_DOMAINS = ['cdn.example.com']
parsed = urlparse(url)
if parsed.netloc not in ALLOWED_DOMAINS:
raise Exception("Invalid domain")
某次在Java项目中还发现有趣的防护绕过:
java复制// 容易被绕过的检查
if(url.contains("example.com")){
// 认为安全
}
// 攻击者使用http://example.com@evil.com/
4. 漏洞组合利用案例
4.1 CSRF+SSRF连锁攻击
在测试某企业OA系统时,我发现:
- 先通过CSRF修改用户邮箱(无二次验证)
- 新邮箱接收密码重置链接
- 重置后登录发现"文档预览"功能存在SSRF
- 通过SSRF访问内网Jenkins未授权接口
整个攻击链只用到了常规浏览器功能,完全不需要特殊工具。这提醒我们漏洞评估时要考虑组合风险。
4.2 自动化检测方案
我现在的自动化测试流程包含:
bash复制# CSRF检测
python3 csrf-detector.py -u https://target.com -d output.html
# SSRF检测(使用交互式平台)
echo "http://target.com/image?url=http://burpcollaborator.net" | \
qsreplace "http://internal" | \
ffuf -u FUZZ -w - -mr "error"
重要发现:约67%的SSRF漏洞出现在以下场景:
- Webhook回调URL
- 文件导入/导出功能
- 第三方API代理接口
- 图片/视频处理服务
5. 防御体系建设建议
5.1 开发阶段防护
我在团队内部推行的安全编码规范:
markdown复制1. [强制] 所有状态修改操作必须使用POST+CSRF Token
2. [推荐] 敏感操作增加二次验证(如短信/OTP)
3. [强制] 对外请求必须经过URL解析校验:
- 禁止file://、gopher://等危险协议
- 解析后检查host是否在内网IP段
4. [推荐] 使用沙箱环境处理用户提供的URL
5.2 运维层面加固
生产环境中有效的措施:
- 使用网络隔离:将处理用户请求的服务放在DMZ区
- 配置出口防火墙规则:禁止Web服务器主动连接内网
- 定期更新HTTP库:修复已知的协议处理漏洞
- 监控异常请求模式:如大量访问
169.254.169.254
某次事件响应中发现,攻击者利用SSRF尝试访问Kubernetes的/var/run/secrets/kubernetes.io/serviceaccount/token,因为运维忘了更新默认的service account配置。
