SSRF中的绕过手段——字节总结得比较好,如何绕过SSRF的保护机制,DNS欺骗,使用IPV6地址,十六进制编码、八进制编码、双字编码、URL编码和混合编码等
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编码的等价词
“%6c%6f%63%61%6c%68%6f%73%74”表示。
因此,当服务器阻止对内部主机名(如“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
SSRF漏洞和CSRF漏洞有一些相似之处:CSRF跨站请求伪造,基于客户端的请求伪造;SSRF服务器端请求伪造,基于服务端的请求伪造。
今天,我们来学习一下SSRF漏洞!
SSRF漏洞简介
1.SSRF漏洞概述
SSRF(Server-Side Request Forgery:服务器端请求伪造) 是一种由攻击者构造形成由服务端发起请求的一个安全漏洞。
一般情况下,SSRF攻击的目标是从外网无法访问的内部系统。(因为它是由服务端发起的,所以它能够请求到与它相连而与外网隔离的内网。也就是说可以利用一个网络请求的服务,当作跳板进行攻击)。
2.SSRF漏洞产生原因
SSRF 形成的原因往往是由于服务端提供了从其他服务器应用获取数据的功能且没有对目标地址做过滤与限制。
如:从指定URL地址获取网页文本内容,加载指定地址的图片,下载等。利用的就是服务端的请求伪造。ssrf是利用存在缺陷的web应用作为代理攻击远程和本地的服务器。
3.容易出现SSRF的地方
4.利用SSRF可以实现的攻击
SSRF漏洞相关函数和协议
1.函数
file_get_contents、fsockopen、curl_exec、fopen、readfile等函数使用不当会造成SSRF漏洞
(1)file_get_contents
file_get_content函数从用户指定的url获取内容,然后指定一个文件名j进行保存,并展示给用户。file_put_content函数把一个字符串写入文件中。
file_get_content函数从用户指定的url获取内容,然后指定一个文件名j进行保存,并展示给用户。file_put_content函数把一个字符串写入文件中。
(2)fsockopen
fsockopen函数实现对用户指定url数据的获取,该函数使用socket(端口)跟服务器建立tcp连接,传输数据。变量host为主机名,port为端口,errstr表示错误信息将以字符串的信息返回,30为时限。
fsockopen函数实现对用户指定url数据的获取,该函数使用socket(端口)跟服务器建立tcp连接,传输数据。变量host为主机名,port为端口,errstr表示错误信息将以字符串的信息返回,30为时限。
(3)curl_exec
$filename = './curled/'.rand.'.txt';file_put_contents($filename, $result); echo $result;}?>
curl_exec函数用于执行指定的cURL会话。
curl_exec函数用于执行指定的cURL会话。
注意
1.一般情况下PHP不会开启fopen的gopher wrapper
2.file_get_contents的gopher协议不能URL编码
3.file_get_contents关于Gopher的302跳转会出现bug,导致利用失败
4.curl/libcurl 7.43 上gopher协议存在bug(%00截断) 经测试7.49 可用
5.curl_exec //默认不跟踪跳转,
6.file_get_contents // file_get_contents支持php://input协议
2.协议
(1)file:在有回显的情况下,利用 file 协议可以读取任意内容
(2)dict:泄露安装软件版本信息,查看端口,操作内网redis服务等
(3)gopher:gopher支持发出GET、POST请求:可以先截获get请求包和post请求包,再构造成符合gopher协议的请求。gopher协议是ssrf利用中一个最强大的协议(俗称万能协议)。可用于反弹shell
(4)http/s:探测内网主机存活
SSRF漏洞利用
本地利用
以curl举例,查看 curl 支持的协议列表 curl -V。本地利用方式:
(1)使用file协议 file protocol (任意文件读取)
(2)使用dict协议 dict protocol (获取Redis配置信息)
(3)使用gopher协议(俗称万能协议) gopher protocol (一键反弹Bash)
远程利用
1、环境
攻击机ip:192.168.201.129、121.36.67.230
攻击机:Kali、公网服务器
远程服务器ip:39.x.x.x
docker镜像:ssrf_redis
PHP版本:PHP Version 7.2.28(5.6版本测试会失败)
2、远程利用示例代码
ssrf.php
post.php
3、远程利用方式
1.利用file协议
任意文件读取
2.利用dict协议
(1)查看端口及端口上运行服务的版本信息
说明22端口开放
(2)通过dict协议getshell
有关dict协议:向服务器的端口请求 命令:参数,并在末尾自动补上rn(CRLF)。
dict协议要一条一条的执行,而gopher协议执行一条命令就行了。
一条一条的执行就可以了。
3.利用gopher协议
(1)攻击内网redis并反弹shell
利用redis未授权访问攻击redis
攻击redis的exp
从而捕获到数据,并进行转换。
转换规则如下:
如果第一个字符是>或者<那么丢弃该行字符串,表示请求和返回的时间。
如果前3个字符是+OK 那么丢弃该行字符串,表示返回的字符串。
将r字符串替换成%0d%0a
空白行替换为%0a
结合gopher协议攻击内网redis,使用上边捕获数据的转换结果即可,然后进行反弹shell:
反弹成功
http://39.x.x.x:8000/ssrf.php是存在SSRF漏洞的Web服务
192.168.1.4是redis应用所在内网ip
121.36.67.230是公网服务器,接收反弹shell
(2)伪造post请求反弹shell
反弹成功
192.168.1.5是内网Web服务,有post.php
4 .利用http/s协议
探测内网主机存活
说明内网ip为192.168.1.3的主机存活
SSRF攻击应用实战
1、gopher攻击redis
参考远程利用 3.利用gopher协议
2、weblogic ssrf攻击redis
下载地址:https://github.com/vulhub/vulhub/tree/master/weblogic/ssrf
编译并启动环境
SSRF漏洞存在于http://your-ip:7001/uddiexplorer/SearchPublicRegistries.jsp
1.查看端口
访问
not connect,说明80端口未开放。
返回404,说明端口开放。
2.探测内网主机存活
说明内网ip为192.168.1.1的主机存活。
3.注入HTTP头,利用Redis反弹shell
通过ssrf探测内网中的redis服务器,发现172.22.0.2:6379可以连通
和上边的远程利用几乎一样。
将反弹shell脚本写入/etc/crontab定时任务
进行url编码
换行符是“rn”换成“%0D%0A”。将url编码后的字符串放在ssrf的域名后面,发送。
反弹成功
SSRF漏洞相关绕过
1、常用绕过方法
1.@
在对@解析域名中,不同的处理函数存在处理差异,如:
http://www.aaa.com@www.bbb.com@www.ccc.com
2.利用[::]
可以利用[::]来绕过localhost
3.添加端口号
4.利用短网址
站长工具短网址
百度短网址
5.利用特殊域名
原理是DNS解析。xip.io可以指向任意域名,即
6.利用DNS解析
在域名上设置A记录,指向127.0.1
7.利用进制转换
8.句号
9.302跳转
使用https://tinyurl.com生成302跳转地址
2、常见限制
1.限制为http://www.xxx.com 域名
采用http基本身份认证的方式绕过。即@
http://www.xxx.com@www.xxc.com
2.限制请求IP不为内网地址
当不允许ip为内网地址时
(1)采取短网址绕过
(2)采取特殊域名
(3)采取进制转换
3.限制请求只为http协议
(1)采取302跳转
(2)采取短地址
SSRF漏洞防御
1、禁用不需要的协议(如:file:///、gopher://,dict://等)。仅仅允许http和https请求
2、统一错误信息,防止根据错误信息判断端口状态
3、禁止302跳转,或每次跳转,都检查新的Host是否是内网IP,直到抵达最后的网址
4、设置URL白名单或者限制内网IP
后记
在SSRF漏洞的学习过程中,遇到了一些问题,比如反弹shell到公网服务器,折腾了许久。不过最终克服了问题。同时,通过SSRF漏洞的学习,发现SSRF漏洞果然比CSRF漏洞的利用的局限性要小,并且SSRF漏洞对内网的一些应用危害比较大。所以在开发过程中,要尽量避免产生SSRF漏洞。