ssrf漏洞


* 介绍

ssrf(Server-Side Request Forgery:服务器端请求伪造): 是一种由攻击者构造形成由服务端发起请求的一个安全漏洞。一般情况下,SSRF攻击的目标是从外网无法访问的内部系统。(正是因为它是由服务端发起的,所以它能够请求到与它相连而与外网隔离的内部系统)

* 成因

都是由于服务端提供了从其他服务器应用获取数据的功能且没有对目标地址做过滤与限制。

也就是说,对于为服务器提供服务的其他应用没有对访问进行限制,如果我构造好我的访问包,那我就有可能利用目标服务对他的其他服务器应用进行调用。

SSRF 漏洞出现的场景

1.能够对外发起网络请求的地方,就可能存在 SSRF 漏洞

2.从远程服务器请求资源(Upload from URL,Import & Export RSS Feed)

3.数据库内置功能(Oracle、MongoDB、MSSQL、Postgres、CouchDB)

4.Webmail 收取其他邮箱邮件(POP3、IMAP、SMTP)

5.文件处理、编码处理、属性信息处理(ffmpeg、ImageMagic、DOCX、PDF、XML)
![](https://img2020.cnblogs.com/blog/2047558/202103/2047558-20210316110356372-499581422.png)

常利用的相关协议

http://:探测内网主机存活、端口开放情况

gopher://:发送GET或POST请求;攻击内网应用,如FastCGI、Redis

dict://:泄露安装软件版本信息,查看端口,操作内网redis访问等

file://:读取本地文件
##Bypass

常见限制:

限制为http://www.xxx.com域名,http://www.xxx.com@127.0.0.1/flag.php

限制请求IP不为内网地址

采用短网址绕过

采用特殊域名.xip.io

采用进制转换:如,十进制形式?url=http://2130706433/flag.php、十六进制形式?url=http://0x7F000001/flag.php

限制请求IP只为http协议

采用302跳转

采用短地址

##常见绕过方法:

利用302跳转

进制转换

利用DNS解析

利用@绕过

利用[::]

添加端口号

利用短网址

其他各种指向127.0.0.1的地址

漏洞产生

##相关PHP函数

curl()

fsockopen()

file_get_contents()

fopen()

readfile()

curl_exec()


##相关PHP内置类

SoapClient

##攻击内网应用

redis

fastcgi

mysql

postgresql

zabbix

pymemcache

smtp

file_get_contents

<?php
if(isset($_POST['url']))
{
$content=file_get_contents($_POST['url']);
$filename='./images/'.rand().';img11.jpg';
file_put_contents($filename,$content);
echo $_POST['url'];
$img="<img src=\"".$filename."\"/>";      //src指向从远程获取到的文件
}
echo $img;      
?>

fsockopen()实现获取用户制定url的数据。这个函数会使用secket跟服务器建立tcp连接

<?php
function GetFile($host,$port,$link)      //获得对应主机IP、端口、位置
{
$fp = fsockopen($host,intval($port),$errno,$errstr,30);
if(!$fp){
echo "$errstr(error number $errno) \n";
} else{
$out = "GET $link HTTP/1.1\r\n";
$out = "Host:$host\r\n";
$out = "Connection:Close\r\n\r\n";}
$out = "\r\n";
fwrite($fp,$out);
$contents=";
while(!feof($fp)){      //feof为true时结束
$contents.=fgets($fp,1024);      //使用套接字一次接受1024个
}
fclose($fp);
return $contents;
}
}
?>

curl_exec()使用curl发送请求获取数据


<?php
if(isset($_POST['url']))
{
$link = $_POST['url'];
$curlobj = curl_init();      //初始化curl
curl_setopt($curlobj,CURLOPT_POST,0);
curl_setopt($curlobj,CURLOPT_RETURNTRANSFER,TRUE);      //TRUE将curl_exec()获取的信息以字符串返回,而不是直接输出
$result = curl_exec($curlobj);
curl_close($curlobj);

$filename = './curled/'.rand().'.txt';      //本地服务器新建文件
file_put_contents($filename,$result);
echo $result;
}   
?>
PHP支持的伪协议

file:// — 访问本地文件系统
http:// — 访问 HTTP(s) 网址
ftp:// — 访问 FTP(s) URLs
php:// — 访问各个输入/输出流(I/O streams)
zlib:// — 压缩流
data:// — 数据(RFC 2397)
glob:// — 查找匹配的文件路径模式
phar:// — PHP 归档
ssh2:// — Secure Shell 2
rar:// — RAR
ogg:// — 音频流
expect:// — 处理交互式的流

php.ini参数设置

allow_url_fopen:默认值On,允许url里的封装协议访问文件。

allow_url_include:默认值Off,不允许url里的封装协议包含文件。

各协议的利用条件和方法
![](https://img2020.cnblogs.com/blog/2047558/202103/2047558-20210316111324723-1694983257.png)

举例:

?url=file:///var/www/html/flag.php
端口扫描

在SSRF中,dict协议与http协议可以用来探测内网主机存活与端口开放情况。

?url=dict://127.0.0.1:8000

用burp,在intruder中,将端口设置为变量。使用Simple List扫描常用端口,或者使用NumerList进行枚举。当发现长度不同的数据包时,再用http协议进一步探测。

?url=http://127.0.0.1:8111

Gopher协议的利用


什么是gopher协议

gopher协议是一种信息查找系统,他将Internet上的文件组织成某种索引,方便用户从Internet的一处带到另一处。在WWW出现之前,Gopher是Internet上最主要的信息检索工具,Gopher站点也是最主要的站点,使用tcp70端口。利用此协议可以攻击内网的 Redis、Mysql、FastCGI、Ftp等等,也可以发送 GET、POST 请求。这拓宽了 SSRF 的攻击面。

gopher协议的格式:gopher://IP:port/_TCP/IP数据流

gopher协议发送http get请求

    构造HTTP数据包

    URL编码、替换回车换行为%0d%0a,HTTP包最后加%0d%0a代表消息结束

    发送gopher协议, 协议后的IP一定要接端口

发送http post请求

    POST与GET传参的区别:它有4个参数为必要参数

    需要传递Content-Type,Content-Length,host,post的参数
posted @ 2020-11-26 20:15  WANGXIN_YU  阅读(344)  评论(0)    收藏  举报