Island: Refactor monkey download to take OS and return agent file

This commit is contained in:
Mike Salvatore 2022-02-28 14:55:20 -05:00
parent c075fed2da
commit 0df165e140
3 changed files with 47 additions and 62 deletions

View File

@ -134,8 +134,7 @@ def init_api_resources(api):
api.add_resource(ConfigurationImport, "/api/configuration/import") api.add_resource(ConfigurationImport, "/api/configuration/import")
api.add_resource( api.add_resource(
MonkeyDownload, MonkeyDownload,
"/api/monkey/download", "/api/monkey/download/<string:host_os>",
"/api/monkey/download/<string:path>",
) )
api.add_resource(NetMap, "/api/netmap") api.add_resource(NetMap, "/api/netmap")
api.add_resource(Edge, "/api/netmap/edge") api.add_resource(Edge, "/api/netmap/edge")

View File

@ -1,63 +1,34 @@
import hashlib import hashlib
import json
import logging import logging
import os from pathlib import Path
import flask_restful import flask_restful
from flask import request, send_from_directory from flask import make_response, send_from_directory
from monkey_island.cc.server_utils.consts import MONKEY_ISLAND_ABS_PATH from monkey_island.cc.server_utils.consts import MONKEY_ISLAND_ABS_PATH
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
MONKEY_DOWNLOADS = [ AGENTS = {
{ "linux": "monkey-linux-64",
"type": "linux", "windows": "monkey-windows-64.exe",
"filename": "monkey-linux-64", }
},
{
"type": "windows",
"filename": "monkey-windows-64.exe",
},
]
def get_monkey_executable(host_os): class UnsupportedOSError(Exception):
for download in MONKEY_DOWNLOADS: pass
if host_os == download.get("type"):
logger.info(f"Monkey exec found for os: {host_os}")
return download
logger.warning(f"No monkey executables could be found for the host os: {host_os}")
return None
class MonkeyDownload(flask_restful.Resource): class MonkeyDownload(flask_restful.Resource):
# Used by monkey. can't secure. # Used by monkey. can't secure.
def get(self, path): def get(self, host_os):
return send_from_directory(os.path.join(MONKEY_ISLAND_ABS_PATH, "cc", "binaries"), path) try:
path = get_agent_executable_path(host_os)
# Used by monkey. can't secure. return send_from_directory(path.parent, path.name)
def post(self): except UnsupportedOSError as ex:
host_json = json.loads(request.data) logger.error(ex)
host_os = host_json.get("os") return make_response({"error": str(ex)}, 404)
if host_os:
result = get_monkey_executable(host_os.get("type"))
if result:
# change resulting from new base path
executable_filename = result["filename"]
real_path = MonkeyDownload.get_executable_full_path(executable_filename)
if os.path.isfile(real_path):
result["size"] = os.path.getsize(real_path)
return result
return {}
@staticmethod
def get_executable_full_path(executable_filename):
real_path = os.path.join(MONKEY_ISLAND_ABS_PATH, "cc", "binaries", executable_filename)
return real_path
@staticmethod @staticmethod
def log_executable_hashes(): def log_executable_hashes():
@ -65,16 +36,30 @@ class MonkeyDownload(flask_restful.Resource):
Logs all the hashes of the monkey executables for debugging ease (can check what Monkey Logs all the hashes of the monkey executables for debugging ease (can check what Monkey
version you have etc.). version you have etc.).
""" """
filenames = set([x["filename"] for x in MONKEY_DOWNLOADS]) filenames = set(AGENTS.values())
for filename in filenames: for filename in filenames:
filepath = MonkeyDownload.get_executable_full_path(filename) filepath = get_executable_full_path(filename)
if os.path.isfile(filepath): if filepath.is_file():
with open(filepath, "rb") as monkey_exec_file: with open(filepath, "rb") as monkey_exec_file:
file_contents = monkey_exec_file.read() file_contents = monkey_exec_file.read()
logger.debug( file_sha256_hash = filename, hashlib.sha256(file_contents).hexdigest()
"{} hashes:\nSHA-256 {}".format( logger.debug(f"{filename} hash:\nSHA-256 {file_sha256_hash}")
filename, hashlib.sha256(file_contents).hexdigest()
)
)
else: else:
logger.debug("No monkey executable for {}.".format(filepath)) logger.debug(f"No monkey executable for {filepath}")
def get_agent_executable_path(host_os: str) -> Path:
try:
agent_path = get_executable_full_path(AGENTS[host_os])
logger.debug(f"Monkey exec found for os: {host_os}, {agent_path}")
return agent_path
except KeyError:
logger.warning(f"No monkey executables could be found for the host os: {host_os}")
raise UnsupportedOSError(
f'No Agents are available for unsupported operating system "{host_os}"'
)
def get_executable_full_path(executable_filename: str) -> Path:
return Path(MONKEY_ISLAND_ABS_PATH) / "cc" / "binaries" / executable_filename

View File

@ -5,8 +5,8 @@ import stat
import subprocess import subprocess
from shutil import copyfile from shutil import copyfile
from monkey_island.cc.resources.monkey_download import get_monkey_executable from monkey_island.cc.resources.monkey_download import get_agent_executable_path
from monkey_island.cc.server_utils.consts import ISLAND_PORT, MONKEY_ISLAND_ABS_PATH from monkey_island.cc.server_utils.consts import ISLAND_PORT
from monkey_island.cc.services.utils.network_utils import local_ip_addresses from monkey_island.cc.services.utils.network_utils import local_ip_addresses
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -25,12 +25,13 @@ class LocalMonkeyRunService:
@staticmethod @staticmethod
def run_local_monkey(): def run_local_monkey():
# get the monkey executable suitable to run on the server # get the monkey executable suitable to run on the server
result = get_monkey_executable(platform.system().lower()) try:
if not result: src_path = get_agent_executable_path(platform.system().lower())
return False, "OS Type not found" except Exception as ex:
logger.error(f"Error running agent from island: {ex}")
return False, str(ex)
src_path = os.path.join(MONKEY_ISLAND_ABS_PATH, "cc", "binaries", result["filename"]) dest_path = LocalMonkeyRunService.DATA_DIR / src_path.name
dest_path = os.path.join(LocalMonkeyRunService.DATA_DIR, result["filename"])
# copy the executable to temp path (don't run the monkey from its current location as it may # copy the executable to temp path (don't run the monkey from its current location as it may
# delete itself) # delete itself)