SSRF

SSRF

一、介绍SSRF漏洞

SSRF (Server-Side Request Forgery,服务器端请求伪造)是一种由攻击者构造请求,由服务端发起请求,由服务端发起请求的安全漏洞。一般情况下,SSRF攻击的目标是外网无法访问的内部系统(正因为请求是由服务端发起的,所以服务端能请求到与自身相连而与外网隔离的内部系统)。

二、SSRF漏洞原理

SSRF的形成大多是由于服务端提供了从其他服务器应用获取数据的功能且没有对目标地址做过滤与限制。例如黑客操作服务端从指定URL地址获取网页文本内容,加载指定地址的图片等,利用的是服务端的请求伪造。SSRF利用存在缺陷的Web

应用作为代理攻击远程和本地的服务器。
主要攻击方式如下所示。

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

三、引发SSRF的函数

  • file_get_contents()
  • fsockopen()
  • curl_exec()
  • fopen()
  • readfile()

(1) file_get_contents()

<?php $url = $_GET['url'];; echo file_get_contents($url); ?>

file_get_content函数从用户指定的url获取内容,然后指定一个文件名j进行保存,并展示给用户。file_put_content函数把一个字符串写入文件中。

(2) fsockopen()

<?php function GetFile($host,$port,$link) { $fp = fsockopen($host, intval($port), $errno, $errstr, 30); if (!$fp) { echo "$errstr (error number $errno) \n"; } else { $out = "GET $link HTTP/1.1\r\n"; $out .= "Host: $host\r\n"; $out .= "Connection: Close\r\n\r\n"; $out .= "\r\n"; fwrite($fp, $out); $contents=''; while (!feof($fp)) { $contents.= fgets($fp, 1024); } fclose($fp); return $contents; } } ?>

fsockopen函数实现对用户指定url数据的获取,该函数使用socket(端口)跟服务器建立tcp连接,传输数据。变量host为主机名,port为端口,errstr表示错误信息将以字符串的信息返回,30为时限

(3) curl_exec()

<?php if (isset($_POST['url'])){ $link = $_POST['url']; $curlobj = curl_init();// 创建新的 cURL 资源 curl_setopt($curlobj, CURLOPT_POST, 0); curl_setopt($curlobj,CURLOPT_URL,$link); curl_setopt($curlobj, CURLOPT_RETURNTRANSFER, 1);// 设置 URL 和相应的选项 $result=curl_exec($curlobj);// 抓取 URL 并把它传递给浏览器 curl_close($curlobj);// 关闭 cURL 资源,并且释放系统资源 $filename = './curled/'.rand().'.txt'; file_put_contents($filename, $result); echo $result; } ?>

curl_exec函数用于执行指定的cURL会话

注意:

1.一般情况下PHP不会开启fopen的gopher wrapper 2.file_get_contents的gopher协议不能URL编码 3.file_get_contents关于Gopher的302跳转会出现bug,导致利用失败 4.curl/libcurl 7.43 上gopher协议存在bug(%00截断) 经测试7.49 可用 5.curl_exec() //默认不跟踪跳转, 6.file_get_contents() // file_get_contents支持php://input协议

四、SSRF漏洞验证方式

  1. 排除法

浏览器f12查看源代码看是否在本地进行了请求

比如,该资源地址类型为http://www.xxx.com/a.php?image=URL,URL参数若是其他服务器地址就可能存在SSRF漏洞

  1. DNSlog等工具进行测试

看是否被访问(可以在盲打后台,用例中将当前准备请求的URL和参数编成base64,这样盲打后台解码后就知道是哪台机器哪个cgi触发的请求)

  1. 抓包分析

抓包分析发送的请求是不是通过服务器发送的,如果不是客户端发出的请求,则有可能是存在漏洞。接着找存在HTTP服务的内网地址

  • 从漏洞平台的历史漏洞寻找泄露的存在web应用内网地址
  • 通过二级域名暴力猜解工具模糊猜测内网地址
  • 通过file协议读取内网信息获取相关地址
  1. 直接返回的Banner、tittle、content等信息

  2. 留意布尔型SSRF,通过判断两次不同请求结果的差异来判断是否存在SSRF,类似布尔型sql盲注方法

五、常见利用方式

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

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

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

  • http/s:探测内网主机存活

伪协议读取文件

伪协议读取文件,在SSRF中常用的伪协议就是file:///协议

/?url=file:///var/www/html/flag.php

内网访问

我们从目标主机内网环境访问其本地的flag.php

/?url=http://127.0.0.1/flag.php

端口扫描

在SSRF中,dict协议与http协议可用来探测内网的主机存活与端口开放情况。

Dict(DICT)协议是一种用于访问网络上的词典和字典数据库的协议。Dict 协议默认使用TCP连接,服务器端监听TCP端口号2628。

可以利用BP的爆破模块,也可以用python写脚本来进行端口爆破扫描

Gopher协议

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

可以攻击内网的 FTP、Telnet、Redis、Memcache,也可以进行 GET、POST 请求,还可以攻击内网未授权MySQL。

curl是支持gopher协议的,所以这也是curl_exec()容易出现漏洞的地方

gopher协议的格式:gopher://IP:port/_TCP/IP数据流

GET请求

GET/flag.php HTTP/1.1 Host: 127.0.0.1

POST请求

POST /flag.php HTTP/1.1 Host: 127.0.0.1 Content-Type: application/x-www-form-urlencoded Content-Length: 36 key=3e0d2cb7daa9987bb95eab15605f71d7

有四个参数为必要参数

Content-Type,Content-Length,host和POST内容

注意:Content-Length和POST的参数长度必须一致

在gopher协议中发送HTTP的数据,需要以下三步:

  1. 构造HTTP数据包
  2. URL编码、替换回车换行为%0d%0a
  3. 发送gopher协议

注意:

  1. 问号(?)需要转码为URL编码,也就是%3f
  2. 回车换行要变为%0d%0a,但如果直接用工具转,可能只会有%0a
  3. 在HTTP包的最后要加%0d%0a,代表消息结束(具体可研究HTTP包结束)
  4. 编码之后+协议+IP+_ _的作用是防止接收到的第一个字母被吞,具体为什么被吞,就不到了(演示可看下面的文章)

补充:这里查了一下需要三次编码的原因,大概是 Gopher 协议将 URL 解析为 hostname:port/selector 的格式,其中 hostname、port 和 selector 都需要进行编码。URL编码的次数主要取决于你请求的次数,比如你直接POST请求算一次。

Fast CGI协议

如果目标服务器使用的是php,并且存在ssrf,那么就可以构造FastCGI请求报文,直接让php解析服务进行解析,进而执行任意代码

利用条件:

  • libcurl版本>=7.45.0
  • PHP-FPM监听端口
  • PHP-FPM版本 >= 5.3.3
  • 知道服务器上任意一个php文件的绝对路径

CGI全称”通用网关接口”(Common Gateway Interface),用于HTTP服务器与其它机器上的程序服务通信交流的一种工具,CGI程序须运行在网络服务器上。 传统CGI接口方式的主要缺点是性能较差,因为每次HTTP服务器遇到动态程序时都需要重启解析器来执行解析,然后结果被返回给HTTP服务器。这在处理高并发访问几乎是不可用的,因此就诞生了FastCGI。另外传统的CGI接口方式安全性也很差。 FastCGI是一个可伸缩地、高速地在HTTP服务器和动态脚本语言间通信的接口(FastCGI接口在Linux下是socket(可以是文件socket,也可以是ip socket)),主要优点是把动态语言和HTTP服务器分离开来。多数流行的HTTP服务器都支持FastCGI,包括Apache、Nginx和lightpd。 同时,FastCGI也被许多脚本语言所支持,比较流行的脚本语言之一为PHP。FastCGI接口方式采用C/S架构,可以将HTTP服务器和脚本解析服务器分开,同时在脚本解析服务器上启动一个或多个脚本解析守护进程。当HTTP服务器每次遇到动态程序时,可以将其直接交付给FastCGI进程执行,然后将得到的结构返回给浏览器。这种方式可以让HTTP服务器专一地处理静态请求或者将动态脚本服务器的结果返回给客户端,这在很大程度上提高了整个应用系统的性能。

Dict协议

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

dict://xxxxx:port/info(探测端口和版本信息)

dict返回的指纹信息判断开启的服务 , 结合端口探测内网服务

Redis协议(看不懂)

推荐文章:浅析Redis中SSRF的利用

redis的数据包转换字符串

转换规则如下:

如果第一个字符是>或者<那么丢弃该行字符串,表示请求和返回的时间。

如果前3个字符是+OK 那么丢弃该行字符串,表示返回的字符串。

将r字符串替换成%0d%0a

空白行替换为%0a

结合gopher协议攻击内网redis,使用上边捕获数据的转换结果即可,然后进行反弹shell(192.168.1.4是存在redis未授权访问漏洞的服务器):

利用方式

  1. 绝对路径写webshell
  2. 写ssh公钥
  3. 写contrab计划任务反弹shell

gopherus谁用谁说好

该工具的攻击范围:

  1. MySQL (Port-3306)
  2. PostgreSQL(Port-5432)
  3. FastCGI (Port-9000)
  4. Memcached (Port-11211)
  5. Redis (Port-6379)
  6. Zabbix (Port-10050)
  7. SMTP (Port-25)

六、SSRF漏洞绕过方法

常用绕过方法

  1. @ http://abc.com@127.0.0.1
  2. 添加端口号 http://127.0.0.1:8080
  3. 短地址 https://0x9.me/cuGfD

推荐:http://tool.chinaz.com/tools/dwz.aspx、https://dwz.cn/

  1. 可以指向任意ip的域名 xip.io

原理是DNS解析。xip.io可以指向任意域名,即127.0.0.1.xip.io,可解析为127.0.0.1

  1. ip地址转换成进制来访问 192.168.0.1=3232235521(十进制)

  2. 非HTTP协议

  3. DNS Rebinding https://lock.cmpxchg8b.com/rebinder.html

  4. 利用[::]绕过 http://[::]:80/ >>> http://127.0.0.1

  5. 句号绕过 127。0。0。1 >>> 127.0.0.1

  6. 利用302跳转绕过

使用[https://tinyurl.com]生成302跳转地址

常见限制

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

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

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

服务器有可能禁止了127.0.0.1的地址,来防御内网探测,可以使用一些不同的进制替代ip地址,从而绕过WAF

利用进制的转换

127.0.0.1:八进制:0177.0.0.1 十六进制:0x7f.0.0.1 十进制:2130706433

利用其他各种指向127.0.0.1的地址

http://localhost/ http://0/ http://[0:0:0:0:0:ffff:127.0.0.1]/ http://①②⑦.⓪.⓪.①
  • 限制请求只为http协议

(1)采取302跳转

(2)采取短地址

302重定向又称之为暂时性转移(Temporarily Moved ),英文名称:302 redirect。 也被认为是暂时重定向(temporary redirect),一条对网站浏览器的指令来显示浏览器被要求显示的不同的URL,当一个网页经历过短期的URL的变化时使用。

可以用BP拦截请求访问

可以用curl命令直接访问

因为BP和curl命令都不会跟随302跳转

  • DNS重绑定

要完成DNS重绑定攻击,我们需要一个域名,并且将这个域名的解析指定到我们自己的DNS Server,在我们的可控的DNS Server上编写解析服务,设置TTL时间为0。

https://lock.cmpxchg8b.com/rebinder.html

补充:做题时遇到的解法

url=http://sudo.cc/flag.php http://safe.taobao.com/ http://wifi.aliyun.com/ http://ecd.tencent.com/

网上存在一个名为 sudo.cc 的服务,当访问该服务时会自动重定向到127.0.0.1,这个方法可以在过滤localhost或127.0.0.1时使用


__EOF__

本文作者Solitude
本文链接https://www.cnblogs.com/solitude0-c/p/17561986.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   Solitude0c  阅读(74)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
点击右上角即可分享
微信分享提示