SSRF漏洞
SSRF是Server-Side Request Forgery(服务器端请求伪造)的缩写,是一种网络攻击技术。攻击者发送恶意请求给目标服务器,让服务器去访问攻击者指定的其他服务器或者域名,从而获取敏感信息或者攻击其他系统。
SSRF漏洞的利用
探测内网主机存活:通过构造特定的URL,可以探测内网中存活的主机。例如,可以使用http协议进行内网主机存活探测。
端口扫描:利用SSRF漏洞可以对内网主机的端口进行扫描,寻找开放的端口和服务。
文件读取:通过file协议,可以尝试读取服务器上的敏感文件。例如,可以尝试读取
/etc/passwd
或/flag
文件。Redis未授权访问:如果内网中存在Redis服务且未授权访问,可以利用SSRF漏洞进行攻击。例如,可以将webshell写入Redis的db文件,然后通过访问该文件来执行命令。
SSRF漏洞的防范
输入验证:对用户输入的URL进行严格的验证,过滤掉危险的协议和关键字。
限制访问:限制服务器对外部网络的访问,避免服务器被攻击者利用来访问其他系统。
使用白名单:对于需要访问的外部服务或API,可以采用白名单机制,只允许访问指定的域名或IP地址。
监控和审计:对服务器的网络请求进行监控和审计,及时发现和阻止异常的请求。
SSRF的防御与绕过
SSRF漏洞形成的原因主要是服务器端所提供的接口中包含了所要请求的内容的URL参数,并且未对客户端所传输过来的URL参数进行过滤
一般的防御措施是对URL参数进行过滤,或者使得URL参数用户不可控,但当过滤方法不当时,就存在Bypass的不同方式
0x01 常见的过滤
过滤开头不是http://xxx.com的所有链接
过滤格式为ip的链接,比如127.0.0.1
结尾必须是某个后缀
0x02 绕过
http://www.baidu.com@10.10.10.10
与http://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
点分割符号替换
在浏览器中可以使用不同的分割符号来代替域名中的.
分割,可以使用。
、。
、.
来代替:
http://www。qq。com http://www。qq。com http://www.qq.com 无效的绕过方式
本地回环地址
127.0.0.1,通常被称为本地回环地址(Loopback Address),指本机的虚拟接口,一些表示方法如下(ipv6的地址使用http访问需要加[]
):
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
IP的进制转换
IP地址是一个32位的二进制数,通常被分割为4个8位二进制数。通常用“点分十进制”表示成(a.b.c.d)的形式,所以IP地址的每一段可以用其他进制来转换。 IPFuscator 工具可实现IP地址的进制转换,包括了八进制、十进制、十六进制、混合进制。在这个工具的基础上添加了IPV6的转换和版本输出的优化。
在脚本对IP进行八进制转换时,一些情况下会在字符串末尾多加一个L。
封闭式字母数字 (Enclosed Alphanumerics)字符
封闭式字母数字是一个由字母数字组成的Unicode印刷符号块,使用这些符号块替换域名中的字母也可以被浏览器接受。在浏览器测试中只有下列单圆圈的字符可用:
List: ① ② ③ ④ ⑤ ⑥ ⑦ ⑧ ⑨ ⑩ ⑪ ⑫ ⑬ ⑭ ⑮ ⑯ ⑰ ⑱ ⑲ ⑳ ⑴ ⑵ ⑶ ⑷ ⑸ ⑹ ⑺ ⑻ ⑼ ⑽ ⑾ ⑿ ⒀ ⒁ ⒂ ⒃ ⒄ ⒅ ⒆ ⒇ ⒈ ⒉ ⒊ ⒋ ⒌ ⒍ ⒎ ⒏ ⒐ ⒑ ⒒ ⒓ ⒔ ⒕ ⒖ ⒗ ⒘ ⒙ ⒚ ⒛ ⒜ ⒝ ⒞ ⒟ ⒠ ⒡ ⒢ ⒣ ⒤ ⒥ ⒦ ⒧ ⒨ ⒩ ⒪ ⒫ ⒬ ⒭ ⒮ ⒯ ⒰ ⒱ ⒲ ⒳ ⒴ ⒵ Ⓐ Ⓑ Ⓒ Ⓓ Ⓔ Ⓕ Ⓖ Ⓗ Ⓘ Ⓙ Ⓚ Ⓛ Ⓜ Ⓝ Ⓞ Ⓟ Ⓠ Ⓡ Ⓢ Ⓣ Ⓤ Ⓥ Ⓦ Ⓧ Ⓨ Ⓩ ⓐ ⓑ ⓒ ⓓ ⓔ ⓕ ⓖ ⓗ ⓘ ⓙ ⓚ ⓛ ⓜ ⓝ ⓞ ⓟ ⓠ ⓡ ⓢ ⓣ ⓤ ⓥ ⓦ ⓧ ⓨ ⓩ ⓪ ⓫ ⓬ ⓭ ⓮ ⓯ ⓰ ⓱ ⓲ ⓳ ⓴ ⓵ ⓶ ⓷ ⓸ ⓹ ⓺ ⓻ ⓼ ⓽ ⓾ ⓿ ⓧⓘⓐⓝⓞⓤⓟⓔⓝⓖ.ⓒⓞⓜ ①⑦②.①⑥.⑥⓪.①⑥⑥ 经测试,不可行,也许有其他方式
浏览器访问时会自动识别成拉丁英文字符:
ⓔⓧⓐⓜⓟⓛⓔ.ⓒⓞⓜ >>> example.com
URL十六进制编码
URL十六进制编码可被浏览器正常识别,编码脚本:
#-*- 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)
利用网址缩短
网上有很多将网址转换未短网址的网站。
•短网址-短链接生成•短网址 - URLC.CN短网址,短网址生成,网址缩短,免费提供API接口生成,活码二维码生成,域名拦截检测
利用30X重定向
可以使用重定向来让服务器访问目标地址,可用于重定向的HTTP状态码:300、301、302、303、305、307、308。
需要一个vps,把302转换的代码部署到vps上,然后去访问,就可跳转到内网中
服务端代码如下:
<?php header("Location: http://192.168.1.10"); exit(); ?>
DNS解析
配置域名的DNS解析到目标地址(A、cname等),这里有几个配置解析到任意的地址的域名:
nslookup 127.0.0.1.nip.io nslookup owasp.org.127.0.0.1.nip.io 在内网外网可以解析
xip.io
xip.io是一个开源泛域名服务。它会把如下的域名解析到特定的地址,其实和dns解析绕过一个道理。
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 不可行 在内网外网不能解析
SSRF的测试工具
SSRFmap
SSRFmap-master - 可以在一个请求包中指定SSRF的位置,工具根据模块来发送EXP,支持了下列漏洞的利用:
帮助说明如下:
SSRF-Testing
SSRF-Testing-master - 常用的SSRF绕过测试
redis-over-gopher
redis-over-gopher - 将请求转换为gopher协议格式
SSRF的加固
•禁止302跳转,或者每跳转一次都进行校验目的地址是否为内网地址或合法地址。
•过滤返回信息,验证远程服务器对请求的返回结果,是否合法。
•禁用高危协议,例如:gopher、dict、ftp、file等,只允许http/https
•设置URL白名单或者限制内网IP
•限制请求的端口为http的常用端口,或者根据业务需要治开放远程调用服务的端口
•catch错误信息,做统一错误信息,避免黑客通过错误信息判断端口对应的服务
ssrf攻击fastcgi复现及环境搭建
环境搭建
7.2版本的成功复现
docker run -it --name t1 -p 127.0.0.1:12313:80 ubuntu 先docker 起一个干净的ubuntu
这里可以看到端口已经成功映射过来了
简单解释几下,先增加一些其他的源,然后down下来php7.2以及他的一些扩展,还有nginx 修改nginx,和php-fpm的配置文件
主要配置文件修改的就是这几个地方 fpm的www.conf文件 listen = 127.0.0.1:9000 nginx的default文件 fastcgi_pass 127.0.0.1:9000;
然后在/var/www/html目录下创建
phpinfo.php 1.php <?php highlight_file(__FILE__); $url = $_GET['url']; $curl = curl_init($url); curl_setopt($curl, CURLOPT_HEADER, 0); $responseText = curl_exec($curl); echo $responseText; curl_close($curl); ?>
开始攻击
很明显的ssrf漏洞了
http://127.0.0.1:12313/1.php?url=http://www.baidu.com
可以成功返回百度页面
利用gopher协议去伪造请求
利用Gopherus-master工具生成exp
可以看到成功执行命令了