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/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

View File

@ -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
```

View File

@ -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 = <<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
user_data_windows_64 = <<EOF
@ -95,31 +68,10 @@ add-type @"
"@
[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
</powershell>
<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
}

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -117,9 +117,9 @@ def init_api_resources(api):
api.add_resource(Authenticate, "/api/auth")
api.add_resource(
Monkey,
"/api/monkey",
"/api/monkey/<string:guid>",
"/api/monkey/<string:guid>/<string:config_format>",
"/api/agent",
"/api/agent/<string:guid>",
"/api/agent/<string:guid>/<string:config_format>",
)
api.add_resource(LocalRun, "/api/local-monkey")
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(
MonkeyDownload,
"/api/monkey/download/<string:host_os>",
"/api/agent/download/<string:host_os>",
)
api.add_resource(NetMap, "/api/netmap")
api.add_resource(Edge, "/api/netmap/edge")

View File

@ -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/<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.
if config_format == "legacy":
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
: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,39 +84,35 @@ 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/monkey/download/monkey-linux-"
+ bit_text
+ r"; chmod +x monkey-linux-"
+ bit_text
+ r"; ./monkey-linux-"
+ bit_text
+ r":5000/api/agent/download/linux "
+ 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://"
+ 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'; "
)
@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)
)

View File

@ -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;`;

View File

@ -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`;

View File

@ -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`;