forked from p15670423/monkey
Merge remote-tracking branch 'upstream/develop' into ui_performance_fixes
This commit is contained in:
commit
43a94b626d
|
@ -24,4 +24,3 @@ def no_gcp(request):
|
||||||
@pytest.fixture(scope='session')
|
@pytest.fixture(scope='session')
|
||||||
def quick_performance_tests(request):
|
def quick_performance_tests(request):
|
||||||
return request.config.getoption("--quick-performance-tests")
|
return request.config.getoption("--quick-performance-tests")
|
||||||
|
|
||||||
|
|
|
@ -90,9 +90,10 @@ class MonkeyIslandRequests(object):
|
||||||
@_Decorators.refresh_jwt_token
|
@_Decorators.refresh_jwt_token
|
||||||
def patch(self, url, data: Dict):
|
def patch(self, url, data: Dict):
|
||||||
return requests.patch(self.addr + url, # noqa: DUO123
|
return requests.patch(self.addr + url, # noqa: DUO123
|
||||||
data=data,
|
data=data,
|
||||||
headers=self.get_jwt_header(),
|
headers=self.get_jwt_header(),
|
||||||
verify=False)
|
verify=False
|
||||||
|
)
|
||||||
|
|
||||||
@_Decorators.refresh_jwt_token
|
@_Decorators.refresh_jwt_token
|
||||||
def delete(self, url):
|
def delete(self, url):
|
||||||
|
|
|
@ -10,9 +10,9 @@ class FakeMonkey:
|
||||||
self.original_guid = guid
|
self.original_guid = guid
|
||||||
self.fake_ip_generator = fake_ip_generator
|
self.fake_ip_generator = fake_ip_generator
|
||||||
self.on_island = on_island
|
self.on_island = on_island
|
||||||
self.fake_guid = str(random.randint(1000000000000, 9999999999999))
|
self.fake_guid = str(random.randint(1000000000000, 9999999999999)) # noqa: DUO102
|
||||||
self.fake_ips = fake_ip_generator.generate_fake_ips_for_real_ips(ips)
|
self.fake_ips = fake_ip_generator.generate_fake_ips_for_real_ips(ips)
|
||||||
|
|
||||||
def change_fake_data(self):
|
def change_fake_data(self):
|
||||||
self.fake_ips = self.fake_ip_generator.generate_fake_ips_for_real_ips(self.original_ips)
|
self.fake_ips = self.fake_ip_generator.generate_fake_ips_for_real_ips(self.original_ips)
|
||||||
self.fake_guid = str(random.randint(1000000000000, 9999999999999))
|
self.fake_guid = str(random.randint(1000000000000, 9999999999999)) # noqa: DUO102
|
||||||
|
|
|
@ -15,10 +15,10 @@ class GCPHandler(object):
|
||||||
self.zone = zone
|
self.zone = zone
|
||||||
try:
|
try:
|
||||||
# pass the key file to gcp
|
# pass the key file to gcp
|
||||||
subprocess.call(GCPHandler.get_auth_command(key_path), shell=True)
|
subprocess.call(GCPHandler.get_auth_command(key_path), shell=True) # noqa: DUO116
|
||||||
LOGGER.info("GCP Handler passed key")
|
LOGGER.info("GCP Handler passed key")
|
||||||
# set project
|
# set project
|
||||||
subprocess.call(GCPHandler.get_set_project_command(project_id), shell=True)
|
subprocess.call(GCPHandler.get_set_project_command(project_id), shell=True) # noqa: DUO116
|
||||||
LOGGER.info("GCP Handler set project")
|
LOGGER.info("GCP Handler set project")
|
||||||
LOGGER.info("GCP Handler initialized successfully")
|
LOGGER.info("GCP Handler initialized successfully")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
@ -32,14 +32,14 @@ class GCPHandler(object):
|
||||||
"""
|
"""
|
||||||
LOGGER.info("Setting up all GCP machines...")
|
LOGGER.info("Setting up all GCP machines...")
|
||||||
try:
|
try:
|
||||||
subprocess.call((GCPHandler.MACHINE_STARTING_COMMAND % (machine_list, self.zone)), shell=True)
|
subprocess.call((GCPHandler.MACHINE_STARTING_COMMAND % (machine_list, self.zone)), shell=True) # noqa: DUO116
|
||||||
LOGGER.info("GCP machines successfully started.")
|
LOGGER.info("GCP machines successfully started.")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
LOGGER.error("GCP Handler failed to start GCP machines: %s" % e)
|
LOGGER.error("GCP Handler failed to start GCP machines: %s" % e)
|
||||||
|
|
||||||
def stop_machines(self, machine_list):
|
def stop_machines(self, machine_list):
|
||||||
try:
|
try:
|
||||||
subprocess.call((GCPHandler.MACHINE_STOPPING_COMMAND % (machine_list, self.zone)), shell=True)
|
subprocess.call((GCPHandler.MACHINE_STOPPING_COMMAND % (machine_list, self.zone)), shell=True) # noqa: DUO116
|
||||||
LOGGER.info("GCP machines stopped successfully.")
|
LOGGER.info("GCP machines stopped successfully.")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
LOGGER.error("GCP Handler failed to stop network machines: %s" % e)
|
LOGGER.error("GCP Handler failed to stop network machines: %s" % e)
|
||||||
|
|
|
@ -13,6 +13,7 @@ GUID = str(uuid.getnode())
|
||||||
EXTERNAL_CONFIG_FILE = os.path.join(os.path.abspath(os.path.dirname(sys.argv[0])), 'monkey.bin')
|
EXTERNAL_CONFIG_FILE = os.path.join(os.path.abspath(os.path.dirname(sys.argv[0])), 'monkey.bin')
|
||||||
|
|
||||||
SENSITIVE_FIELDS = ["exploit_password_list", "exploit_user_list", "exploit_ssh_keys"]
|
SENSITIVE_FIELDS = ["exploit_password_list", "exploit_user_list", "exploit_ssh_keys"]
|
||||||
|
LOCAL_CONFIG_VARS = ["name", "id", "current_server", "max_depth"]
|
||||||
HIDDEN_FIELD_REPLACEMENT_CONTENT = "hidden"
|
HIDDEN_FIELD_REPLACEMENT_CONTENT = "hidden"
|
||||||
|
|
||||||
|
|
||||||
|
@ -22,7 +23,7 @@ class Configuration(object):
|
||||||
for key, value in list(formatted_data.items()):
|
for key, value in list(formatted_data.items()):
|
||||||
if key.startswith('_'):
|
if key.startswith('_'):
|
||||||
continue
|
continue
|
||||||
if key in ["name", "id", "current_server", "max_depth"]:
|
if key in LOCAL_CONFIG_VARS:
|
||||||
continue
|
continue
|
||||||
if self._depth_from_commandline and key == "depth":
|
if self._depth_from_commandline and key == "depth":
|
||||||
self.max_depth = value
|
self.max_depth = value
|
||||||
|
@ -290,7 +291,7 @@ class Configuration(object):
|
||||||
###########################
|
###########################
|
||||||
export_monkey_telems = False
|
export_monkey_telems = False
|
||||||
|
|
||||||
def get_hop_count(self):
|
def get_hop_distance_to_island(self):
|
||||||
return self.max_depth - self.depth
|
return self.max_depth - self.depth
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -327,7 +327,7 @@ class ControlClient(object):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def should_monkey_run(vulnerable_port: str) -> bool:
|
def should_monkey_run(vulnerable_port: str) -> bool:
|
||||||
if vulnerable_port and \
|
if vulnerable_port and \
|
||||||
WormConfiguration.get_hop_count() > 1 and \
|
WormConfiguration.get_hop_distance_to_island() > 1 and \
|
||||||
ControlClient.can_island_see_port(vulnerable_port) and \
|
ControlClient.can_island_see_port(vulnerable_port) and \
|
||||||
WormConfiguration.started_on_island:
|
WormConfiguration.started_on_island:
|
||||||
raise PlannedShutdownException("Monkey shouldn't run on current machine "
|
raise PlannedShutdownException("Monkey shouldn't run on current machine "
|
||||||
|
|
|
@ -116,11 +116,12 @@ class MonkeyDrops(object):
|
||||||
LOG.warning("Cannot set reference date to destination file")
|
LOG.warning("Cannot set reference date to destination file")
|
||||||
|
|
||||||
monkey_options = \
|
monkey_options = \
|
||||||
build_monkey_commandline_explicitly(self.opts.parent,
|
build_monkey_commandline_explicitly(parent=self.opts.parent,
|
||||||
self.opts.tunnel,
|
tunnel=self.opts.tunnel,
|
||||||
self.opts.server,
|
server=self.opts.server,
|
||||||
self.opts.depth,
|
depth=self.opts.depth,
|
||||||
self.opts.vulnerable_port)
|
location=None,
|
||||||
|
vulnerable_port=self.opts.vulnerable_port)
|
||||||
|
|
||||||
if OperatingSystem.Windows == SystemInfoCollector.get_os():
|
if OperatingSystem.Windows == SystemInfoCollector.get_os():
|
||||||
monkey_cmdline = MONKEY_CMDLINE_WINDOWS % {'monkey_path': self._config['destination_path']} + monkey_options
|
monkey_cmdline = MONKEY_CMDLINE_WINDOWS % {'monkey_path': self._config['destination_path']} + monkey_options
|
||||||
|
|
|
@ -46,19 +46,19 @@ def build_monkey_commandline_explicitly(parent=None, tunnel=None, server=None, d
|
||||||
cmdline = ""
|
cmdline = ""
|
||||||
|
|
||||||
if parent is not None:
|
if parent is not None:
|
||||||
cmdline += " -p " + parent
|
cmdline += f" -p {parent}"
|
||||||
if tunnel is not None:
|
if tunnel is not None:
|
||||||
cmdline += " -t " + tunnel
|
cmdline += f" -t {tunnel}"
|
||||||
if server is not None:
|
if server is not None:
|
||||||
cmdline += " -s " + server
|
cmdline += f" -s {server}"
|
||||||
if depth is not None:
|
if depth is not None:
|
||||||
if depth < 0:
|
if int(depth) < 0:
|
||||||
depth = 0
|
depth = 0
|
||||||
cmdline += f" -d {depth}"
|
cmdline += f" -d {depth}"
|
||||||
if location is not None:
|
if location is not None:
|
||||||
cmdline += f" -l {location}"
|
cmdline += f" -l {location}"
|
||||||
if vulnerable_port is not None:
|
if vulnerable_port is not None:
|
||||||
cmdline += f" -vp {str(vulnerable_port)}"
|
cmdline += f" -vp {vulnerable_port}"
|
||||||
|
|
||||||
return cmdline
|
return cmdline
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from infection_monkey.exploit.tools.helpers import build_monkey_commandline_explicitly
|
||||||
|
|
||||||
|
|
||||||
|
class TestHelpers(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_build_monkey_commandline_explicitly(self):
|
||||||
|
test1 = " -p 101010 -t 10.10.101.10 -s 127.127.127.127:5000 -d 0 -l C:\\windows\\abc -vp 80"
|
||||||
|
result1 = build_monkey_commandline_explicitly(101010,
|
||||||
|
"10.10.101.10",
|
||||||
|
"127.127.127.127:5000",
|
||||||
|
0,
|
||||||
|
"C:\\windows\\abc",
|
||||||
|
80)
|
||||||
|
|
||||||
|
test2 = " -p parent -s 127.127.127.127:5000 -d 0 -vp 80"
|
||||||
|
result2 = build_monkey_commandline_explicitly(parent="parent",
|
||||||
|
server="127.127.127.127:5000",
|
||||||
|
depth="0",
|
||||||
|
vulnerable_port="80")
|
||||||
|
|
||||||
|
self.assertEqual(test1, result1)
|
||||||
|
self.assertEqual(test2, result2)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
|
@ -74,6 +74,7 @@ class InfectionMonkey(object):
|
||||||
arg_parser.add_argument('-d', '--depth', type=int)
|
arg_parser.add_argument('-d', '--depth', type=int)
|
||||||
arg_parser.add_argument('-vp', '--vulnerable-port')
|
arg_parser.add_argument('-vp', '--vulnerable-port')
|
||||||
self._opts, self._args = arg_parser.parse_known_args(self._args)
|
self._opts, self._args = arg_parser.parse_known_args(self._args)
|
||||||
|
self.log_arguments()
|
||||||
|
|
||||||
self._parent = self._opts.parent
|
self._parent = self._opts.parent
|
||||||
self._default_tunnel = self._opts.tunnel
|
self._default_tunnel = self._opts.tunnel
|
||||||
|
@ -387,3 +388,7 @@ class InfectionMonkey(object):
|
||||||
def is_started_on_island(self):
|
def is_started_on_island(self):
|
||||||
island_ip = remove_port_from_ip_string(self._default_server)
|
island_ip = remove_port_from_ip_string(self._default_server)
|
||||||
return is_running_on_server(island_ip) and WormConfiguration.depth == WormConfiguration.max_depth
|
return is_running_on_server(island_ip) and WormConfiguration.depth == WormConfiguration.max_depth
|
||||||
|
|
||||||
|
def log_arguments(self):
|
||||||
|
arg_string = " ".join([f"{key}: {value}" for key, value in vars(self._opts).items()])
|
||||||
|
LOG.info(f"Monkey started with arguments: {arg_string}")
|
||||||
|
|
|
@ -10,7 +10,7 @@ import pymongo
|
||||||
from monkey_island.cc.environment import Environment
|
from monkey_island.cc.environment import Environment
|
||||||
|
|
||||||
# Disable "unverified certificate" warnings when sending requests to island
|
# Disable "unverified certificate" warnings when sending requests to island
|
||||||
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) # noqa: DUO131
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@ -29,7 +29,9 @@ class BootloaderHTTPRequestHandler(BaseHTTPRequestHandler):
|
||||||
post_data = self.rfile.read(content_length).decode()
|
post_data = self.rfile.read(content_length).decode()
|
||||||
island_server_path = BootloaderHTTPRequestHandler.get_bootloader_resource_url(self.request.getsockname()[0])
|
island_server_path = BootloaderHTTPRequestHandler.get_bootloader_resource_url(self.request.getsockname()[0])
|
||||||
island_server_path = parse.urljoin(island_server_path, self.path[1:])
|
island_server_path = parse.urljoin(island_server_path, self.path[1:])
|
||||||
r = requests.post(url=island_server_path, data=post_data, verify=False)
|
# The island server doesn't always have a correct SSL cert installed (By default it comes with a self signed one),
|
||||||
|
# that's why we're not verifying the cert in this request.
|
||||||
|
r = requests.post(url=island_server_path, data=post_data, verify=False) # noqa: DUO123
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if r.status_code != 200:
|
if r.status_code != 200:
|
||||||
|
|
|
@ -58,6 +58,7 @@ class Monkey(flask_restful.Resource):
|
||||||
return mongo.db.monkey.update({"_id": monkey["_id"]}, update, upsert=False)
|
return mongo.db.monkey.update({"_id": monkey["_id"]}, update, upsert=False)
|
||||||
|
|
||||||
# Used by monkey. can't secure.
|
# Used by monkey. can't secure.
|
||||||
|
# Called on monkey wakeup to initialize local configuration
|
||||||
@TestTelemStore.store_test_telem
|
@TestTelemStore.store_test_telem
|
||||||
def post(self, **kw):
|
def post(self, **kw):
|
||||||
monkey_json = json.loads(request.data)
|
monkey_json = json.loads(request.data)
|
||||||
|
|
|
@ -8,7 +8,7 @@ class RemotePortCheck(flask_restful.Resource):
|
||||||
|
|
||||||
# Used by monkey. can't secure.
|
# Used by monkey. can't secure.
|
||||||
def get(self, port):
|
def get(self, port):
|
||||||
if check_tcp_port(request.remote_addr, port):
|
if port and check_tcp_port(request.remote_addr, port):
|
||||||
return {"status": "port_visible"}
|
return {"status": "port_visible"}
|
||||||
else:
|
else:
|
||||||
return {"status": "port_invisible"}
|
return {"status": "port_invisible"}
|
||||||
|
|
Loading…
Reference in New Issue