Merge pull request #1893 from guardicore/1888-rename-monkey-endpoint

1888 rename monkey endpoint
This commit is contained in:
Mike Salvatore 2022-04-19 07:37:31 -04:00 committed by GitHub
commit 587331dbdb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 37 additions and 131 deletions

View File

@ -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/test/clear_caches" endpoint to "/api/test/clear-caches". #1888
- The "/api/netmap/nodeStates" endpoint to "/api/netmap/node-states". #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_control" endpoints to "/api/monkey-control". #1888
- All "/api/monkey" endpoints to "/api/agent". #1888
### Removed ### Removed
- VSFTPD exploiter. #1533 - VSFTPD exploiter. #1533

View File

@ -68,13 +68,13 @@ Example commands:
```cmd ```cmd
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy [System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
Set-MpPreference -DisableRealtimeMonitoring $true -ErrorAction SilentlyContinue 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 C:\windows\temp\monkey-windows-64.exe m0nk3y -s 10.0.0.251:5000
``` ```
- Bash: - Bash:
```shell script ```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 chmod +x ./monkey-linux-64
./monkey-linux-64 m0nk3y -s 10.0.0.251:5000 ./monkey-linux-64 m0nk3y -s 10.0.0.251:5000
``` ```

View File

@ -47,37 +47,10 @@ Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="userdata.txt" Content-Disposition: attachment; filename="userdata.txt"
#!/bin/bash #!/bin/bash
rm ./monkey-linux-64 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 chmod +x ./monkey-linux-64
./monkey-linux-64 m0nk3y -s 10.0.0.251:5000 ./monkey-linux-64 m0nk3y -s 10.0.0.251:5000
--// --//
EOF
user_data_linux_32 = <<EOF
Content-Type: multipart/mixed; boundary="//"
MIME-Version: 1.0
--//
Content-Type: text/cloud-config; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="cloud-config.txt"
#cloud-config
cloud_final_modules:
- [scripts-user, always]
--//
Content-Type: text/x-shellscript; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="userdata.txt"
#!/bin/bash
rm ./monkey-linux-32
wget --no-check-certificate -q https://10.0.0.251:5000/api/monkey/download/monkey-linux-32 -O ./monkey-linux-32 || curl https://10.0.0.251:5000/api/monkey/download/monkey-linux-32 -k -o monkey-linux-32
chmod +x ./monkey-linux-32
./monkey-linux-32 m0nk3y -s 10.0.0.251:5000
--//
EOF EOF
user_data_windows_64 = <<EOF user_data_windows_64 = <<EOF
@ -95,31 +68,10 @@ add-type @"
"@ "@
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy [System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
Set-MpPreference -DisableRealtimeMonitoring $true -ErrorAction SilentlyContinue 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 C:\windows\temp\monkey-windows-64.exe m0nk3y -s 10.0.0.251:5000
</powershell> </powershell>
<persist>true</persist> <persist>true</persist>
EOF
user_data_windows_32 = <<EOF
<powershell>
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
</powershell>
<persist>true</persist>
EOF EOF
} }

View File

@ -50,7 +50,7 @@ class ControlClient(object):
monkey["tunnel"] = ControlClient.proxies.get("https") monkey["tunnel"] = ControlClient.proxies.get("https")
requests.post( # noqa: DUO123 requests.post( # noqa: DUO123
"https://%s/api/monkey" % (WormConfiguration.current_server,), "https://%s/api/agent" % (WormConfiguration.current_server,),
data=json.dumps(monkey), data=json.dumps(monkey),
headers={"content-type": "application/json"}, headers={"content-type": "application/json"},
verify=False, verify=False,
@ -173,7 +173,7 @@ class ControlClient(object):
return return
try: try:
reply = requests.get( # noqa: DUO123 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, verify=False,
proxies=ControlClient.proxies, proxies=ControlClient.proxies,
timeout=MEDIUM_REQUEST_TIMEOUT, timeout=MEDIUM_REQUEST_TIMEOUT,
@ -210,7 +210,7 @@ class ControlClient(object):
return return
try: try:
requests.patch( # noqa: DUO123 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}), data=json.dumps({"config_error": True}),
headers={"content-type": "application/json"}, headers={"content-type": "application/json"},
verify=False, verify=False,

View File

@ -33,7 +33,7 @@ class CachingAgentRepository(IAgentRepository):
@lru_cache(maxsize=None) @lru_cache(maxsize=None)
def _download_binary_from_island(self, os: str) -> bytes: def _download_binary_from_island(self, os: str) -> bytes:
response = requests.get( # noqa: DUO123 response = requests.get( # noqa: DUO123
f"{self._island_url}/api/monkey/download/{os}", f"{self._island_url}/api/agent/download/{os}",
verify=False, verify=False,
proxies=self._proxies, proxies=self._proxies,
timeout=MEDIUM_REQUEST_TIMEOUT, timeout=MEDIUM_REQUEST_TIMEOUT,

View File

@ -50,7 +50,7 @@ class ControlChannel(IControlChannel):
def get_config(self) -> dict: def get_config(self) -> dict:
try: try:
response = requests.get( # noqa: DUO123 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, verify=False,
proxies=ControlClient.proxies, proxies=ControlClient.proxies,
timeout=SHORT_REQUEST_TIMEOUT, timeout=SHORT_REQUEST_TIMEOUT,

View File

@ -117,9 +117,9 @@ def init_api_resources(api):
api.add_resource(Authenticate, "/api/auth") api.add_resource(Authenticate, "/api/auth")
api.add_resource( api.add_resource(
Monkey, Monkey,
"/api/monkey", "/api/agent",
"/api/monkey/<string:guid>", "/api/agent/<string:guid>",
"/api/monkey/<string:guid>/<string:config_format>", "/api/agent/<string:guid>/<string:config_format>",
) )
api.add_resource(LocalRun, "/api/local-monkey") api.add_resource(LocalRun, "/api/local-monkey")
api.add_resource(Telemetry, "/api/telemetry", "/api/telemetry/<string:monkey_guid>") api.add_resource(Telemetry, "/api/telemetry", "/api/telemetry/<string:monkey_guid>")
@ -130,7 +130,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/<string:host_os>", "/api/agent/download/<string:host_os>",
) )
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

@ -26,7 +26,7 @@ class Monkey(flask_restful.Resource):
if guid: if guid:
monkey_json = mongo.db.monkey.find_one_or_404({"guid": 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 # TODO: When the "legacy" format is no longer needed, update this logic and remove the
# "/api/monkey/<string:guid>/<string:config_format>" route. Also considering not # "/api/agent/<string:guid>/<string:config_format>" route. Also considering not
# flattening the config in the first place. # flattening the config in the first place.
if config_format == "legacy": if config_format == "legacy":
ConfigService.decrypt_flat_config(monkey_json["config"]) ConfigService.decrypt_flat_config(monkey_json["config"])

View File

@ -41,14 +41,12 @@ class RemoteRunAwsService:
:param island_ip: IP of island the monkey will communicate with :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 :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( return CmdRunner.run_multiple_commands(
instances, instances,
lambda instance: RemoteRunAwsService.run_aws_monkey_cmd_async( lambda instance: RemoteRunAwsService._run_aws_monkey_cmd_async(
instance["instance_id"], instance["instance_id"],
RemoteRunAwsService._is_linux(instance["os"]), RemoteRunAwsService._is_linux(instance["os"]),
island_ip, island_ip,
instances_bitness[instance["instance_id"]],
), ),
lambda _, result: result.is_success, lambda _, result: result.is_success,
) )
@ -65,60 +63,19 @@ class RemoteRunAwsService:
AwsService.set_region(RemoteRunAwsService.aws_instance.region) AwsService.set_region(RemoteRunAwsService.aws_instance.region)
@staticmethod @staticmethod
def get_bitness(instances): def _run_aws_monkey_cmd_async(instance_id, is_linux, island_ip):
"""
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):
""" """
Runs a monkey remotely using AWS Runs a monkey remotely using AWS
:param instance_id: Instance ID of target :param instance_id: Instance ID of target
:param is_linux: Whether target is linux :param is_linux: Whether target is linux
:param island_ip: IP of the island which the instance will try to connect to :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 :return: Cmd
""" """
cmd_text = RemoteRunAwsService._get_run_monkey_cmd_line(is_linux, is_64bit, island_ip) cmd_text = RemoteRunAwsService._get_run_monkey_cmd_line(is_linux, island_ip)
return RemoteRunAwsService.run_aws_cmd_async(instance_id, is_linux, cmd_text) return RemoteRunAwsService._run_aws_cmd_async(instance_id, is_linux, cmd_text)
@staticmethod @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) cmd_runner = AwsCmdRunner(is_linux, instance_id)
return Cmd(cmd_runner, cmd_runner.run_command_async(cmd_line)) return Cmd(cmd_runner, cmd_runner.run_command_async(cmd_line))
@ -127,39 +84,35 @@ class RemoteRunAwsService:
return "linux" == os return "linux" == os
@staticmethod @staticmethod
def _get_run_monkey_cmd_linux_line(bit_text, island_ip): def _get_run_monkey_cmd_linux_line(island_ip):
return ( return (
r"wget --no-check-certificate https://" r"wget --no-check-certificate https://"
+ island_ip + island_ip
+ r":5000/api/monkey/download/monkey-linux-" + r":5000/api/agent/download/linux "
+ bit_text + r"-O monkey-linux-64"
+ r"; chmod +x monkey-linux-" + r"; chmod +x monkey-linux-64"
+ bit_text + r"; ./monkey-linux-64"
+ r"; ./monkey-linux-"
+ bit_text
+ r" m0nk3y -s " + r" m0nk3y -s "
+ island_ip + island_ip
+ r":5000" + r":5000"
) )
@staticmethod @staticmethod
def _get_run_monkey_cmd_windows_line(bit_text, island_ip): def _get_run_monkey_cmd_windows_line(island_ip):
return ( return (
r"[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {" r"[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {"
r"$true}; (New-Object System.Net.WebClient).DownloadFile('https://" r"$true}; (New-Object System.Net.WebClient).DownloadFile('https://"
+ island_ip + island_ip
+ r":5000/api/monkey/download/monkey-windows-" + r":5000/api/agent/download/windows'"
+ bit_text + r"'.\\monkey.exe'); "
+ r".exe','.\\monkey.exe'); "
r";Start-Process -FilePath '.\\monkey.exe' " r";Start-Process -FilePath '.\\monkey.exe' "
r"-ArgumentList 'm0nk3y -s " + island_ip + r":5000'; " r"-ArgumentList 'm0nk3y -s " + island_ip + r":5000'; "
) )
@staticmethod @staticmethod
def _get_run_monkey_cmd_line(is_linux, is_64bit, island_ip): def _get_run_monkey_cmd_line(is_linux, island_ip):
bit_text = "64" if is_64bit else "32"
return ( return (
RemoteRunAwsService._get_run_monkey_cmd_linux_line(bit_text, island_ip) RemoteRunAwsService._get_run_monkey_cmd_linux_line(island_ip)
if is_linux 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)
) )

View File

@ -1,5 +1,5 @@
export default function generateLocalLinuxCurl(ip, username) { 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; ` + `-o monkey-linux-64; `
+ `chmod +x monkey-linux-64; ` + `chmod +x monkey-linux-64; `
+ `./monkey-linux-64 m0nk3y -s ${ip}:5000;`; + `./monkey-linux-64 m0nk3y -s ${ip}:5000;`;

View File

@ -1,5 +1,5 @@
export default function generateLocalLinuxWget(ip, username) { 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; ` + `linux -O ./monkey-linux-64; `
+ `chmod +x monkey-linux-64; ` + `chmod +x monkey-linux-64; `
+ `./monkey-linux-64 m0nk3y -s ${ip}:5000`; + `./monkey-linux-64 m0nk3y -s ${ip}:5000`;

View File

@ -1,7 +1,7 @@
function getAgentDownloadCommand(ip) { function getAgentDownloadCommand(ip) {
return `$execCmd = @"\r\n` return `$execCmd = @"\r\n`
+ `[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {\`$true};` + `[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';` + `"""$env:TEMP\\monkey.exe""");Start-Process -FilePath '$env:TEMP\\monkey.exe' -ArgumentList 'm0nk3y -s ${ip}:5000';`
+ `\r\n"@; \r\n` + `\r\n"@; \r\n`
+ `Start-Process -FilePath powershell.exe -ArgumentList $execCmd`; + `Start-Process -FilePath powershell.exe -ArgumentList $execCmd`;