报告编号:B6-2021-033001
报告来源:360CERT
报告作者:360CERT
更新日期:2021-03-30
0x01 漏洞概述
F5 BIG-IP在今年3月补丁日中修复了CVE-2021-22986
,未经身份验证的攻击者可以向iControl REST
发送精心构造的恶意请求,最终在目标服务器上执行任意命令。
0x02 环境配置
F5 BIG-IP官方提供了对应版本的Virtual Edition
版本,所以直接下载导入到vmware
中即可。本篇所使用的漏洞版本为16.0.1,diff版本为16.0.1.1。具体的步骤及操作可以参考这篇文章进行基础配置,完成F5 BIG-IP的启动。
2.1 允许ssh远连
可以根据这篇文章配置允许ssh远连,这里推荐直接用tmsh
来进行配置。
2.2 寻找具体服务
在F5 BIG-IP中,TMUI
与iControl REST
是部署在不同的端口上的。我们可以看一下我们访问的443端口的服务是什么:
可以看到是由Apache httpd进行请求承接,并将请求转发到不同端口的服务上完成对应的处理。我们可以看一下httpd的配置文件,在/config/httpd/conf/httpd.conf
:
这里可以注意到两点:
* AuthPAM开启,说明调用了httpd的某个.so
文件进行预先的认证
* 将所有向/mgmt
发送的请求都转发到了http://localhost:8100/mgmt/
通过阅读官方文档,我们可以知道所有REST API的目录前缀都是含有mgmt
的,所以可以看一下8100端口的服务及其进程信息是什么:
可以看到其classpath
为/usr/share/java/rest/
目录。之后我们可以通过PID
在/proc/
目录下查看进程信息:
这样也知道了进程运行目录为/var/service/restjavad
。
2.3 允许远程调试
根据2.2中找到的进程信息,我们直接到/var/service/restjavad
目录,然后向运行文件中添加相关的jdwp配置:
这里看到运行文件为/etc/bigstart/scripts/restjavad
,直接修改该文件即可:
当添加完jdwp配置后,还需要利用tmsh
将jdwp监听端口8777开放出去,这里可以直接参考这篇文章。这里为了防止链接失效,截一个这篇文章的关键图:
2.4 导出分析代码
在2.2中已经进行了详细的叙述,直接把/usr/share/java/rest/
下的代码导出就行了。如果遇到无法导出的问题,可能是由于/usr
目录无写权限,重新挂载一下/usr
即可:
mount -o remount w /usr
0x03 diff信息
3.1 ssrf
3.2 命令执行
0x04 漏洞分析
该漏洞可以分解为两部分:
* 认证绕过
* 命令执行端点
该漏洞有两种方式可以达成认证绕过:
* 认证不完全导致绕过
* ssrf获取token导致认证绕过
本文将使用动静态跟踪结合的方式,将两部分进行串流分析。
4.1 iControl REST处理逻辑
在开始分析认证绕过前,首先来分析一下程序执行流。
4.1.1 RestServerServlet
RestServerServlet
是整个iControle REST
的入口,首先看一下其service
方法:
从service
方法中,可以获得以下几个信息:
* RestServerServlet
以异步执行,并注册了一个ReadListener
* 在处理请求时,为每一个请求创建了一个RestOperation
* 因为向RestOperation
注册了一个RestRequestCompletion
,后续逻辑将以回调的方式执行
由于是注册了ReadListener
,所以我们直接跟进看com.f5.rest.app.RestServerServlet.ReadListenerImpl#onAllDataRead
(具体原因可以看ReadListener官方文档):
跟进看一下com.f5.rest.common.RestOperationIdentifier#setIdentityFromAuthenticationData
:
这里会监测请求中是否包含相关认证,并将其设置到RestOperation
中。注意这里涉及到两种身份设置方法,第一种是检测是否存在X-F5-Auth-Token
,第二种是通过Basic认证来设置身份。其中setIdentityFromBasicAuth
即为diff点:
在setIdentityData
中只会判断Basic头信息中是否存在username
,当存在时,将userReference
初始化为/mgmt/shared/authz/users/[username]
。
在完成设置后,便会执行completion.run()
方法,即:
关键逻辑为com.f5.rest.common.RestServer#trySendInProcess
:
其中会根据请求端口来寻找相关的RestWorker
,并执行OnRequest
方法。这里因为是8100
端口,其映射为RestServer
对象:
在findWorker()
方法中,将以请求的路径为查询条件,匹配RestServer
的pathToWarkerMap
。之后便会执行worker.onRequest()
方法,在这里会将worker添加到RestServer.readyWorkerSet
中。后面会以该Set
为消费者队列,并执行各个worker。
4.1.2 RestServer
RestServer
中主要工作是维护队列,并执行相关的worker。入口点为其构造方法:
这里明显为一个消费者,所以直接看callRestMethodHandler
即可,一路向下跟进到callDerivedRestMethod
方法:
这里即会调用对应worker的处理方法并完成对应的链调用。
4.2 认证绕过
该漏洞的重点是认证绕过这一部分,两种绕过方式采用了不同的思路,本篇主要分析第二种绕过方式,针对第一种方式只进行基础的分析,如果想要了解详情,可以阅读斗象的研究文章。
4.2.1 认证不完全导致绕过
BIG-IP由两部分组成,首先是通过Apache httpd
接收443的请求,并将请求转发给本地8100端口的Jetty服务,最终通过Jetty的servlet将不同的路由分发到不同的worker中,完成请求的处理。
而第一种利用方式正是利用了Jetty服务不会对通过httpd认证的请求进行二次认证的缺陷,导致了未认证的攻击者可以绕过认证访问任意worker,最终完成pre auth rce。
在2.2中,从httpd.conf
中已经看到httpd
在进行转发时启用了AuthPAM
,其具体的.so
文件为/usr/lib/httpd/modules/mod_auth_pam.so
。
用IDA分析一下逻辑:
httpd只查看请求中是否存在X-F5-Auth-Token
,若存在,则直接将请求转发到Jetty进行后续处理。
在Jetty这端,首先会判断X-F5-Auth-Token
是否为空,当设置为空时,对访问路径进行校验,但是这里不匹配任何一种情况。最终进入到else中。这里只会判断userReference
是否为空,以及userReference
是否为admin的userReference
。
回看userReference
的生成过程(在com.f5.rest.common.RestOperationIdentifier#setIdentityFromBasicAuth
):
可以发现这里的userReference
就是默认admin的userReference
:
从而导致了绕过。
4.2.2 ssrf获取token导致认证绕过
在diff中可以明显的看到在com.f5.rest.workers.authn.AuthnWorker#onPost
方法中增加了对loginReference.link
的校验。在跟踪了代码逻辑后,可以发现这里存在一处ssrf。
可控输入点为:
向下看ssrf点:
这里state.loginReference.link
是可控的。首先会new一个RestRequestCompletion
,并将其封装到RestOperation
中,最后向state.loginReference
发起请求。注意到在RestRequestCompletion
中存在completed()
方法,其中会调用AuthnWorker.generateToken()
方法生成一个token,跟进可以看到:
这里又新创建了一个RestOperation
,其中的completed
方法完成了token的映射及返回。具体的token生成在com.f5.rest.workers.AuthTokenWorker#generatePrimaryKey
中:
调用栈为:
如果想要静态跟踪到token生成点的话,直接跟进RestRequestSender.sendPost()
方法即可。
4.2.3 ssrf获取token总结
根据4.1中对处理逻辑的分析,想要找到获取token的点的话,只需要在所有的RestWorker
子类中寻找符合以下两个条件的子类即可:
* 存在onPost
方法可以处理POST
请求
* onPost
方法中可以控制执行流到RestOperation.complete()
方法
由于F5采用了回调的方式完成执行流的构建,最终都会通过回调的逻辑执行RestRequestCompletion.completed()
方法。
4.3 命令执行端点
命令执行端点主要是配合认证绕过最终达成远程pre auth rce的效果。
4.3.1 /mgmt/tm/util/bash
从[F5 BIG IP官方sdk][7]中找到/mgmt/tm/util/bash
可以直接执行命令:
4.3.2 /mgmt/tm/access/bundle-install-tasks
从diff中可以看到/mgmt/tm/access/bundle-install-tasks
直接将可控参数与tar -xf
拼接,直接执行命令。可以通过反引号直接执行命令。
0x05 漏洞利用
5.1 认证不完全导致绕过
第一种方法,可以直接构造如下的包,便可以直接执行命令:
POST /mgmt/tm/util/bash HTTP/1.1
Host: 192.168.59.7
Content-Type: application/json
X-F5-Auth-Token:
Authorization: Basic YWRtaW46
Content-Length: 52
5.2 ssrf获取token
参考4.2.3的总结,寻找相应获取token的端点,然后配合X-F5-Auth-Token
头向命令执行端点发送请求即可。
0x06 Reference
斗象的研究文章
https://blog.riskivy.com/f5%e4%bb%8e%e8%ae%a4%e8%af%81%e7%bb%95%e8%bf%87%e5%88%b0%e8%bf%9c%e7%a8%8b%e4%bb%a3%e7%a0%81%e6%89%a7%e8%a1%8c%e6%bc%8f%e6%b4%9e%e5%88%86%e6%9e%90/
F5 BIG-IP官方下载链接
https://downloads.f5.com/esd/productlines.jsp
Deploying BIG-IP Virtual Edition in ESXi
https://techdocs.f5.com/kb/en-us/products/big-ip_ltm/manuals/product/bigip-ve-setup-vmware-esxi-13-1-0/3.html
Specify allowable IP ranges for SSH accessm01e对于F5的漏洞配置文章
ReadListener官方文档
https://docs.oracle.com/javaee/7/api/javax/servlet/ReadListener.html
F5 BIG IP官方sdk
https://f5-sdk.readthedocs.io/en/latest/_modules/f5/bigip/tm/util/bash.html
推荐阅读:
3、安全运营周刊
长按下方二维码关注360CERT!谢谢你的关注!
注:360CERT官方网站提供 《CVE-2021-22986:F5 BIG-IP iControl REST未授权远程命令执行漏洞分析》 完整详情,点击阅读原文
本文始发于微信公众号(三六零CERT):CVE-2021-22986:F5 BIG-IP iControl REST未授权远程命令执行漏洞分析
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论