From c0da5b7103fab7f6905be2cf827f2a4dca14ba16 Mon Sep 17 00:00:00 2001 From: Ilija Lazoroski Date: Fri, 15 Apr 2022 15:38:40 +0200 Subject: [PATCH 1/5] Island: Rename api/monkey endpoint to api/agent --- monkey/monkey_island/cc/app.py | 8 ++++---- monkey/monkey_island/cc/resources/monkey.py | 2 +- monkey/monkey_island/cc/services/remote_run_aws.py | 8 ++++---- .../pages/RunMonkeyPage/commands/local_linux_curl.js | 2 +- .../pages/RunMonkeyPage/commands/local_linux_wget.js | 2 +- .../RunMonkeyPage/commands/local_windows_powershell.js | 2 +- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/monkey/monkey_island/cc/app.py b/monkey/monkey_island/cc/app.py index 792888a19..f6975eb36 100644 --- a/monkey/monkey_island/cc/app.py +++ b/monkey/monkey_island/cc/app.py @@ -118,9 +118,9 @@ def init_api_resources(api): api.add_resource(Authenticate, "/api/auth") api.add_resource( Monkey, - "/api/monkey", - "/api/monkey/", - "/api/monkey//", + "/api/agent", + "/api/agent/", + "/api/agent//", ) api.add_resource(LocalRun, "/api/local-monkey") api.add_resource(ClientRun, "/api/client-monkey") @@ -132,7 +132,7 @@ def init_api_resources(api): api.add_resource(ConfigurationImport, "/api/configuration/import") api.add_resource( MonkeyDownload, - "/api/monkey/download/", + "/api/agent/download/", ) api.add_resource(NetMap, "/api/netmap") api.add_resource(Edge, "/api/netmap/edge") diff --git a/monkey/monkey_island/cc/resources/monkey.py b/monkey/monkey_island/cc/resources/monkey.py index 9e4cf47af..a11f9ffb8 100644 --- a/monkey/monkey_island/cc/resources/monkey.py +++ b/monkey/monkey_island/cc/resources/monkey.py @@ -26,7 +26,7 @@ class Monkey(flask_restful.Resource): if guid: monkey_json = mongo.db.monkey.find_one_or_404({"guid": guid}) # TODO: When the "legacy" format is no longer needed, update this logic and remove the - # "/api/monkey//" route. Also considering not + # "/api/agent//" route. Also considering not # flattening the config in the first place. if config_format == "legacy": ConfigService.decrypt_flat_config(monkey_json["config"]) diff --git a/monkey/monkey_island/cc/services/remote_run_aws.py b/monkey/monkey_island/cc/services/remote_run_aws.py index ae9d910ea..fcabb6d86 100644 --- a/monkey/monkey_island/cc/services/remote_run_aws.py +++ b/monkey/monkey_island/cc/services/remote_run_aws.py @@ -131,7 +131,8 @@ class RemoteRunAwsService: return ( r"wget --no-check-certificate https://" + island_ip - + r":5000/api/monkey/download/monkey-linux-" + + r":5000/api/agent/download/linux " + + r"-O monkey-linux-" + bit_text + r"; chmod +x monkey-linux-" + bit_text @@ -148,9 +149,8 @@ class RemoteRunAwsService: r"[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {" r"$true}; (New-Object System.Net.WebClient).DownloadFile('https://" + island_ip - + r":5000/api/monkey/download/monkey-windows-" - + bit_text - + r".exe','.\\monkey.exe'); " + + r":5000/api/agent/download/windows'" + + r"'.\\monkey.exe'); " r";Start-Process -FilePath '.\\monkey.exe' " r"-ArgumentList 'm0nk3y -s " + island_ip + r":5000'; " ) diff --git a/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/commands/local_linux_curl.js b/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/commands/local_linux_curl.js index 6daf29f18..2f45ce457 100644 --- a/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/commands/local_linux_curl.js +++ b/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/commands/local_linux_curl.js @@ -1,5 +1,5 @@ export default function generateLocalLinuxCurl(ip, username) { - let command = `curl https://${ip}:5000/api/monkey/download/linux -k ` + let command = `curl https://${ip}:5000/api/agent/download/linux -k ` + `-o monkey-linux-64; ` + `chmod +x monkey-linux-64; ` + `./monkey-linux-64 m0nk3y -s ${ip}:5000;`; diff --git a/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/commands/local_linux_wget.js b/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/commands/local_linux_wget.js index 2549c7272..d03b9a4f7 100644 --- a/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/commands/local_linux_wget.js +++ b/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/commands/local_linux_wget.js @@ -1,5 +1,5 @@ export default function generateLocalLinuxWget(ip, username) { - let command = `wget --no-check-certificate https://${ip}:5000/api/monkey/download/` + let command = `wget --no-check-certificate https://${ip}:5000/api/agent/download/` + `linux -O ./monkey-linux-64; ` + `chmod +x monkey-linux-64; ` + `./monkey-linux-64 m0nk3y -s ${ip}:5000`; diff --git a/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/commands/local_windows_powershell.js b/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/commands/local_windows_powershell.js index ea068dfb5..8c194c252 100644 --- a/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/commands/local_windows_powershell.js +++ b/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/commands/local_windows_powershell.js @@ -1,7 +1,7 @@ function getAgentDownloadCommand(ip) { return `$execCmd = @"\r\n` + `[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {\`$true};` - + `(New-Object System.Net.WebClient).DownloadFile('https://${ip}:5000/api/monkey/download/windows',` + + `(New-Object System.Net.WebClient).DownloadFile('https://${ip}:5000/api/agent/download/windows',` + `"""$env:TEMP\\monkey.exe""");Start-Process -FilePath '$env:TEMP\\monkey.exe' -ArgumentList 'm0nk3y -s ${ip}:5000';` + `\r\n"@; \r\n` + `Start-Process -FilePath powershell.exe -ArgumentList $execCmd`; From 3597e08628fd18e60fb62f8dc10895e645a2b28d Mon Sep 17 00:00:00 2001 From: Ilija Lazoroski Date: Fri, 15 Apr 2022 15:39:59 +0200 Subject: [PATCH 2/5] Agent: Rename api/monkey endpoint to api/agent --- monkey/infection_monkey/control.py | 6 +++--- monkey/infection_monkey/exploit/caching_agent_repository.py | 2 +- monkey/infection_monkey/master/control_channel.py | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/monkey/infection_monkey/control.py b/monkey/infection_monkey/control.py index 54a65d04a..ce4d14840 100644 --- a/monkey/infection_monkey/control.py +++ b/monkey/infection_monkey/control.py @@ -50,7 +50,7 @@ class ControlClient(object): monkey["tunnel"] = ControlClient.proxies.get("https") requests.post( # noqa: DUO123 - "https://%s/api/monkey" % (WormConfiguration.current_server,), + "https://%s/api/agent" % (WormConfiguration.current_server,), data=json.dumps(monkey), headers={"content-type": "application/json"}, verify=False, @@ -173,7 +173,7 @@ class ControlClient(object): return try: reply = requests.get( # noqa: DUO123 - "https://%s/api/monkey/%s/legacy" % (WormConfiguration.current_server, GUID), + "https://%s/api/agent/%s/legacy" % (WormConfiguration.current_server, GUID), verify=False, proxies=ControlClient.proxies, timeout=MEDIUM_REQUEST_TIMEOUT, @@ -210,7 +210,7 @@ class ControlClient(object): return try: requests.patch( # noqa: DUO123 - "https://%s/api/monkey/%s" % (WormConfiguration.current_server, GUID), + "https://%s/api/agent/%s" % (WormConfiguration.current_server, GUID), data=json.dumps({"config_error": True}), headers={"content-type": "application/json"}, verify=False, diff --git a/monkey/infection_monkey/exploit/caching_agent_repository.py b/monkey/infection_monkey/exploit/caching_agent_repository.py index 9d24746ad..dbe58f58f 100644 --- a/monkey/infection_monkey/exploit/caching_agent_repository.py +++ b/monkey/infection_monkey/exploit/caching_agent_repository.py @@ -33,7 +33,7 @@ class CachingAgentRepository(IAgentRepository): @lru_cache(maxsize=None) def _download_binary_from_island(self, os: str) -> bytes: response = requests.get( # noqa: DUO123 - f"{self._island_url}/api/monkey/download/{os}", + f"{self._island_url}/api/agent/download/{os}", verify=False, proxies=self._proxies, timeout=MEDIUM_REQUEST_TIMEOUT, diff --git a/monkey/infection_monkey/master/control_channel.py b/monkey/infection_monkey/master/control_channel.py index a74724991..ad8361c62 100644 --- a/monkey/infection_monkey/master/control_channel.py +++ b/monkey/infection_monkey/master/control_channel.py @@ -50,7 +50,7 @@ class ControlChannel(IControlChannel): def get_config(self) -> dict: try: response = requests.get( # noqa: DUO123 - "https://%s/api/monkey/%s" % (WormConfiguration.current_server, self._agent_id), + "https://%s/api/agent/%s" % (WormConfiguration.current_server, self._agent_id), verify=False, proxies=ControlClient.proxies, timeout=SHORT_REQUEST_TIMEOUT, From a740e92784c3a896993bf60d6e5943f6642fc5a7 Mon Sep 17 00:00:00 2001 From: Ilija Lazoroski Date: Fri, 15 Apr 2022 15:40:34 +0200 Subject: [PATCH 3/5] Envs: Rename api/monkey endpoint to api/agent * Remove 32-bitness * Fix api/agent/download endpoint --- envs/os_compatibility/README.md | 10 ++-- envs/os_compatibility/terraform/instances.tf | 52 +------------------- 2 files changed, 7 insertions(+), 55 deletions(-) diff --git a/envs/os_compatibility/README.md b/envs/os_compatibility/README.md index e0ad30dec..f8b0586d0 100644 --- a/envs/os_compatibility/README.md +++ b/envs/os_compatibility/README.md @@ -2,9 +2,9 @@ ## About -OS compatibility is an environment on AWS that +OS compatibility is an environment on AWS that is designed to test monkey binary compatibility on -different operating systems. +different operating systems. This environment is deployed using terraform scripts located in this directory. @@ -33,7 +33,7 @@ terraform apply 1. Launch os_compat_ISLAND machine and upload your binaries/update island. Reset island environment. 2. Launch/Reboot all other os_compat test machines (Can be filtered with tag "Purpose: os_compat_instance") 3. Wait until machines boot and run monkey -4. Launch `test_compatibility.py` pytest script with island ip parameter +4. Launch `test_compatibility.py` pytest script with island ip parameter (e.g. `test_compatibility.py --island 111.111.111.111:5000`) ## Machines @@ -68,13 +68,13 @@ Example commands: ```cmd [System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy Set-MpPreference -DisableRealtimeMonitoring $true -ErrorAction SilentlyContinue -Invoke-WebRequest -Uri 'https://10.0.0.251:5000/api/monkey/download/monkey-windows-64.exe' -OutFile 'C:\windows\temp\monkey-windows-64.exe' -UseBasicParsing +Invoke-WebRequest -Uri 'https://10.0.0.251:5000/api/agent/download/windows' -OutFile 'C:\windows\temp\monkey-windows-64.exe' -UseBasicParsing C:\windows\temp\monkey-windows-64.exe m0nk3y -s 10.0.0.251:5000 ``` - Bash: ```shell script -wget --no-check-certificate -q https://10.0.0.251:5000/api/monkey/download/monkey-linux-64 -O ./monkey-linux-64 || curl https://10.0.0.251:5000/api/monkey/download/monkey-linux-64 -k -o monkey-linux-64 +wget --no-check-certificate -q https://10.0.0.251:5000/api/agent/download/linux -O ./monkey-linux-64 || curl https://10.0.0.251:5000/api/agent/download/linux -k -o monkey-linux-64 chmod +x ./monkey-linux-64 ./monkey-linux-64 m0nk3y -s 10.0.0.251:5000 ``` diff --git a/envs/os_compatibility/terraform/instances.tf b/envs/os_compatibility/terraform/instances.tf index 44b2f8a3d..065f5039c 100644 --- a/envs/os_compatibility/terraform/instances.tf +++ b/envs/os_compatibility/terraform/instances.tf @@ -47,37 +47,10 @@ Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="userdata.txt" #!/bin/bash rm ./monkey-linux-64 -wget --no-check-certificate -q https://10.0.0.251:5000/api/monkey/download/monkey-linux-64 -O ./monkey-linux-64 || curl https://10.0.0.251:5000/api/monkey/download/monkey-linux-64 -k -o monkey-linux-64 +wget --no-check-certificate -q https://10.0.0.251:5000/api/agent/download/linux -O ./monkey-linux-64 || curl https://10.0.0.251:5000/api/agent/download/linux -k -o monkey-linux-64 chmod +x ./monkey-linux-64 ./monkey-linux-64 m0nk3y -s 10.0.0.251:5000 --// -EOF - - user_data_linux_32 = < true -EOF - - user_data_windows_32 = < -add-type @" - using System.Net; - using System.Security.Cryptography.X509Certificates; - public class TrustAllCertsPolicy : ICertificatePolicy { - public bool CheckValidationResult( - ServicePoint srvPoint, X509Certificate certificate, - WebRequest request, int certificateProblem) { - return true; - } - } -"@ -[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy -Set-MpPreference -DisableRealtimeMonitoring $true -ErrorAction SilentlyContinue -Invoke-WebRequest -Uri 'https://10.0.0.251:5000/api/monkey/download/monkey-windows-32.exe' -OutFile 'C:\windows\temp\monkey-windows-32.exe' -UseBasicParsing -C:\windows\temp\monkey-windows-32.exe m0nk3y -s 10.0.0.251:5000 - -true EOF } From 743efe37dc9aa210b3c4fb88ecfd86921aa3ae90 Mon Sep 17 00:00:00 2001 From: Ilija Lazoroski Date: Mon, 18 Apr 2022 13:50:51 +0200 Subject: [PATCH 4/5] Changelog: Add entry for renaming api/monkey endpoint to api/agent --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 15f7998f3..b37b38dbb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,7 @@ Changelog](https://keepachangelog.com/en/1.0.0/). - The "/api/test/clear_caches" endpoint to "/api/test/clear-caches". #1888 - The "/api/netmap/nodeStates" endpoint to "/api/netmap/node-states". #1888 - All "/api/monkey_control" endpoints to "/api/monkey-control". #1888 +- All "/api/monkey" endpoints to "/api/agent". #1888 ### Removed - VSFTPD exploiter. #1533 From ab24bf0d72ea0aae37b2f880744af0ab5a7808ba Mon Sep 17 00:00:00 2001 From: Ilija Lazoroski Date: Tue, 19 Apr 2022 11:27:20 +0200 Subject: [PATCH 5/5] Island: Remove bitness functionality from RemoteRunAws service --- .../cc/services/remote_run_aws.py | 73 ++++--------------- 1 file changed, 13 insertions(+), 60 deletions(-) diff --git a/monkey/monkey_island/cc/services/remote_run_aws.py b/monkey/monkey_island/cc/services/remote_run_aws.py index fcabb6d86..9f94a4d0b 100644 --- a/monkey/monkey_island/cc/services/remote_run_aws.py +++ b/monkey/monkey_island/cc/services/remote_run_aws.py @@ -41,14 +41,12 @@ class RemoteRunAwsService: :param island_ip: IP of island the monkey will communicate with :return: Dictionary with instance ids as keys, and True/False as values if succeeded or not """ - instances_bitness = RemoteRunAwsService.get_bitness(instances) return CmdRunner.run_multiple_commands( instances, - lambda instance: RemoteRunAwsService.run_aws_monkey_cmd_async( + lambda instance: RemoteRunAwsService._run_aws_monkey_cmd_async( instance["instance_id"], RemoteRunAwsService._is_linux(instance["os"]), island_ip, - instances_bitness[instance["instance_id"]], ), lambda _, result: result.is_success, ) @@ -65,60 +63,19 @@ class RemoteRunAwsService: AwsService.set_region(RemoteRunAwsService.aws_instance.region) @staticmethod - def get_bitness(instances): - """ - For all given instances, checks whether they're 32 or 64 bit. - :param instances: List of instances to check - :return: Dictionary with instance ids as keys, and True/False as values. True if 64bit, - False otherwise - """ - return CmdRunner.run_multiple_commands( - instances, - lambda instance: RemoteRunAwsService.run_aws_bitness_cmd_async( - instance["instance_id"], RemoteRunAwsService._is_linux(instance["os"]) - ), - lambda instance, result: RemoteRunAwsService._get_bitness_by_result( - RemoteRunAwsService._is_linux(instance["os"]), result - ), - ) - - @staticmethod - def _get_bitness_by_result(is_linux, result): - if not result.is_success: - return None - elif is_linux: - return result.stdout.find("i686") == -1 # i686 means 32bit - else: - return ( - result.stdout.lower().find("programfiles(x86)") != -1 - ) # if not found it means 32bit - - @staticmethod - def run_aws_bitness_cmd_async(instance_id, is_linux): - """ - Runs an AWS command to check bitness - :param instance_id: Instance ID of target - :param is_linux: Whether target is linux - :return: Cmd - """ - cmd_text = "uname -m" if is_linux else "Get-ChildItem Env:" - return RemoteRunAwsService.run_aws_cmd_async(instance_id, is_linux, cmd_text) - - @staticmethod - def run_aws_monkey_cmd_async(instance_id, is_linux, island_ip, is_64bit): + def _run_aws_monkey_cmd_async(instance_id, is_linux, island_ip): """ Runs a monkey remotely using AWS :param instance_id: Instance ID of target :param is_linux: Whether target is linux :param island_ip: IP of the island which the instance will try to connect to - :param is_64bit: Whether the instance is 64bit :return: Cmd """ - cmd_text = RemoteRunAwsService._get_run_monkey_cmd_line(is_linux, is_64bit, island_ip) - return RemoteRunAwsService.run_aws_cmd_async(instance_id, is_linux, cmd_text) + cmd_text = RemoteRunAwsService._get_run_monkey_cmd_line(is_linux, island_ip) + return RemoteRunAwsService._run_aws_cmd_async(instance_id, is_linux, cmd_text) @staticmethod - def run_aws_cmd_async(instance_id, is_linux, cmd_line): + def _run_aws_cmd_async(instance_id, is_linux, cmd_line): cmd_runner = AwsCmdRunner(is_linux, instance_id) return Cmd(cmd_runner, cmd_runner.run_command_async(cmd_line)) @@ -127,24 +84,21 @@ class RemoteRunAwsService: return "linux" == os @staticmethod - def _get_run_monkey_cmd_linux_line(bit_text, island_ip): + def _get_run_monkey_cmd_linux_line(island_ip): return ( r"wget --no-check-certificate https://" + island_ip + r":5000/api/agent/download/linux " - + r"-O monkey-linux-" - + bit_text - + r"; chmod +x monkey-linux-" - + bit_text - + r"; ./monkey-linux-" - + bit_text + + r"-O monkey-linux-64" + + r"; chmod +x monkey-linux-64" + + r"; ./monkey-linux-64" + r" m0nk3y -s " + island_ip + r":5000" ) @staticmethod - def _get_run_monkey_cmd_windows_line(bit_text, island_ip): + def _get_run_monkey_cmd_windows_line(island_ip): return ( r"[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {" r"$true}; (New-Object System.Net.WebClient).DownloadFile('https://" @@ -156,10 +110,9 @@ class RemoteRunAwsService: ) @staticmethod - def _get_run_monkey_cmd_line(is_linux, is_64bit, island_ip): - bit_text = "64" if is_64bit else "32" + def _get_run_monkey_cmd_line(is_linux, island_ip): return ( - RemoteRunAwsService._get_run_monkey_cmd_linux_line(bit_text, island_ip) + RemoteRunAwsService._get_run_monkey_cmd_linux_line(island_ip) if is_linux - else RemoteRunAwsService._get_run_monkey_cmd_windows_line(bit_text, island_ip) + else RemoteRunAwsService._get_run_monkey_cmd_windows_line(island_ip) )