前言
在《浅谈云上攻防——元数据服务带来的安全挑战》一文中,生动形象的为我们讲述了元数据服务所面临的一系列安全问题,而其中的问题之一就是通过SSRF去攻击元数据服务;文中列举了2019年美国第一资本投资国际集团(Capital One Financial Corp.,下“Capital One公司”)信息泄漏的案例;我们内部也监测到过类似的事件:测试人员通过SSRF漏洞攻击元数据服务,并将获取到的AK信息存储到日志服务中,然后在日志服务中获取到了AK信息,最终通过获取到的AK信息控制了超过200台服务器。具体攻击路径如图所示:
图1-美国Capital One公司信息泄漏路径
通过上述案例,我们可以看到在云场景中,由于云厂商提供云服务均使用同一套网络边界和鉴权系统,且各云组件默认相互信任。此时一旦存在SSRF漏洞,此类边界将不复存在,攻击者可直接调用云厂商支持环境中的相应接口,因此SSRF漏洞在云环境中更具有危害性。为此本文就SSRF与云环境结合所带来的一些问题以及SSRF常见的一些绕过方法进行了整理,希望通过对这些方法的学习来提高我们在云上对于SSRF的防护能力。
SSRF漏洞对云环境带来的影响
在介绍SSRF漏洞在云场景中的危害之前,这里先为大家简单介绍一下什么是SSRF漏洞。SSRF(Server-Side Request Forgery:服务器端请求伪造) 是一种由攻击者构造形成由服务端发起请求的一个安全漏洞。SSRF 形成的原因大都是由于服务端提供了对外发起请求的功能且没有对目标地址做过滤与限制。SSRF根据是否回显请求内容分为回显型SSRF和非回显型SSRF。如图所示,当服务器A存在SSRF漏洞时,攻击者就可以通过服务器A去访问内网的服务器B,从而向B服务器发起攻击。
图2-SSRF原理
在传统环境中,SSRF漏洞的主要作用是帮助攻击者突破网络边界,从而可以使攻击者攻击那些外网无法访问的内部系统。而这些内部系统往往都容易成为企业安全建设的盲区。从而导致企业内网被攻破的概率增加。在传统环境中,SSRF漏洞的危害基本可以分为以下四种:
1) 获取敏感信息:攻击者通过SSRF可以尝试获取一些存在敏感信息的系统文件或者网页;
2) 内网信息探测:攻击者也可以通过SSRF去对内网的主机和端口进行探测,获取内网主机的IP存活和端口开放信息,从而去判断内网都开有哪些服务;
3)攻击内网应用程序:根据获取到的内网服务的信息,攻击者就可以有针对性的对内网的web应用,或者其他应用程序进行攻击,如weblogic,redis,tomcat等等,从而获取内网机器的权限,为后续的攻击打开突破口;
4) DOS攻击:如果有需要,攻击者也可以利用SSRF企业服务进行DOS攻击。
在云环境中,SSRF漏洞除了传统的攻击内网等攻击方式外,也增加了一些云上特有的攻击方式,这些攻击方式一旦被攻击者利用成功,往往都会对云上资产造成严重的危害。下面就将为大家一一介绍一下这些攻击方式:
攻击元数据服务:在云环境中,元数据即表示实例的相关数据,可以用来配置或管理正在运行中的实例。攻击通过SSRF去访问元数据中存储的临时密钥或者用于自启动实例的启动脚本,这些脚本可能会包含AK、密码、源码等等,然后根据从元数据服务获取的信息,攻击者可尝试获取到受害者账户下COS、CVM、集群等服务的权限。具体攻击方式如下图所示:
图3-元数据服务攻击方式
攻击Kubelet API:在云环境中,可通过Kubelet API查询集群pod和node的信息,也可通过其执行命令。为了安全考虑,此服务一般不对外开放。但是,攻击者可以通过SSRF去访问Kubelet API,获取信息和执行命令。具体攻击方式如下图所示:
图4-针对Kubelet API攻击方式1
近期我们也监测到一个类似的案例,如下图所示,测试人员通过发现的某个SSRF漏洞,通过访问集群中的Kubelet API来执行命令,从而获取进群内容器的权限。
图5-针对Kubelet API攻击方式2
攻击Docker Remote API:Docker Remote API是一个取代远程命令行界面(rcli)的REST API,默认开放端口为2375。此API如果存在未授权访问,则攻击者可以利用其执行docker命令,获取敏感信息,并获取服务器root权限。因此为了安全考虑,一般不会在外网开放,此时我们就可以通过SSRF去尝试攻击那些不对外开放的Docker Remote API。其过程与攻击Kubelet API类似。
越权攻击云平台内其他组件或服务:由于云上各组件相互信任,当云平台内某个组件或服务存在SSRF漏洞时,就可通过此漏洞越权攻击其他组件或者服务。如下图所示,用户正常请求服务A时,云API层会对请求进行校验,其中包括身份、权限等。如果服务A存在SSRF漏洞,则可构造请求使服务A访问服务B,因为服务A与服务B互相信任,所以服务B未校验服务A的请求,从而越权操作服务B的资源。
图6-越权操作
SSRF漏洞易出现的场景
云场景中除了传统的一些可能出现SSRF的场景之外,也出现了一些新的容易出现SSRF的场景:
1) 代理功能:如开发、运维人员因为方便工作所搭建的web代理等等,此类功能如果没有设置好身份认证,就会导致SSRF漏洞出现,因为利用方式简单,且存在回显,故此类问题一旦出现,造成的危害往往都会比较严重;
2) 远程资源调用功能:此类功能如果没能做好安全检测,就会导致SSRF。如weblogic的SSRF漏洞;
3) 文件上传功能:在某些场景中,开发人员未对上传类型进行限制,导致攻击者可以修改type=url,将type=file改为type=url,然后将上传内容改为url,测试可否上传成功,如果可以上传成功,则可能存在SSRF;
4) 数据库内置功能:如mongodb的copyDatabase函数,在进行数据备份时,输入的IP进行限制,则可能存在SSRF漏洞;
5) 未公开的api:这类api有时也会有对外发起网络请求或者需要远程下载资源的功能,并且因为此api未公开,所以很有可能会成为安全防护的盲区;
6) 对象存储功能:对象存储功能是云上特有的文件存储系统,在对象存储功能中,获取存储桶时,如果此时未做302校验,则可结合cos回源绕过,尝试是否存在SSR;
7) 其他:处理图片文件、处理音视频文件、html解析、PDF解析等,这些功能如果防护不到位,也可能存在SSRF漏洞,如PDFReacter等等。
SSRF漏洞防御绕过方法
“ 道高一尺,魔高一丈 ”,在进行SSRF漏洞修复及防御的过程中,我们监测到一些新的攻击手段,这些手段很容易就绕过旧的防御策略。下面就为大家介绍一些典型的SSRF绕过手段。
利用@符号绕过
当我们需要通过URL发送用户名和密码时,可以使用
http://username:password@www.xxx.com,此时@前的字符会被当作用户名密码处理,@后面的字符才是我们请求的地址,即http://qq.com@127.0.0.1/与http://127.0.0.1/请求时是相同的,而这种方法有时可以绕过系统对地址的检测。
图7-利用@符号绕过
利用进制转换绕过
开发人员在提取或者过滤域名或者IP时,未考虑到IP的进制转换的影响,则存在被利用进制转换绕过的可能。浏览器不仅可以识别正常的IP地址,也可以识别八进制、十进制、十六进制等其他进制的IP地址,但是有时候开发人员会忽视这一点,因此有时,我们可以通过这一点去绕过防护。进制转换可以通过在线网站或者工具脚本完成,下面列举常用十进制和十六进制的例子。
十进制
http://127.0.0.1/->http://2130706433/
图8-利用十进制绕过
十六进制:
http://127.0.0.1/->http://0x7F000001/
图9-利用十六进制绕过
注意:16进制使用时一定要加0x,不然浏览器无法识别,八进制使用的时候要加0
利用30X跳转绕过
开发人员在进行SSRF防护时,未考虑到30X跳转的影响,则存在被利用30X跳转绕过的可能。服务器发请求的时候,一般会跟随30X接着访问跳转后的网址,而开发人员有时候会忽略这一点,在防护的时候只对第一次请求的链接进行检测,从而忽略了跳转后的链接,因此可以通过这种方式去尝试绕过系统的防护。下面附上一个302跳转的python脚本。
#!/usr/bin/env python3
import sys
from http.server import HTTPServer, BaseHTTPRequestHandler
if len(sys.argv)-1 != 2:
print("""
Usage: {} <port_number> <url>
""".format(sys.argv[0]))
sys.exit()
class Redirect(BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(302)
self.send_header('Location', sys.argv[2])
self.end_headers()
def send_error(self, code, message=None):
self.send_response(302)
self.send_header('Location', sys.argv[2])
self.end_headers()
HTTPServer(("", int(sys.argv[1])), Redirect).serve_forever()
使用方法:python 302.py port 跳转地址
图10-302跳转绕过
图11-302跳转绕过
利用短网址绕过
开发人员在进行SSRF防护时,未考虑到短网址的影响,则存在被利用短网址绕过的可能。短网址本质上是一种302跳转,但是短网址字符长度一般都比较短,其中有的短网址域名可能还做过认证,在某些时候被信任的可能比个人申请的域名会高一点,且网上都有搭建好的服务,方便快捷。因此本文将短网址绕过也单独列为一种方法。
图12-利用短网址绕过
图13-短网址绕过
利用域名解析服务绕过
开发人员在构建SSRF防护时,只考虑到了域名,没有考虑到域名解析后的IP,则存在被利用域名解析服务来绕过的可能。此类服务有一个功能就是将xxx.127.0.0.1.xxx.xx解析成127.0.0.1,并且此类服务一般在互联网上都是可以免费使用,十分方便。因此有时候也可以尝试利用此种方法去绕过系统的防护。
图14-利用域名解析服务绕过
图15-利用域名解析服务绕过
利用添加端口的方式绕过
开发人员在提取或者过滤域名或者IP时,未考虑到端口端口对IP格式的影响,则存在被通过添加端口绕过的可能,如http://127.0.0.1->http://127.0.0.1:80。下图是笔者利用python的正则例举的一种可能存在的情况。
图16-利用添加端口的方式绕过
利用将自己的域名解析到目标内网IP的方式绕过
上文讲的利用域名解析服务去绕过SSRF防护,我们也可通过自己购买域名,然后将其解析都某个内网,达到同样的效果。但是有的时候,这种方法也能做到一些域名解析服务做不到的事情。假设现在有这样一个功能,此功能的作用是先把用户输入的域名存储起来,等需要的时候再去调用。而开发人员只在输入的时候,对域名和域名解析后的IP做了校验,而真正调用的时候,未做任何校验,这个时候我们就可以先将域名解析到某个外网IP上,等存储完成之后,真正需要调用的时候再将其解析到内网的目标IP上。
利用对象存储回源功能绕过
在遇到302跳转绕过时,除了上述的两种方法之外,还有一种利用对象存储本身的回源功能进行绕过的方法。下面笔者会介绍如何去使用这种方法:
(1)新建一个存储桶;
图17-新建存储桶
(2)设置权限为公有读私有写,其他的默认即可;
图18-新建公有读私有写存储桶
(3) 开启静态网站;
图19-开启静态网站
(4)在回源设置处添加回源规则;
图20-添加回源地址
(5)协议配置页面,默认404即可触发回源,也可以自己添加关键字触发,类似于
https://xxx.com/key,key为触发的关键字,其他的默认即可;
图21-配置http状态码
(6)源站设置页面,回源地址填写要访问的地址,这块限制了内网地址,抓包修改成完整的请求(xxx.com/xxx),即可绕过,或者绑定好自己的域名后,再将其解析到内网地址。其他的根据需要填写。
图22-配置回源地址
(7)设置好之后,在可能存在ssrf的地方填上静态网站的地址即可。
利用DNS重绑定(DNS Rebinding)绕过
在上文中,笔者介绍了一种通过手动更改域名解析的方式绕过SSRF防护的方法,但是如果开发人员在调用的时候也进行了检测呢,这样还有办法绕过吗,答案是可以的。可以通过DDNS重绑定的方式去进行绕过。
在介绍DNS重绑定之前,我们先看下服务器从获取一个URL,到发起请求,都会经历哪些步骤。首先,系统会取到用户输入的URL,并从该URL中提取host;然后,系统会对该host进行DNS解析,获取到解析的IP;接着会对该IP进行检测,检测该IP是否是合法的,比如是否是私有IP等;最后,如果IP检测为合法的,则进入curl的阶段发包。
在这个过程中,第一次去请求DNS服务进行域名解析到第二次服务端去请求URL之间存在一个时间差,利用这个时间差,我们可以在第一次去请求DNS服务进行域名解析时,返回一个正常的IP,而在第二次服务端去请求URL时,让DNS解析到内网IP,这时候就可以绕过系统对于SSRF的防护。这就是DNS Rebinding。具体原理如下:
服务器端获得URL参数,进行第一次DNS解析,获得了一个非内网的IP;
对于获得的IP进行判断,发现为非黑名单IP,则通过验证;
服务器端对于URL进行访问,由于DNS服务器设置的TTL为0,所以再次进行DNS解析,这一次DNS服务器返回的是内网地址;
由于已经绕过验证,所以服务器端返回访问内网资源的结果。
图23-配置回源地址
利用别名绕过
开发人员在进行SSRF防护时,有时会忽略掉127.0.0.1和0.0.0.0的一些别名。这些别名往往是无法被正则匹配到的,但是却可以被浏览器识别,从而可能会导致防护失效。下面列举一些常见的别名:
http://localhost/->http://127.0.0.1/
http://0/->http://0.0.0.0/
图24-利用别名绕过
利用封闭式字母数字(Enclosed Alphanumerics)字符绕过
封闭式字母数字(Enclosed Alphanumerics)字符是一个Unicode块,其中包含圆形,支架或其他非封闭外壳内的字母数字印刷符号,或以句号结尾。封闭的字母数字块包含一个表情符号,封闭的M用作掩码工作的符号。它默认为文本显示,并且定义了两个标准化变体,用于指定表情符号样式或文本表示。这些字符也是可以被浏览器识别的,而开发人员有时会忽略这一点。举例如下:
ⓢⓢⓡⓕ.ⓒⓞⓜ->ssrf.com
图25-利用封闭式字母数字绕过
以下是在网上搜集的一个封闭式字母数字(Enclosed Alphanumerics)字符表:
图26-封闭式字母数字表
利用句号绕过
部分浏览器中会把中文句号写的IP也当作正常IP识别,如果开发者在进行防护忽略这一点,也可能会被攻击者利用此特性绕过。如127。0。0。1 >>> 127.0.0.1
图27-利用句号绕过
不过这种方法局限性很大,在测试了Firefox、chrome、IE、Safrai、curl五种方式之后,发现只有chrome可以使用。
利用IPv6绕过
有时候,企业内网可能已经支持IPv6了,但是开发人员在进行防护时,只对IPv4做了防护,这个时候就可以使用IPv6地址去绕过系统对于SSRF的防护。
如:http://[::1]/->http://127.0.0.1/
利用组合拳绕过
有时候开发人员对上述的一些问题都一一进行了防护,但在衔接的时候逻辑处理存在问题,这个时候单一种方法往往是不行的,可以尝试几种方法的组合,发散思维,勇于尝试,通过不断尝试,也许就会发现可能存在的问题。
写在最后
云环境与SSRF结合虽然带了许多问题,但是也为我们带来了全新的检测SSRF漏洞的可能,我们可以利用云上的一些特性,去尝试寻找一些相比于常规环境下更快速、更高效的SSRF自动化收敛方案。在这样的背景下,我们开创性的提出了一种基于云API的实时监控来检测SSRF漏洞的方法,并实际应用于日常SSRF检测中,这种方式可以基本覆盖接入了云API的云产品,针对存在SSRF漏洞的接口进行精准测试,大大提高了SSRF漏洞的检出率,保障了产品侧以及用户侧的安全。
随着云计算技术与SSRF攻击技术的不断发展,SSRF与云也会不断产生新的化学反应,因此需要我们去更加重视这个问题,不断学习新的知识,以攻促防,为云上安全保驾护航。
参考文献
1.https://cloud.tencent.com/developer/article/1668008
2.https://security.tencent.com/index.php/blog/msg/179
3.https://github.com/1135/notes/blob/master/web_vul_SSRF.md
4.https://mp.weixin.qq.com/s/0wdxfetcp8TUtLZFWI16uA
5.https://zhuanlan.zhihu.com/p/73736127
6.http://byd.dropsec.xyz/2017/11/21/SSRF%E7%BB%95%E8%BF%87%E6%96%B9%E6%B3%95%E6%80%BB%E7%BB%93/
7.https://www.shuzhiduo.com/A/LPdoepLgJ3/
8.http://blog.leanote.com/post/snowming/e2c24cf057a4
9.https://mp.weixin.qq.com/s/Y9CBYJ_3c2UI54Du6bneZA
10.https://www.freebuf.com/articles/web/179910.html
11.https://sirleeroyjenkins.medium.com/just-gopher-it-escalating-a-blind-ssrf-to-rce-for-15k-f5329a974530
云上攻防往期推荐: