From 056c260c12734f8587bb19333a3269cdd56bc4b6 Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Mon, 24 Feb 2020 17:17:34 +0200 Subject: [PATCH] Island adjusted to differentiate parsing data incoming from linux and windows bootloaders --- monkey/infection_monkey/transport/http.py | 8 ++++++-- monkey/monkey_island/cc/app.py | 2 +- monkey/monkey_island/cc/bootloader_server.py | 4 +++- monkey/monkey_island/cc/resources/bootloader.py | 17 ++++++++++++++--- 4 files changed, 24 insertions(+), 7 deletions(-) diff --git a/monkey/infection_monkey/transport/http.py b/monkey/infection_monkey/transport/http.py index 8745e62eb..efb39a71c 100644 --- a/monkey/infection_monkey/transport/http.py +++ b/monkey/infection_monkey/transport/http.py @@ -115,8 +115,12 @@ class HTTPConnectProxyHandler(http.server.BaseHTTPRequestHandler): def do_POST(self): content_length = int(self.headers['Content-Length']) # <--- Gets the size of data post_data = self.rfile.read(content_length).decode() # <--- Gets the data itself - r = requests.post(url=self.path, data=post_data) - if (r.status_code != 200): + try: + r = requests.post(url=self.path, data=post_data) + except requests.exceptions.ConnectionError as e: + LOG.error("Couldn't forward request to the island: {}".format(e)) + return self.send_response(404) + if r.status_code != 200: # somehow forward post request to the next proxy r = requests.post(url=self.path, data=post_data, proxy=self.path) if (r.status_code != 200): diff --git a/monkey/monkey_island/cc/app.py b/monkey/monkey_island/cc/app.py index 4698d6007..80d743209 100644 --- a/monkey/monkey_island/cc/app.py +++ b/monkey/monkey_island/cc/app.py @@ -87,7 +87,7 @@ def init_app_url_rules(app): def init_api_resources(api): api.add_resource(Root, '/api') api.add_resource(Monkey, '/api/monkey', '/api/monkey/', '/api/monkey/') - api.add_resource(Bootloader, '/api/bootloader') + api.add_resource(Bootloader, '/api/bootloader/') api.add_resource(LocalRun, '/api/local-monkey', '/api/local-monkey/') api.add_resource(ClientRun, '/api/client-monkey', '/api/client-monkey/') api.add_resource(Telemetry, '/api/telemetry', '/api/telemetry/', '/api/telemetry/') diff --git a/monkey/monkey_island/cc/bootloader_server.py b/monkey/monkey_island/cc/bootloader_server.py index 7706817f8..3ba15b5e2 100644 --- a/monkey/monkey_island/cc/bootloader_server.py +++ b/monkey/monkey_island/cc/bootloader_server.py @@ -1,4 +1,5 @@ from http.server import HTTPServer, BaseHTTPRequestHandler +from socketserver import ThreadingMixIn from urllib import parse import urllib3 @@ -9,7 +10,7 @@ import pymongo urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) -class BootloaderHttpServer(HTTPServer): +class BootloaderHttpServer(ThreadingMixIn, HTTPServer): def __init__(self, mongo_url): self.mongo_client = pymongo.MongoClient(mongo_url) @@ -26,6 +27,7 @@ class BootloaderHTTPRequestHandler(BaseHTTPRequestHandler): if not conf: conf = self.server.mongo_client['monkeyisland']['config'].find_one({'name': 'initial'}) island_server_path = BootloaderHTTPRequestHandler.get_bootloader_resource_path_from_config(conf) + island_server_path = parse.urljoin(island_server_path, self.path) r = requests.post(url=island_server_path, data=post_data, verify=False) if r.status_code != 200: diff --git a/monkey/monkey_island/cc/resources/bootloader.py b/monkey/monkey_island/cc/resources/bootloader.py index 1094b139b..66eb48ae1 100644 --- a/monkey/monkey_island/cc/resources/bootloader.py +++ b/monkey/monkey_island/cc/resources/bootloader.py @@ -10,18 +10,29 @@ from monkey_island.cc.services.bootloader import BootloaderService class Bootloader(flask_restful.Resource): # Used by monkey. can't secure. - def post(self, **kw): - data = Bootloader.parse_bootloader_request(request.data) + def post(self, os): + if os == 'linux': + data = Bootloader.parse_bootloader_request_linux(request.data) + elif os == 'windows': + data = Bootloader.parse_bootloader_request_windows(request.data) + else: + return make_response({"status": "OS_NOT_FOUND"}, 404) + resp = BootloaderService.parse_bootloader_data(data) + if resp: return make_response({"status": "RUN"}, 200) else: return make_response({"status": "ABORT"}, 200) @staticmethod - def parse_bootloader_request(request_data: bytes) -> Dict[str, str]: + def parse_bootloader_request_linux(request_data: bytes) -> Dict[str, str]: parsed_data = json.loads(request_data.decode().replace("\n", "") .replace("NAME=\"", "") .replace("\"\"", "\"") .replace("\":\",", "\":\"\",")) return parsed_data + + @staticmethod + def parse_bootloader_request_windows(request_data: bytes) -> Dict[str, str]: + return json.loads(request_data.decode("utf-16", "ignore"))