什么是SSRF?
SERVER SIDE REQUEST FORGERY的简写
因为服务器本身提供了资源获取相关的服务,在资源地址能够被用户控制时,将可能导致攻击者利用服务器身份获取预期外的资源的后果
危害?
条件满足的情况下:突破网络防护边界,造成内部信息或资源1被外部攻击者获取,比如探测内网存活主机、获取信任身份、攻击内网服务等。
原理?
利用服务器能够发送网络请求的特点,攻击者控制了服务器指定的发送内容。
支持那些请求协议?各个协议作用?
http:// 探测内网主机存活、端口开放情况
gopher:// 发送GET和POST请求:用TCP包攻击内网应用,如FastCGI、Redis
dict:// 泄露安装软件版本信息,查看端口,操作内网redis访问等(需要加上端口号)
file:// 读取本地文件
相关PHP函数和类
- file_get_contents():将整个文件或一个url所指向的文件内容读入一个字符串中
- readfile():读取一个文件的内容并输出
- fsockopen():打开一个网络连接或者Unix套接字连接
- curl_exec():初始化一个新的会话,返回一个cURL句柄,供curlsetopt(),curlexec()和curlclose()函数使用
- fopen():打开一个文件或者URL
上述函数使用不当造成SSRF漏洞。此外,PHP原生类SoapClient在触发反序列化时可导致SSRF
测试代码:
//ssrf1.php
<?php
show_source(_file_);
&url=&_GET['url'];
echo file_get_contents(&url);
?>
上述测试代码中,file_get_contents()函数将整个文件或一个url所指向的文件读入一个字符串中,并展示给用户,我们构造蕾丝ssrf.php?url=../../../../etc/passwd的paylaod即可读取服务器本地的任意文件。也可以进行远程访问。
readfile()函数与file_get_contents()函数相似
fsockopen()
不能读取文件、能发起网络请求
fsockopen(&hostname,&port,&errno,&errstr,&tieout)用于打开一个网络连接或者Unix套装接字连接,初始化一个套接字连接到指定主机(hostname),实现对用户指定url数据的获取。改函数会使用socket跟服务器建立tcp连接,进行传输原始数据。fsockopen()将返回一个文件句柄,之后可以被其他文件类函数调用(例如:fgets(),fgetss(),fwrite(),fclose()还有feof())如果电泳失败,将返回false
测试代码:
<?
$host=$_GET['url'];
$fp = fsockopen($host,80,$errno,$errstr,30);
if(!$fp){echo"$errstr($errno)<br/>\n";
}else{$out="GET/HTTP/1.1\r\n";$out="Host:$host\r\n";$out="Connection:Close\r\n\r\n";fwrite($fp,$out);while(!feof($fp)){echo fgets($fp,128); }ifclose($fp);
}
?>
构造ssrf,php?url=www.baidu.com即可成功触发ssrf并返回百度主页。但是该函数的ssrf无法读取本地文件
curl_exec()
能读文件、能发起网络请求
curl_init(url)函数初始化一个新的会话,返回一个cURL句柄,供curlsetopt(),curlexec()和curlclose()函数使用
测试代码:
<?
$url=$_REQUEST['url'];
$ch=curl_init($url);//创造一个curl资源
curl_setopt($ch,CURLOPT_HEADER,0);//设置url和响应的选项
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
$result=curl_exec($ch);//抓取curl并将其传递给浏览器
curl_close($ch);//关闭curl资源echo($result);
?>
构造ssrf.php?url=http://www.baidu.com/即可成功触发ssrf并返回百度主页
如何挖掘?挖掘场景?
看url、看功能、看代码
服务器调用三方资源时,其资源URL前端可控,比如:
- 找特征URL:通过URL地址分享内容,如?url=、src 、from、img、u、link、share wap urllink src source target u 3g display sourceURl imageURL domain res resource file host...
http://www.server.com/?url=xxxxx
- 找特殊场景:
- 转码服务
- 在线翻译
- 图片加载与下载:通过URL地址加载或下载图片
- 图片、文章收藏功能
- 网站采集、网页抓取的地方
- 头像的地方(远程加载头像)
- 一切要你输入网址的地方和可以输入ip的地方
- 文件下载
- 连接其他网络服务
未公开的api实现以及其他调用url的功能
- 源码审计特殊函数
php相关ssrf函数
漏洞条件
受害服务器可通内网,或者,受害者服务器接受前端自定义资源URL并解析
相关协议限制
没有回显:带回原址
gopher://在各类脚本语言中利用限制?
注意
- 一半情况下PHP不会开启fopen的gopher wrapper
- file_get_contents的gopher协议不能URL编码
- file_get_contents关于Gopher的302跳转会出现bug,导致利用失败
- curl/libcurl 7.43 上gopher协议存在bug(%00截断) 经测试7.49 可用
- curl_exec() //默认不跟踪跳转
- .file_get_contents() // 支持php://input协议
防范思路?
- 过滤返回信息,验证远程服务器对请求的响应是比较容易的方法。如果web应用是去获取某一种类型的文件。那么在把返回结果展示给用户之前先验证返回的信息是否符合标准。
- 统一错误信息,避免用户可以根据错误信息来判断远端服务器的端口状态。
- 限制请求的端口为http常用的端口,比如,80,443,8080,8090
- 黑名单内网ip。避免应用被用来获取获取内网数据,攻击内网
- 禁用不需要的协议。仅仅允许http和https请求。可以防止类似于file:///,gopher://,ftp:// 等引起的问题
- 使其与内网隔离