SSRF概念 SSRF(Server-Side Request Forgery:服务器端请求伪造) 是一种由攻击者构造请求,由服务端发起请求的安全漏洞。一般情况下,SSRF攻击的目标是外网无法访 问的内部系统(正因为请求是由服务端发起的,所以服务端能请求到与自身相连而与外网隔离的内部系 统)。 很多Web应用都提供了从其他服务器上获取数据的功能。使用用户指定的URL,Web应用可以获取图 片,下载文件,读取文件内容等。这个功能如果被恶意使用,可以利用存在缺陷的web应用作为代理攻 击远程和本地服务器。 由于服务端提供了从其他服务器应用获取数据的功能,但又没有对目标地址做严格过滤与限制,导致攻 击者可以传入任意的地址来让后端服务器对其发起请求,并返回对该目标地址请求的数据。
数据流:攻击者----->服务器---->目标地址
SSRF原理 SSRF形成的原因大都是由于服务端提供了从其他服务器应用获取数据的功能,且没有对目标地址做过滤 与限制。例如,黑客操作服务端从指定URL地址获取网页文本内容,加载指定地址的图片等,利用的是 服务点的请求伪造。SSRF利用存在缺陷的Web应用作为代理攻击远程和本地的服务器。可以使用如下理 解:首先,我们要对目标网站的架构了解,脑子了要有一个架构图。比如 :A网站,是一个所有人都可以访问的外网网站,B网站是一个他们内部的OA网站。
所以,我们普通用户只可以访问a网站,不能访问b网站。但是我们可以同过a网站做中间人,访问b网 站,从而达到攻击b网站需求。
正常用户访问网站的流程是: 输入A网站URL --> 发送请求 --> A服务器接受请求(没有过滤),并处理 -->返回用户响应 如果那网站有个请求是www.xxxx.com/xxx.php?image=URL 那么产生SSRF漏洞的环节在哪里呢?安全的网站应接收请求后,检测请求的合法性 产生的原因:服务器端的验证并没有对其请求获取图片的参数(image=)做出严格的过滤以及限制,导 致A网站可以从其他服务器的获取数据例如:www.xxxx.com/xxx.php?image=www.abc.com/1.jpg 如果我们将www.abc.com/1.jpg换为与该服务器相连的内网服务器地址会产生什么效果呢? 如果存在该内网地址就会返回1xx 2xx 之类的状态码,不存在就会其他的状态码。
总结:SSRF漏洞就是通过篡改获取资源的请求发送给服务器,但是服务器并没有检测这个请求是否合法的,然 后服务器以他的身份来访问其他服务器的资源。
主要的攻击方式(不限于):
- 对外网、服务器所在内网、本地进行端口扫描,获取一些服务的banner信息。
- 攻击运行在内网或本地的应用程序。
- 对内网Web应用进行指纹识别,识别企业内部的资产信息。
- 攻击内外网的web应用,主要是使用HTTP GET请求就可以实现的攻击(比如strust2、SQLi等)。
- 利用file协议读取本地文件等
SSRF利用
利用的协议
主要涉及的协议:http://,file://,dict://,gopher://这四个协议。 SSRF利用存在多种形式以及不同的场景,针对不同场景可以使用不同的利用和绕过方式。 以curl为例, 可以使用dict协议操作Redis、file协议读文件、gopher协议反弹Shell等功能。 curl命令在SSRF漏洞有非常重要的作用,结合协议常见用法:
使用file协议curl -v file:///etc/passwd
使用ftp协议 curl -v "ftp://127.0.0.1:端口/info"
使用dict协议 curl -v "dict://127.0.0.1:端口/info"
使用gopher协议 curl -v "gopher://127.0.0.1:端口/_info"
# -v参数输出通信的整个过程,用于调试。我们便可以利用-v参数进行读取文件
常见内网IP 局域网地址范围分三类,以下IP段为内网IP段:
C类:192.168.0.0 - 192.168.255.255
B类:172.16.0.0 - 172.31.255.255
A类:10.0.0.0 - 10.255.255.255
SSRF利用的步骤
1. http协议进行内网的ip扫描、端口探测
2. file协议进行本地文件的读取
3. 利用gopher/dict 来打探测到的一些服务,最为出名的就是redis服务
PHP的相关函数来利用
根据后台使用的函数的不同,对应的影响和利用方法又有不一样,PHP中下面函数的使用不当会导致 SSRF:
file_get_contents()
fsockopen()
curl_exec()
核心重点掌握curl_exec().
PHP的CURL支持很多协议:FTP, FTPS, HTTP, HTTPS, GOPHER, TELNET, DICT, FILE 以及 LDAP。curl 同样支持HTTPS认证,HTTP POST方法, HTTP PUT方法, FTP上传, kerberos认证, HTTP上传, 代理服务 器, cookies, 用户名/密码认证, 下载文件断点续传, 上载文件断点续传, http代理服务器管道( proxy tunneling), 甚至它还支持IPv6, socks5代理服务器, 通过http代理服务器上传文件到FTP服务器等等, 功能十分强大。
准备代码ssrf.php
<?php
// 获取参数
$url = isset($_GET['url']) ? $_GET['url'] : "";
if ($url){
// 初始化curl
$ch = curl_init();
//设置URL参数
curl_setopt($ch, CURLOPT_URL, $url);
// 设置是否返回响应头
curl_setopt($ch, CURLOPT_HEADER, 0);
// 执行
$result = curl_exec($ch);
// 关闭
curl_close($ch);
}
在写一个info.php 就用来输出:phpinfo()。
<?php
phpinfo();
获取探针
尝试利用ssrf.php来获取php探针信息。
浏览器访问:http://localhost/ssrf/ssrf.php?url=localhost/ssrf/info.php
访问百度
可以尝试将url更改为:www.baidu.com/www.qq.com/www.jd.com
发现ssrf.php替我们去访问了百度。
探测端口
我们尝试看看本地的3306是否开放:
发现如果有对应的服务,那么会有对应的返回值。 这个时候可以结合burp对内网进行一次服务的爆破。大家自行思考。
也可以通过dict协议来探测: dict是什么协议呢? 定义:词典网络协议,在RFC 2009中进行描述。它的目标是超越Webster protocol,并允许客户端在使 用过程中访问更多字典。Dict服务器和客户机使用TCP端口2628。
官方介绍:http://dict.org/rfc2229.txt
利用dict协议可以探测出目标端口的指纹信息,进一步方便我们利用。
获取铭感文件信息可以利用file://协议来读取一些铭感文件:
SSRF防御
1.过滤返回信息,验证远程服务器对请求的响应是比较容易的方法。如果web应用是去获取某一种类型的文件。那么在把返回结果展示给用户之前先验证返回的信息是否符合标准。
2.统一错误信息,避免用户可以根据错误信息来判断远端服务器的端口状态。
3.限制请求的端口为http常用的端口,比如,80,443,8080,8090。
4.黑名单内网ip。避免应用被用来获取获取内网数据,攻击内网。
5.禁用不需要的协议。仅仅允许http和https请求。可以防止类似于file:///,gopher://,ftp:// 等引起的问题