SSRF漏洞(Server-Side Request Forgery)
1. 定义与原理
SSRF(服务端请求伪造) 是一种安全漏洞,攻击者通过构造恶意请求,诱使服务器向非预期的目标发起网络请求。其核心原理是服务端未对用户输入的URL进行充分校验和过滤,导致服务器成为攻击者的“代理”,访问内部系统、第三方服务或敏感资源。
2. 漏洞分类
- 按照是否回显分:
- 回显型(Reflective SSRF):服务器将请求结果返回给客户端,攻击者可直接查看响应(如读取本地文件、访问元数据)。
- Basic SSRF:在响应中返回结果。如传送一个网址,会返回这个网址的界面或对应的 html 代码。
- 非回显型(Blind SSRF):服务器不返回响应,但攻击者可通过延迟、DNS查询或错误信息间接推断请求结果。
- Semi SSRF:响应中不返回请求结果的所有详细信息,但是会暴露一些数据信息。
- 按照程序语言分类:
- PHP SSRF
- Java SSRF
- ASPX SSRF
- Python SSRF
- Golang SSRF
3. 攻击场景与危害
- 访问内部服务:
- 云环境元数据泄露(如AWS的169.254.169.254、阿里云100.100.100.200)。
- 扫描内网端口和服务(如Redis、MySQL未授权访问)。
- 绕过安全机制:
- 利用服务器IP绕过IP白名单或身份验证。
- 攻击外部系统(如通过服务器发起DDoS或攻击第三方API)。
- 协议滥用:
- 使用file://协议读取服务器本地文件。
- 利用gopher://或dict://协议与TCP服务交互(如攻击Redis主从复制)。
4. 利用技巧与绕过方法
- 协议混淆:
- 使用非HTTP协议(如file:///etc/passwd、gopher://构造Redis命令)。
- 利用URL编码或特殊符号绕过黑名单(如http://127.0.0.1@evil.com)。
- IP表示绕过:
- 十进制IP(如2130706433代表127.0.0.1)。
- IPv6缩写(如[::]等效localhost)。
- 解析差异:
- 不同编程语言/库对URL的解析不一致(如PHP的parse_url与Python的urllib)。
- 重定向利用:
- 通过第三方服务(如GitHub Pages)重定向到内网地址。
- DNS重绑定技术(动态切换域名解析IP绕过校验)。
5. 经典案例
- Capital One数据泄露(2019):
攻击者利用SSRF访问AWS元数据服务,获取临时凭证,最终窃取1亿用户数据。 - Discord图片代理SSRF:
攻击者通过上传特定URL触发服务器访问内部服务,导致敏感信息泄露。 - 企业内网渗透:
通过SSRF扫描内网Redis服务,利用未授权访问漏洞植入后门。
6. 防御策略
- 输入校验:
- 白名单限制协议(仅允许HTTP/HTTPS)。
- 禁止访问内网IP段(如127.0.0.0/8、10.0.0.0/8)。
- 校验域名归属(防止DNS重绑定)。
- 安全配置:
- 禁用危险协议(如file://、gopher://)。
- 使用代理服务器并限制出站流量(仅允许访问必要的外部服务)。
- 服务端加固:
- 过滤响应敏感头(如Authorization、Cookie)。
- 避免返回原始错误信息(防止泄露内部IP/端口)。
- 网络隔离:
- 云服务器配置安全组限制元数据访问。
- 内网服务设置双向认证(如mTLS)。
7. 检测与工具
- 手动测试:
- 尝试输入file:///etc/passwd、http://169.254.169.254。
- 使用Burp Collaborator检测Blind SSRF。
- 自动化工具:
- SSRFmap:自动化探测和利用SSRF。
- Gopherus:生成攻击Redis、MySQL等的Payload。
- 代码审计:
- 检查网络请求函数(如curl、requests.get)是否直接使用用户输入。
8. 与其他漏洞结合
- XXE(XML外部实体注入):
- 通过XXE触发SSRF(如<!ENTITY xxe SYSTEM "http://internal">)。
- SQL注入:
- 若内网服务存在SQL注入,SSRF可间接触发攻击。
- RCE(远程代码执行):
- 通过SSRF访问控制台接口(如Jenkins脚本执行)。
9. 进阶绕过技术
- DNS重绑定:
攻击者控制域名在短时间内解析为内网IP,绕过服务端IP校验。 - 分段URL攻击:
利用http://foo@evil.com:80@internal.com混淆解析。 - Unicode编码:
使用ⓔⓧⓐⓜⓟⓛⓔ.ⓒⓞⓜ绕过域名黑名单。
10. 云环境下的特殊风险
- 元数据服务:
- AWS、Azure、GCP等均提供元数据API,泄露可能导致临时凭证被盗。
- Serverless架构:
- 函数计算(如AWS Lambda)若存在SSRF,可能访问云账户资源。
11. 总结
SSRF的防御需要多层次策略:从输入校验到网络隔离,从协议限制到响应过滤。开发者需警惕所有用户可控的URL参数,安全团队应定期演练应急响应流程,确保在漏洞被利用前及时修复。
SSRF漏洞的常用伪协议和攻击手法
1. 文件协议(file://)
攻击者可以利用 file:// 协议让目标服务器读取本地文件。例如,通过访问 file:///etc/passwd 可以获取目标系统的敏感文件内容。
2. 内部网络访问
服务器通常无法访问外部的资源,但可能允许向内网发起请求。攻击者可以利用这一点访问内部服务或接口:
- http://127.0.0.1/ 或 http://localhost/ 尝试访问本地服务。
- http://169.254.169.254/ 如果服务器在云环境中,可能尝试访问云平台的元数据服务,如 AWS 或 GCP 等的实例元数据。
- http://localhost:9200/ 访问本地 Elasticsearch 服务。
- http://172.16.0.1/ 内网地址,攻击者可能探测服务器连接的内网服务。
3. 端口扫描
SSRF 可以用来扫描目标服务器的开放端口。如果服务器允许向任意 IP 发起请求,攻击者可以通过伪造 URL(如 http://127.0.0.1:8080/) 来检查服务是否运行在特定端口。
4. DNS协议
SSRF 攻击也可以通过利用 DNS 请求来泄漏内部网络信息或绕过访问控制。攻击者可以利用 Example Domain 的域名解析查询来实现。
5. Gopher 协议(gopher://)
gopher:// 是一种老旧的协议,它可以被用来通过目标服务器向内网或其他服务发送请求,可能用于读取文件或访问其他协议。
6. HTTP 请求中的特殊字符
攻击者可以在 URL 中注入特殊字符来改变请求的目的地。例如,使用 %0A(换行符)来注入新的头部字段,或者使用 %0D(回车符)来插入额外的请求头,可能用来绕过安全防护。
7. HTTP Host 头攻击
攻击者通过篡改 HTTP 请求中的 Host 头,使得目标服务器向恶意服务器发起请求。例如,攻击者可以把 Host 头设置为内网地址,诱使目标服务器请求内部服务。
8. TCP/UDP 包操作
如果服务器允许对外的 TCP 或 UDP 请求,攻击者可以尝试向任意 IP 或端口发起请求,利用 SSRF 绕过防火墙等防护措施。
防御建议:
- 对用户输入进行严格的过滤,限制只允许访问白名单中的服务。
- 对外部请求进行严格的协议限制,防止使用不安全的协议(如 file://, gopher:// 等)。
- 禁用对本地或内部资源(如 localhost、127.0.0.1、169.254.169.254 等)的访问。
- 使用防火墙、网关、代理等手段限制内部服务暴露给外部网络。
- 日志监控和检测异常的外部请求模式,以便及时发现和响应。
SSRF漏洞靶场
SSRF(curl)
1,观察靶场,有一个超链接允许我访问网站外部资源
观察页面源代码也是如此吗,并且使用了php的curl函数
在 PHP 中,cURL 是一种非常常用的库,用于通过各种协议(如 HTTP、HTTPS、FTP 等)发送请求和接收响应。它提供了非常强大的功能,可以通过 HTTP 请求与其他服务器进行通信。
2,点击超链接,就会跳转到其他页面,,并且观察URL栏直接拼接了目标网页的地址
3,那么我们就可以利用PHP伪协议,构造payload去达到攻击者想要的目的
payload:http://192.168.23.154/06/vul/ssrf/ssrf_curl.php?url=file:///etc/passwd
成功读取到了记录敏感信息的文件
因为curl_exec滥用导致了该靶场存在SSRF漏洞,通过漏洞可以做到:
1、通过网址访问链接比如说修改url为:url=http://www.baidu.com,访问百度页面:
2,通过file://协议获取靶机本地文件资源
3、dict:// 协议扫描内网主机开放端口
- 基本概念:
dict:// 是一种用于访问字典协议的网络协议(通常用于文字或短语的查找)。在一些情况下,dict:// 协议可能被某些 Web 应用程序的输入字段支持,尤其是未严格限制协议的应用程序。攻击者可以通过这种方式利用 SSRF 漏洞来探测内部网络或获取敏感信息。 - 扫描内网开放端口的方式:
- 攻击者首先会构造包含内网主机和端口号的 dict:// 请求。
- 通过对目标应用的 SSRF 漏洞进行暴力或字典式攻击,攻击者会尝试访问多个内网 IP 地址和端口,以探测哪些端口是开放的。
- 攻击流程:
- 步骤 1:通过 SSRF 漏洞向服务器发送包含 dict:// 协议的请求。例如,攻击者可以构造如下 URL:
dict://127.0.0.1:80
dict://192.168.1.1:22
dict://10.0.0.1:443 - 步骤 2:这些请求会通过目标服务器发起。如果目标应用没有限制访问内部网络资源,服务器就会尝试访问这些端口。
- 步骤 3:通过对多个主机和端口组合的不断扫描,攻击者可以收集哪些端口开放的响应。通常,成功连接的端口将返回响应,而失败的请求会超时或返回错误。
- 步骤 1:通过 SSRF 漏洞向服务器发送包含 dict:// 协议的请求。例如,攻击者可以构造如下 URL:
阅读靶场源代码
代码结构和漏洞点
- 接收用户输入的 URL
if(isset($_GET['url']) && $_GET['url'] != null){ |
- $_GET['url'] 是一个由用户提供的 URL 输入。代码并没有对输入 URL 进行有效的验证或过滤,直接将用户输入的 URL 传递给 curl_exec() 函数执行。
- 如果没有对 URL 进行严格检查,攻击者就可以通过修改 url 参数来让服务器发起任意请求(例如,访问本地文件、内网服务,或者发起外部的恶意请求)。
- 通过 curl_exec() 执行用户输入的 URL
$CH = curl_init($URL); |
- 使用 curl_exec() 执行来自用户输入的 URL,返回结果并直接输出。
- curl_exec() 会向服务器发起网络请求,而攻击者通过伪造 url 参数可以使服务器请求到攻击者想要访问的任何资源。这是典型的 SSRF 漏洞。
- 漏洞分析
- 攻击者利用 SSRF 漏洞:攻击者可以通过访问该页面并在 url 参数中传递恶意的 URL(如 file://、http://127.0.0.1:8080 等),使服务器发起恶意请求。
- 内网服务访问:如果服务器能够访问内网资源,攻击者可以使用该漏洞扫描内网的服务,进行端口扫描等。
- 文件读取:如果攻击者通过传递如 file:///etc/passwd 这样的 URL,可以让服务器读取并返回文件内容。
- 远程服务攻击:攻击者还可以通过 http:// 或 ftp:// 等协议访问其他服务器,可能会进一步扩展攻击面。
- 攻击者利用 SSRF 漏洞:攻击者可以通过访问该页面并在 url 参数中传递恶意的 URL(如 file://、http://127.0.0.1:8080 等),使服务器发起恶意请求。
SSRF(file_get_contant)
1,观察一下靶场,该靶场应该和file_get_contant函数有关
file_get_contents() 把整个文件读入一个字符串中。
该函数是用于把文件的内容读入到一个字符串中的首选方法。如果服务器操作系统支持,还会使用内存映射技术来增强性能。
语法
file_get_contents(path,include_path,context,start,max_length)
参数 | 描述 |
path | 必需。规定要读取的文件。 |
include_path | 可选。如果您还想在 include_path(在 php.ini 中)中搜索文件的话,请设置该参数为 '1'。 |
context | 可选。规定文件句柄的环境。context 是一套可以修改流的行为的选项。若使用 NULL,则忽略。 |
start | 可选。规定在文件中开始读取的位置。该参数是 PHP 5.1 中新增的。 |
max_length | 可选。规定读取的字节数。该参数是 PHP 5.1 中新增的。 |
2,点击一下超链接,访问的资源依然被拼接到了URL栏当中
3,file读取本地文件
payload为:file=file:///etc/passwd,查看文件的内容:
4,http协议请求内网资源
payload为:file=http://127.0.0.1/06/vul/sqli/sqli.php,查看内网资源的内容
阅读靶场源代码
代码功能概述
- 接收用户输入的文件路径:
if(isset($_GET['file']) && $_GET['file'] != null){ |
- 代码通过 $_GET['file'] 参数接收一个文件路径,并使用 file_get_contents() 函数读取该文件的内容。
- file_get_contents() 函数不仅可以读取本地文件,也可以用于通过 URL 读取远程资源(包括 HTTP 和其他协议)。
file_get_contents() 函数的安全隐患:
- file_get_contents() 函数默认支持读取 URL,包括 http://、ftp://、file:// 等协议。如果没有对输入的 URL 进行严格的过滤或验证,攻击者就可以利用这个特性发起 SSRF 攻击。
- 服务器不仅能够读取本地文件,还可以通过 file:// 访问本地资源,或者通过 HTTP 协议访问内网服务、外部恶意服务器等。