ssrf是一种由攻击者构造请求,由服务端发起请求的安全漏洞。一般情况下,ssrf攻击的目标是外网无法访问的内部系统
ssrf漏洞原理
ssrf的形成大多是由于服务端提供了从其他服务器应用获取数据的功能且没有对目标地址做过滤与限制。例如,服务端从指定URL地址获取网页文本内容,加载指定的图片等,利用的是服务端的请求伪造。SSRF利用存在缺陷的web应用作为代理攻击远程和本地服务器。
攻击方式
对外网,服务器所在内网,本地进行端口扫描,获取banner信息
对内网web应用进行指纹识别,识别企业内部的资产信息
攻击内外网的web
应用,主要是HTTP GET请求就可以实现的攻击(比如struts2,SQli等)
利用file的协议读取本地文件等。
这里看下源代码分析
/**
* Created by runner.han
* There is nothing new under the sun
*/
$SELF_PAGE = substr($_SERVER['PHP_SELF'],strrpos($_SERVER['PHP_SELF'],'/')+1);
if ($SELF_PAGE = "ssrf_curl.php"){
$ACTIVE = array('','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','active open','','active','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','');
}
$FILEDIR = $_SERVER['PHP_SELF'];
$RD = explode('/',$FILEDIR)[1];
$PIKA_ROOT_DIR = "../../";
include_once $PIKA_ROOT_DIR.'header.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;
}
?>
<div class="main-content">
<div class="main-content-inner">
<div class="breadcrumbs ace-save-state" id="breadcrumbs">
<ul class="breadcrumb">
<li>
<i class="ace-icon fa fa-home home-icon"></i>
<a href="ssrf.php"></a>
</li>
<li class="active">概述</li>
</ul>
<a href="#" style="float:right" data-container="body" data-toggle="popover" data-placement="bottom" title="tips(再点一下关闭)"
data-content="先了解一下php中curl相关函数的用法吧">
点一下提示~
</a>
</div>
<div class="page-content">
<a href="ssrf_curl.php?url=$RD.'/vul/ssrf/ssrf_info/info1.php';?>">累了吧,来读一首诗吧</a>
</div><!-- /.page-content -->
</div>
</div><!-- /.main-content -->
<?php
include_once $PIKA_ROOT_DIR . 'footer.php';
?>
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_
init函数进行请求
我们可以用这个漏洞探测端口开发情况,可以看到3306端口是开放的
可以用bp进行批量的端口扫描和banner信息
利用file协议对本地文件进行读取
防御方案
2.过滤返回信息,验证远程服务器对请求的响应是比较容易的方法。如果 web 应用是去获取某一种类型的
文件。那么在把返回结果展示给用户之前先验证返回的信息是否符合标准。
3.禁用不需要的协议,仅仅允许 http 和 https 请求。可以防止类似于 file://, gopher://, ftp:// 等引
起的问题
4.设置 URL 白名单或者限制内网 IP(使用 gethostbyname()判断是否为内网 IP)
5.限制请求的端口为 http 常用的端口,比如 80、443、8080、8090
6.统一错误信息,避免用户可以根据错误信息来判断远端服务器的端口状态。