干货 | SSRF的防御与绕过

2022-02-11 08:06:55 浏览数 (1)

SSRF漏洞形成的原因主要是服务器端所提供的接口中包含了所要请求的内容的URL参数,并且未对客户端所传输过来的URL参数进行过滤 一般的防御措施是对URL参数进行过滤,或者使得URL参数用户不可控,但当过滤方法不当时,就存在Bypass的不同方式

@绕过

http://www.baidu.com@10.10.10.10http://10.10.10.10请求是相同的

该请求得到的内容都是10.10.10.10的内容,此绕过同样在URL跳转绕过中适用。

原理如下:

利用解析URL时的规则问题。

一般情况下利用URL解析导致SSRF过滤被绕过基本上都是因为后端通过不正确的正则表达式对URL进行了解析。而在2017年的Blackhat大会上,Orange Thai 在blackhat中发表的演讲《A New Era of SSRF - Exploiting URL Parser in Trending Programming Languages! 》中介绍了SSRF攻击的一个新的角度———利用不同编程语言对URL的处理标准来绕过SSRF过滤,从而实施攻击。该方式主要是利用URL解析器和URL请求器之间的差异性发起攻击,由于不同的编程语言实现URL解析和请求是不一样的,所以很难验证一个URL是否合法

很难验证一个URL是否合法的原因在于:

1.在 RFC2396/RFC3986 中进行了说明,但是也仅仅是说明。2.WHATWG(网页超文本应用技术工作小组)定义了一个基于RFC协议的具体实现,但是不同的编程语言仍然使用他们自己的实现。

下图展示了cURL请求函数与其他语言解析函数结合使用时,由于差异性造成的漏洞

image-20210222151203604

可以得知,NodeJS url、Perl URI、Go net/url、PHP parser_url以及Ruby addressable解析函数与cURL libcurl请求函数差异性都可能造成漏洞的产生

下图的实例中,我们看到上述所述编程语言的解析函数得到的IP是google.com,而cURL请求得到的却是evil.com:80

image-20210222151535178

点分割符号替换

在浏览器中可以使用不同的分割符号来代替域名中的.分割,可以使用来代替:

代码语言:javascript复制
http://www。qq。com
http://www。qq。com
http://www.qq.com

本地回环地址

127.0.0.1,通常被称为本地回环地址(Loopback Address),指本机的虚拟接口,一些表示方法如下(ipv6的地址使用http访问需要加[]):

代码语言:javascript复制
http://127.0.0.1 
http://localhost 
http://127.255.255.254 
127.0.0.1 - 127.255.255.254 
http://[::1] 
http://[::ffff:7f00:1] 
http://[::ffff:127.0.0.1] 
http://127.1 
http://127.0.1 
http://0:80

img

IP的进制转换

IP地址是一个32位的二进制数,通常被分割为4个8位二进制数。通常用“点分十进制”表示成(a.b.c.d)的形式,所以IP地址的每一段可以用其他进制来转换。 IPFuscator 工具可实现IP地址的进制转换,包括了八进制、十进制、十六进制、混合进制。在这个工具的基础上添加了IPV6的转换和版本输出的优化。

在脚本对IP进行八进制转换时,一些情况下会在字符串末尾多加一个L。

img

封闭式字母数字 (Enclosed Alphanumerics)字符

封闭式字母数字是一个由字母数字组成的Unicode印刷符号块,使用这些符号块替换域名中的字母也可以被浏览器接受。在浏览器测试中只有下列单圆圈的字符可用:

代码语言:javascript复制
List:
① ② ③ ④ ⑤ ⑥ ⑦ ⑧ ⑨ ⑩ ⑪ ⑫ ⑬ ⑭ ⑮ ⑯ ⑰ ⑱ ⑲ ⑳ 
⑴ ⑵ ⑶ ⑷ ⑸ ⑹ ⑺ ⑻ ⑼ ⑽ ⑾ ⑿ ⒀ ⒁ ⒂ ⒃ ⒄ ⒅ ⒆ ⒇ 
⒈ ⒉ ⒊ ⒋ ⒌ ⒍ ⒎ ⒏ ⒐ ⒑ ⒒ ⒓ ⒔ ⒕ ⒖ ⒗ ⒘ ⒙ ⒚ ⒛ 
⒜ ⒝ ⒞ ⒟ ⒠ ⒡ ⒢ ⒣ ⒤ ⒥ ⒦ ⒧ ⒨ ⒩ ⒪ ⒫ ⒬ ⒭ ⒮ ⒯ ⒰ ⒱ ⒲ ⒳ ⒴ ⒵ 
Ⓐ Ⓑ Ⓒ Ⓓ Ⓔ Ⓕ Ⓖ Ⓗ Ⓘ Ⓙ Ⓚ Ⓛ Ⓜ Ⓝ Ⓞ Ⓟ Ⓠ Ⓡ Ⓢ Ⓣ Ⓤ Ⓥ Ⓦ Ⓧ Ⓨ Ⓩ 
ⓐ ⓑ ⓒ ⓓ ⓔ ⓕ ⓖ ⓗ ⓘ ⓙ ⓚ ⓛ ⓜ ⓝ ⓞ ⓟ ⓠ ⓡ ⓢ ⓣ ⓤ ⓥ ⓦ ⓧ ⓨ ⓩ 
⓪ ⓫ ⓬ ⓭ ⓮ ⓯ ⓰ ⓱ ⓲ ⓳ ⓴ 
⓵ ⓶ ⓷ ⓸ ⓹ ⓺ ⓻ ⓼ ⓽ ⓾ ⓿

浏览器访问时会自动识别成拉丁英文字符:

代码语言:javascript复制
ⓔⓧⓐⓜⓟⓛⓔ.ⓒⓞⓜ  >>>  example.com

URL十六进制编码

URL十六进制编码可被浏览器正常识别,编码脚本:

代码语言:javascript复制
#-*- coding:utf-8 -*- 
data = "www.qq.com"; 
alist = [] 
for x in data: 
    for i in range(0, len(x), 2): 
        alist.append((x[i:i 2]).encode('hex')) 
print "http://%" '%'.join(alist)

img

利用网址缩短

网上有很多将网址转换未短网址的网站。

•https://www.985.so/•https://www.urlc.cn/

image-20211205142931661

利用30X重定向

可以使用重定向来让服务器访问目标地址,可用于重定向的HTTP状态码:300、301、302、303、305、307、308。

需要一个vps,把302转换的代码部署到vps上,然后去访问,就可跳转到内网中

服务端代码如下:

代码语言:javascript复制
<?php 
header("Location: http://192.168.1.10");
exit(); 
?>

DNS解析

配置域名的DNS解析到目标地址(A、cname等),这里有几个配置解析到任意的地址的域名:

代码语言:javascript复制
nslookup 127.0.0.1.nip.io

nslookup owasp.org.127.0.0.1.nip.io

xip.io

xip.io是一个开源泛域名服务。它会把如下的域名解析到特定的地址,其实和dns解析绕过一个道理。

代码语言:javascript复制
http://10.0.0.1.xip.io = 10.0.0.1
www.10.0.0.1.xip.io= 10.0.0.1
http://mysite.10.0.0.1.xip.io = 10.0.0.1
foo.http://bar.10.0.0.1.xip.io = 10.0.0.1
10.0.0.1.xip.name resolves to 10.0.0.1
www.10.0.0.2.xip.name resolves to 10.0.0.2
foo.10.0.0.3.xip.name resolves to 10.0.0.3
bar.baz.10.0.0.4.xip.name resolves to 10.0.0.4

DNS重绑定

Untitled Diagram.drawio (3)

根据流程图:对于用户请求的URL参数,首先服务器端会对其进行DNS解析,然后对于DNS服务器返回的IP地址进行判断,如果在黑名单中,就pass掉。

但是在整个过程中,第一次去请求DNS服务进行域名解析到第二次服务端去请求URL之间存在一个时间差,利用这个时间差,我们可以进行DNS 重绑定攻击。我们利用DNS Rebinding技术,在第一次校验IP的时候返回一个合法的IP,在真实发起请求的时候,返回我们真正想要访问的内网IP即可。

要完成DNS重绑定攻击,我们需要一个域名,并且将这个域名的解析指定到我们自己的DNS Server,在我们的可控的DNS Server上编写解析服务,设置TTL(TTL表示DNS记录在DNS服务器上缓存时间)时间为0,这是为了防止有DNS服务器对第一次的解析结果进行缓存

完整的DNS重绑定攻击流程为:

1.服务器端获得URL参数,进行第一次DNS解析,获得了一个非内网的IP2.对于获得的IP进行判断,发现为指定范围IP,则通过验证3.接下来服务器端对URL进行访问,由于DNS服务器设置的TTL为0,所以再次进行DNS解析,这一次DNS服务器返回的是内网地址4.由于已经绕过验证,所以服务器端返回访问内网资源的内容

在这里插入图片描述

比如在把同一个域名绑定两个不同的地址,也就是两条A记录,去碰这个概率,要的情况是第一次为外网地址,然而TTL为0,第二次请求的时候要为内网地址。

上面这种情况的话,每次解析的结果随机,所以要达到上面这样情况有1/4的机率,是这样算的吧。所以去碰这个概率,碰到了就能成功,但这种方法不稳定。

需要一个更好的方法:

在这里插入图片描述

所以需要 添加一条A记录和一条NS记录

ns记录表示域名test.bendawang.site这个子域名指定由ns.bendawang.site这个域名服务器来解析,然后a记录表示我的这个ns.bendawang.site的位置在ip地址104.160.43.154上。

这样的话第一解析test.bendawang.site时为ns.bendawang.site这个地址,能通过,

然后第二次解析ns.bendawang.site的时候,就为配置的内网地址了。

这里推荐一个在线的实现URL重绑定的工具(虽然只能实现上述的第一种方式,碰运气去解析):

https://lock.cmpxchg8b.com/rebinder.html

image-20211205153307651

有关DNS重绑定的具体实现可以参考如下文章: http://www.bendawang.site/2017/05/31/关于DNS-rebinding的总结/

SSRF的测试工具

SSRFmap

SSRFmap-master - 可以在一个请求包中指定SSRF的位置,工具根据模块来发送EXP,支持了下列漏洞的利用:

img

帮助说明如下:

img

SSRF-Testing

SSRF-Testing-master - 常用的SSRF绕过测试

img

redis-over-gopher

redis-over-gopher - 将请求转换为gopher协议格式

img

SSRF的加固

•禁止302跳转,或者每跳转一次都进行校验目的地址是否为内网地址或合法地址。•过滤返回信息,验证远程服务器对请求的返回结果,是否合法。•禁用高危协议,例如:gopher、dict、ftp、file等,只允许http/https•设置URL白名单或者限制内网IP•限制请求的端口为http的常用端口,或者根据业务需要治开放远程调用服务的端口•catch错误信息,做统一错误信息,避免黑客通过错误信息判断端口对应的服务

原创作者:Ulysses

内部学员投稿

0 人点赞