From ff17237ea7e5c1d9d60d5738c55a2cf5b812c61a Mon Sep 17 00:00:00 2001 From: Shreya Malviya Date: Tue, 28 Jun 2022 15:48:19 -0700 Subject: [PATCH 01/13] Island: Remove old configuration schema's definitions --- .../credential_collector_classes.py | 25 ----- .../definitions/exploiter_classes.py | 105 ------------------ .../definitions/finger_classes.py | 48 -------- .../definitions/post_breach_actions.py | 105 ------------------ 4 files changed, 283 deletions(-) delete mode 100644 monkey/monkey_island/cc/services/config_schema/definitions/credential_collector_classes.py delete mode 100644 monkey/monkey_island/cc/services/config_schema/definitions/exploiter_classes.py delete mode 100644 monkey/monkey_island/cc/services/config_schema/definitions/finger_classes.py delete mode 100644 monkey/monkey_island/cc/services/config_schema/definitions/post_breach_actions.py diff --git a/monkey/monkey_island/cc/services/config_schema/definitions/credential_collector_classes.py b/monkey/monkey_island/cc/services/config_schema/definitions/credential_collector_classes.py deleted file mode 100644 index a16b8afac..000000000 --- a/monkey/monkey_island/cc/services/config_schema/definitions/credential_collector_classes.py +++ /dev/null @@ -1,25 +0,0 @@ -from common.common_consts.credential_collector_names import MIMIKATZ_COLLECTOR, SSH_COLLECTOR - -CREDENTIAL_COLLECTORS = { - "title": "Credential Collectors", - "description": "Click on a credential collector to find out what it collects.", - "type": "string", - "anyOf": [ - { - "type": "string", - "enum": [MIMIKATZ_COLLECTOR], - "title": "Mimikatz Credentials Collector", - "safe": True, - "info": "Collects credentials from Windows credential manager.", - "attack_techniques": ["T1003", "T1005"], - }, - { - "type": "string", - "enum": [SSH_COLLECTOR], - "title": "SSH Credentials Collector", - "safe": True, - "info": "Searches users' home directories and collects SSH keypairs.", - "attack_techniques": ["T1005", "T1145"], - }, - ], -} diff --git a/monkey/monkey_island/cc/services/config_schema/definitions/exploiter_classes.py b/monkey/monkey_island/cc/services/config_schema/definitions/exploiter_classes.py deleted file mode 100644 index 2ecaa977b..000000000 --- a/monkey/monkey_island/cc/services/config_schema/definitions/exploiter_classes.py +++ /dev/null @@ -1,105 +0,0 @@ -from monkey_island.cc.services.utils.typographic_symbols import WARNING_SIGN - -EXPLOITER_CLASSES = { - "title": "Exploiters", - "description": "Click on exploiter to get more information about it." - + WARNING_SIGN - + " Note that using unsafe exploits may cause crashes of the exploited " - "machine/service.", - "type": "string", - "anyOf": [ - { - "type": "string", - "enum": ["SmbExploiter"], - "title": "SMB Exploiter", - "safe": True, - "attack_techniques": ["T1110", "T1075", "T1035"], - "info": "Brute forces using credentials provided by user and" - " hashes gathered by mimikatz.", - "link": "https://www.guardicore.com/infectionmonkey/docs/reference" - "/exploiters/smbexec/", - }, - { - "type": "string", - "enum": ["WmiExploiter"], - "title": "WMI Exploiter", - "safe": True, - "attack_techniques": ["T1110", "T1106"], - "info": "Brute forces WMI (Windows Management Instrumentation) " - "using credentials provided by user and hashes gathered by " - "mimikatz.", - "link": "https://www.guardicore.com/infectionmonkey/docs/reference" - "/exploiters/wmiexec/", - }, - { - "type": "string", - "enum": ["MSSQLExploiter"], - "title": "MSSQL Exploiter", - "safe": True, - "attack_techniques": ["T1110"], - "info": "Tries to brute force into MsSQL server and uses insecure " - "configuration to execute commands on server.", - "link": "https://www.guardicore.com/infectionmonkey/docs/reference" - "/exploiters/mssql/", - }, - { - "type": "string", - "enum": ["SSHExploiter"], - "title": "SSH Exploiter", - "safe": True, - "attack_techniques": ["T1110", "T1145", "T1106"], - "info": "Brute forces using credentials provided by user and SSH keys " - "gathered from systems.", - "link": "https://www.guardicore.com/infectionmonkey/docs/reference" - "/exploiters/sshexec/", - }, - { - "type": "string", - "enum": ["HadoopExploiter"], - "title": "Hadoop/Yarn Exploiter", - "safe": True, - "info": "Remote code execution on HADOOP server with YARN and default settings. " - "Logic based on " - "https://github.com/vulhub/vulhub/tree/master/hadoop/unauthorized-yarn.", - "link": "https://www.guardicore.com/infectionmonkey/docs/reference/exploiters/hadoop/", - }, - { - "type": "string", - "enum": ["ZerologonExploiter"], - "title": "Zerologon Exploiter", - "safe": False, - "info": "Exploits a privilege escalation vulnerability (CVE-2020-1472) in a Windows " - "server domain controller (DC) by using the Netlogon Remote Protocol (MS-NRPC). " - "This exploiter changes the password of a Windows server DC account, steals " - "credentials, and then attempts to restore the original DC password. The victim DC " - "will be unable to communicate with other DCs until the original " - "password has been restored. If Infection Monkey fails to restore the " - "password automatically, you'll have to do it manually. For more " - "information, see the documentation.", - "link": "https://www.guardicore.com/infectionmonkey" - "/docs/reference/exploiters/zerologon/", - }, - { - "type": "string", - "enum": ["PowerShellExploiter"], - "title": "PowerShell Remoting Exploiter", - "info": "Exploits PowerShell remote execution setups. PowerShell Remoting uses Windows " - "Remote Management (WinRM) to allow users to run PowerShell commands on remote " - "computers.", - "safe": True, - "link": "https://www.guardicore.com/infectionmonkey" - "/docs/reference/exploiters/powershell", - }, - { - "type": "string", - "enum": ["Log4ShellExploiter"], - "title": "Log4Shell Exploiter", - "safe": True, - "info": "Exploits a software vulnerability (CVE-2021-44228) in Apache Log4j, a Java " - "logging framework. Exploitation is attempted on the following services — " - "Apache Solr, Apache Tomcat, Logstash.", - "link": "https://www.guardicore.com/infectionmonkey/docs/reference" - "/exploiters/log4shell/", - }, - ], -} diff --git a/monkey/monkey_island/cc/services/config_schema/definitions/finger_classes.py b/monkey/monkey_island/cc/services/config_schema/definitions/finger_classes.py deleted file mode 100644 index 1a983a899..000000000 --- a/monkey/monkey_island/cc/services/config_schema/definitions/finger_classes.py +++ /dev/null @@ -1,48 +0,0 @@ -FINGER_CLASSES = { - "title": "Fingerprinters", - "description": "Fingerprint modules collect info about external services " - "Infection Monkey scans.", - "type": "string", - "anyOf": [ - { - "type": "string", - "enum": ["SMBFinger"], - "title": "SMB Fingerprinter", - "safe": True, - "info": "Figures out if SMB is running and what's the version of it.", - "attack_techniques": ["T1210"], - }, - { - "type": "string", - "enum": ["SSHFinger"], - "title": "SSH Fingerprinter", - "safe": True, - "info": "Figures out if SSH is running.", - "attack_techniques": ["T1210"], - }, - { - "type": "string", - "enum": ["HTTPFinger"], - "title": "HTTP Fingerprinter", - "safe": True, - "info": "Checks if host has HTTP/HTTPS ports open.", - }, - { - "type": "string", - "enum": ["MSSQLFinger"], - "title": "MSSQL Fingerprinter", - "safe": True, - "info": "Checks if Microsoft SQL service is running and tries to gather " - "information about it.", - "attack_techniques": ["T1210"], - }, - { - "type": "string", - "enum": ["ElasticFinger"], - "title": "Elastic Fingerprinter", - "safe": True, - "info": "Checks if ElasticSearch is running and attempts to find it's " "version.", - "attack_techniques": ["T1210"], - }, - ], -} diff --git a/monkey/monkey_island/cc/services/config_schema/definitions/post_breach_actions.py b/monkey/monkey_island/cc/services/config_schema/definitions/post_breach_actions.py deleted file mode 100644 index d6831ed63..000000000 --- a/monkey/monkey_island/cc/services/config_schema/definitions/post_breach_actions.py +++ /dev/null @@ -1,105 +0,0 @@ -POST_BREACH_ACTIONS = { - "title": "Post-Breach Actions", - "description": "Runs scripts/commands on infected machines. These actions safely simulate what " - "an adversary might do after breaching a new machine. Used in ATT&CK and Zero trust reports.", - "type": "string", - "anyOf": [ - { - "type": "string", - "enum": ["CommunicateAsBackdoorUser"], - "title": "Communicate as Backdoor User", - "safe": True, - "info": "Attempts to create a new user, create HTTPS requests as that " - "user and delete the user " - "afterwards.", - "attack_techniques": ["T1136"], - }, - { - "type": "string", - "enum": ["ModifyShellStartupFiles"], - "title": "Modify Shell Startup Files", - "safe": True, - "info": "Attempts to modify shell startup files, like ~/.profile, " - "~/.bashrc, ~/.bash_profile " - "in linux, and profile.ps1 in windows. Reverts modifications done" - " afterwards.", - "attack_techniques": ["T1156", "T1504"], - }, - { - "type": "string", - "enum": ["HiddenFiles"], - "title": "Hidden Files and Directories", - "safe": True, - "info": "Attempts to create a hidden file and remove it afterward.", - "attack_techniques": ["T1158"], - }, - { - "type": "string", - "enum": ["TrapCommand"], - "title": "Trap Command", - "safe": True, - "info": "On Linux systems, attempts to trap a terminate signal in order " - "to execute a command upon receiving that signal. Removes the trap afterwards.", - "attack_techniques": ["T1154"], - }, - { - "type": "string", - "enum": ["ChangeSetuidSetgid"], - "title": "Setuid and Setgid", - "safe": True, - "info": "On Linux systems, attempts to set the setuid and setgid bits of " - "a new file. " - "Removes the file afterwards.", - "attack_techniques": ["T1166"], - }, - { - "type": "string", - "enum": ["ScheduleJobs"], - "title": "Job Scheduling", - "safe": True, - "info": "Attempts to create a scheduled job on the system and remove it.", - "attack_techniques": ["T1168", "T1053"], - }, - { - "type": "string", - "enum": ["Timestomping"], - "title": "Timestomping", - "safe": True, - "info": "Creates a temporary file and attempts to modify its time " - "attributes. Removes the file afterwards.", - "attack_techniques": ["T1099"], - }, - { - "type": "string", - "enum": ["SignedScriptProxyExecution"], - "title": "Signed Script Proxy Execution", - "safe": False, - "info": "On Windows systems, attempts to execute an arbitrary file " - "with the help of a pre-existing signed script.", - "attack_techniques": ["T1216"], - }, - { - "type": "string", - "enum": ["AccountDiscovery"], - "title": "Account Discovery", - "safe": True, - "info": "Attempts to get a listing of user accounts on the system.", - "attack_techniques": ["T1087"], - }, - { - "type": "string", - "enum": ["ClearCommandHistory"], - "title": "Clear Command History", - "safe": False, - "info": "Attempts to clear the command history.", - "attack_techniques": ["T1146"], - }, - { - "type": "string", - "enum": ["ProcessListCollection"], - "title": "Process List Collector", - "safe": True, - "info": "Collects a list of running processes on the machine.", - }, - ], -} From 2d960fc4d29d6d6b964c7da3436b91aea105929e Mon Sep 17 00:00:00 2001 From: Shreya Malviya Date: Tue, 28 Jun 2022 15:48:39 -0700 Subject: [PATCH 02/13] Island: Remove old configuration schema's properties --- .../cc/services/config_schema/basic.py | 65 --------- .../services/config_schema/basic_network.py | 96 ------------- .../cc/services/config_schema/internal.py | 135 ------------------ .../cc/services/config_schema/monkey.py | 93 ------------ .../cc/services/config_schema/ransomware.py | 71 --------- 5 files changed, 460 deletions(-) delete mode 100644 monkey/monkey_island/cc/services/config_schema/basic.py delete mode 100644 monkey/monkey_island/cc/services/config_schema/basic_network.py delete mode 100644 monkey/monkey_island/cc/services/config_schema/internal.py delete mode 100644 monkey/monkey_island/cc/services/config_schema/monkey.py delete mode 100644 monkey/monkey_island/cc/services/config_schema/ransomware.py diff --git a/monkey/monkey_island/cc/services/config_schema/basic.py b/monkey/monkey_island/cc/services/config_schema/basic.py deleted file mode 100644 index 0ce28a3d1..000000000 --- a/monkey/monkey_island/cc/services/config_schema/basic.py +++ /dev/null @@ -1,65 +0,0 @@ -BASIC = { - "title": "Exploits", - "type": "object", - "primary": True, - "properties": { - "exploiters": { - "title": "Exploiters", - "type": "object", - "description": "Choose which exploiters the Monkey will attempt.", - "properties": { - "exploiter_classes": { - "title": "Exploiters", - "type": "array", - "uniqueItems": True, - "items": {"$ref": "#/definitions/exploiter_classes"}, - "default": [ - "SmbExploiter", - "WmiExploiter", - "SSHExploiter", - "Log4ShellExploiter", - "HadoopExploiter", - "MSSQLExploiter", - "PowerShellExploiter", - ], - } - }, - }, - "credentials": { - "title": "Credentials", - "type": "object", - "properties": { - "exploit_user_list": { - "title": "Exploit user list", - "type": "array", - "uniqueItems": True, - "items": {"type": "string"}, - "default": ["Administrator", "root", "user"], - "description": "List of user names that will be used by exploiters that need " - "credentials, like " - "SSH brute-forcing.", - }, - "exploit_password_list": { - "title": "Exploit password list", - "type": "array", - "uniqueItems": True, - "items": { - "type": "string", - }, - "default": [ - "root", - "123456", - "password", - "123456789", - "qwerty", - "111111", - "iloveyou", - ], - "description": "List of passwords that will be used by exploiters that need " - "credentials, like " - "SSH brute-forcing.", - }, - }, - }, - }, -} diff --git a/monkey/monkey_island/cc/services/config_schema/basic_network.py b/monkey/monkey_island/cc/services/config_schema/basic_network.py deleted file mode 100644 index eceda4828..000000000 --- a/monkey/monkey_island/cc/services/config_schema/basic_network.py +++ /dev/null @@ -1,96 +0,0 @@ -from common.common_consts.validation_formats import IP, IP_RANGE -from monkey_island.cc.services.utils.typographic_symbols import WARNING_SIGN - -BASIC_NETWORK = { - "title": "Network", - "type": "object", - "properties": { - "scope": { - "title": "Scope", - "type": "object", - "properties": { - "info_box": { - "info": 'The Monkey scans its subnet if "Local network scan" is checked. ' - 'Additionally, the Monkey scans machines according to "Scan ' - 'target list".', - }, - "blocked_ips": { - "title": "Blocked IPs", - "type": "array", - "uniqueItems": True, - "items": { - "type": "string", - "format": IP, - }, - "default": [], - "description": "List of IPs that the Monkey will not scan.", - }, - "local_network_scan": { - "title": "Local network scan", - "type": "boolean", - "default": True, - "description": "Determines whether the Monkey will scan the local subnets of " - "machines it runs on, " - "in addition to the IPs that are configured manually in the " - '"Scan target list".', - }, - "depth": { - "title": "Scan depth", - "type": "integer", - "minimum": 1, - "default": 2, - "description": "Amount of hops allowed for the Monkey to spread from the " - "Island server. \n" - + WARNING_SIGN - + " Note that setting this value too high may result in the " - "Monkey propagating too far, " - 'if the "Local network scan" is enabled.', - }, - "subnet_scan_list": { - "title": "Scan target list", - "type": "array", - "uniqueItems": True, - "items": {"type": "string", "format": IP_RANGE}, - "default": [], - "description": "List of targets the Monkey will try to scan. Targets can be " - "IPs, subnets or hosts." - " Examples:\n" - '\tTarget a specific IP: "192.168.0.1"\n' - "\tTarget a subnet using a network range: " - '"192.168.0.5-192.168.0.20"\n' - '\tTarget a subnet using an IP mask: "192.168.0.5/24"\n' - '\tTarget a specific host: "printer.example"', - }, - }, - }, - "network_analysis": { - "title": "Network Analysis", - "type": "object", - "properties": { - "inaccessible_subnets": { - "title": "Network segmentation testing", - "type": "array", - "uniqueItems": True, - "items": {"type": "string", "format": IP_RANGE}, - "default": [], - "description": "Test for network segmentation by providing a list of network " - "segments " - "that should NOT be accessible to each other.\n\n" - "For example, if you configured the following three segments: " - '"10.0.0.0/24", "11.0.0.2/32", and "12.2.3.0/24", ' - "a Monkey running on 10.0.0.5 will try to access machines in " - "the following subnets: " - "11.0.0.2/32, 12.2.3.0/24. An alert on successful cross-segment " - "connections " - "will be shown in the reports. \n\n" - "Network segments can be IPs, subnets or hosts. Examples:\n" - '\tDefine a single-IP segment: "192.168.0.1"\n' - "\tDefine a segment using a network range: " - '"192.168.0.5-192.168.0.20"\n' - '\tDefine a segment using an subnet IP mask: "192.168.0.5/24"\n' - '\tDefine a single-host segment: "printer.example"', - } - }, - }, - }, -} diff --git a/monkey/monkey_island/cc/services/config_schema/internal.py b/monkey/monkey_island/cc/services/config_schema/internal.py deleted file mode 100644 index e0575ab36..000000000 --- a/monkey/monkey_island/cc/services/config_schema/internal.py +++ /dev/null @@ -1,135 +0,0 @@ -INTERNAL = { - "title": "Internal", - "type": "object", - "properties": { - "general": { - "title": "General", - "type": "object", - "properties": { - "keep_tunnel_open_time": { - "title": "Keep tunnel open time", - "type": "integer", - "default": 30, - "description": "Time to keep tunnel open before going down after last exploit " - "(in seconds)", - }, - }, - }, - "network": { - "title": "Network", - "type": "object", - "properties": { - "tcp_scanner": { - "title": "TCP scanner", - "type": "object", - "properties": { - "HTTP_PORTS": { - "title": "HTTP ports", - "type": "array", - "uniqueItems": True, - "items": {"type": "integer"}, - "default": [80, 8080, 443, 8008, 7001, 9200, 8983, 9600], - "description": "List of ports the monkey will check if are being used " - "for HTTP", - }, - "tcp_target_ports": { - "title": "TCP target ports", - "type": "array", - "uniqueItems": True, - "items": {"type": "integer"}, - "default": [ - 22, - 2222, - 445, - 135, - 3389, - 80, - 8080, - 443, - 8008, - 3306, - 7001, - 8088, - 5985, - 5986, - ], - "description": "List of TCP ports the monkey will check whether " - "they're open", - }, - "tcp_scan_timeout": { - "title": "TCP scan timeout", - "type": "integer", - "default": 3000, - "description": "Maximum time (in milliseconds) " - "to wait for TCP response", - }, - }, - }, - "ping_scanner": { - "title": "Ping scanner", - "type": "object", - "properties": { - "ping_scan_timeout": { - "title": "Ping scan timeout", - "type": "integer", - "default": 1000, - "description": "Maximum time (in milliseconds) to wait for ping " - "response", - } - }, - }, - }, - }, - "classes": { - "title": "Classes", - "type": "object", - "properties": { - "finger_classes": { - "title": "Fingerprint classes", - "type": "array", - "uniqueItems": True, - "items": {"$ref": "#/definitions/finger_classes"}, - "default": [ - "SMBFinger", - "SSHFinger", - "HTTPFinger", - "MSSQLFinger", - "ElasticFinger", - ], - } - }, - }, - "exploits": { - "title": "Exploits", - "type": "object", - "properties": { - "exploit_lm_hash_list": { - "title": "Exploit LM hash list", - "type": "array", - "uniqueItems": True, - "items": {"type": "string"}, - "default": [], - "description": "List of LM hashes to use on exploits using credentials", - "related_attack_techniques": ["T1075"], - }, - "exploit_ntlm_hash_list": { - "title": "Exploit NTLM hash list", - "type": "array", - "uniqueItems": True, - "items": {"type": "string"}, - "default": [], - "description": "List of NTLM hashes to use on exploits using credentials", - "related_attack_techniques": ["T1075"], - }, - "exploit_ssh_keys": { - "title": "SSH key pairs list", - "type": "array", - "uniqueItems": True, - "default": [], - "items": {"type": "string"}, - "description": "List of SSH key pairs to use, when trying to ssh into servers", - }, - }, - }, - }, -} diff --git a/monkey/monkey_island/cc/services/config_schema/monkey.py b/monkey/monkey_island/cc/services/config_schema/monkey.py deleted file mode 100644 index ed30a3c89..000000000 --- a/monkey/monkey_island/cc/services/config_schema/monkey.py +++ /dev/null @@ -1,93 +0,0 @@ -from common.common_consts.credential_collector_names import MIMIKATZ_COLLECTOR, SSH_COLLECTOR - -MONKEY = { - "title": "Monkey", - "type": "object", - "properties": { - "post_breach": { - "title": "Post breach", - "type": "object", - "properties": { - "custom_PBA_linux_cmd": { - "title": "Linux post-breach command", - "type": "string", - "default": "", - "description": "Command to be executed after breaching. " - "Use this field to run custom commands or execute uploaded " - "files on exploited machines.\nExample: " - '"chmod +x ./my_script.sh; ./my_script.sh ; rm ./my_script.sh"', - }, - "PBA_linux_file": { - "title": "Linux post-breach file", - "type": "string", - "format": "data-url", - "description": "File to be uploaded after breaching. " - "Use the 'Linux post-breach command' field to " - "change permissions, run, or delete the file. " - "Reference your file by filename.", - }, - "custom_PBA_windows_cmd": { - "title": "Windows post-breach command", - "type": "string", - "default": "", - "description": "Command to be executed after breaching. " - "Use this field to run custom commands or execute uploaded " - "files on exploited machines.\nExample: " - '"my_script.bat & del my_script.bat"', - }, - "PBA_windows_file": { - "title": "Windows post-breach file", - "type": "string", - "format": "data-url", - "description": "File to be uploaded after breaching. " - "Use the 'Windows post-breach command' field to " - "change permissions, run, or delete the file. " - "Reference your file by filename.", - }, - "PBA_windows_filename": { - "title": "Windows PBA filename", - "type": "string", - "default": "", - }, - "PBA_linux_filename": { - "title": "Linux PBA filename", - "type": "string", - "default": "", - }, - "post_breach_actions": { - "title": "Post breach actions", - "type": "array", - "uniqueItems": True, - "items": {"$ref": "#/definitions/post_breach_actions"}, - "default": [ - "CommunicateAsBackdoorUser", - "ModifyShellStartupFiles", - "HiddenFiles", - "TrapCommand", - "ChangeSetuidSetgid", - "ScheduleJobs", - "Timestomping", - "AccountDiscovery", - "ProcessListCollection", - ], - }, - }, - }, - "credential_collectors": { - "title": "Credential collection", - "type": "object", - "properties": { - "credential_collectors": { - "title": "Credential collectors", - "type": "array", - "uniqueItems": True, - "items": {"$ref": "#/definitions/credential_collectors"}, - "default": [ - MIMIKATZ_COLLECTOR, - SSH_COLLECTOR, - ], - }, - }, - }, - }, -} diff --git a/monkey/monkey_island/cc/services/config_schema/ransomware.py b/monkey/monkey_island/cc/services/config_schema/ransomware.py deleted file mode 100644 index dd77a175d..000000000 --- a/monkey/monkey_island/cc/services/config_schema/ransomware.py +++ /dev/null @@ -1,71 +0,0 @@ -from common.common_consts.validation_formats import ( - VALID_RANSOMWARE_TARGET_PATH_LINUX, - VALID_RANSOMWARE_TARGET_PATH_WINDOWS, -) - -RANSOMWARE = { - "title": "Ransomware", - "type": "object", - "properties": { - "encryption": { - "title": "Simulation", - "type": "object", - "description": "To simulate ransomware encryption, you'll need to provide Infection " - "Monkey with files that it can safely encrypt. On each machine where you would like " - "the ransomware simulation to run, create a directory and put some files in it." - "\n\nProvide the path to the directory that was created on each machine.", - "properties": { - "enabled": { - "title": "Encrypt files", - "type": "boolean", - "default": True, - "description": "Ransomware encryption will be simulated by flipping every bit " - "in the files contained within the target directories.", - }, - "info_box": { - "info": "No files will be encrypted if a directory is not specified or doesn't " - "exist on a victim machine.", - }, - "directories": { - "title": "Directories to encrypt", - "type": "object", - "properties": { - "linux_target_dir": { - "title": "Linux target directory", - "type": "string", - "format": VALID_RANSOMWARE_TARGET_PATH_LINUX, - "default": "", - "description": "A path to a directory on Linux systems that contains " - "files that you will allow Infection Monkey to encrypt. If no " - "directory is specified, no files will be encrypted.", - }, - "windows_target_dir": { - "title": "Windows target directory", - "type": "string", - "format": VALID_RANSOMWARE_TARGET_PATH_WINDOWS, - "default": "", - "description": "A path to a directory on Windows systems that contains " - "files that you will allow Infection Monkey to encrypt. If no " - "directory is specified, no files will be encrypted.", - }, - }, - }, - "text_box": { - "text": "Note: A README.txt will be left in the specified target " "directory.", - }, - }, - }, - "other_behaviors": { - "title": "Other behavior", - "type": "object", - "properties": { - "readme": { - "title": "Create a README.txt file", - "type": "boolean", - "default": True, - "description": "Creates a README.txt ransomware note on infected systems.", - } - }, - }, - }, -} From b883f502ed38aab619e046b7412de4773408ee99 Mon Sep 17 00:00:00 2001 From: Shreya Malviya Date: Tue, 28 Jun 2022 15:51:14 -0700 Subject: [PATCH 03/13] Island: Remove old configuration schema --- .../services/config_schema/config_schema.py | 35 ------------------- 1 file changed, 35 deletions(-) delete mode 100644 monkey/monkey_island/cc/services/config_schema/config_schema.py diff --git a/monkey/monkey_island/cc/services/config_schema/config_schema.py b/monkey/monkey_island/cc/services/config_schema/config_schema.py deleted file mode 100644 index 2993dc15e..000000000 --- a/monkey/monkey_island/cc/services/config_schema/config_schema.py +++ /dev/null @@ -1,35 +0,0 @@ -from monkey_island.cc.services.config_schema.basic import BASIC -from monkey_island.cc.services.config_schema.basic_network import BASIC_NETWORK -from monkey_island.cc.services.config_schema.definitions.credential_collector_classes import ( - CREDENTIAL_COLLECTORS, -) -from monkey_island.cc.services.config_schema.definitions.exploiter_classes import EXPLOITER_CLASSES -from monkey_island.cc.services.config_schema.definitions.finger_classes import FINGER_CLASSES -from monkey_island.cc.services.config_schema.definitions.post_breach_actions import ( - POST_BREACH_ACTIONS, -) -from monkey_island.cc.services.config_schema.internal import INTERNAL -from monkey_island.cc.services.config_schema.monkey import MONKEY -from monkey_island.cc.services.config_schema.ransomware import RANSOMWARE - -SCHEMA = { - "title": "Monkey", - "type": "object", - # Newly added definitions should also be added to - # monkey/monkey_island/cc/ui/src/components/utils/SafeOptionValidator.js so that - # users will not accidentally chose unsafe options - "definitions": { - "exploiter_classes": EXPLOITER_CLASSES, - "credential_collectors": CREDENTIAL_COLLECTORS, - "post_breach_actions": POST_BREACH_ACTIONS, - "finger_classes": FINGER_CLASSES, - }, - "properties": { - "basic": BASIC, - "basic_network": BASIC_NETWORK, - "monkey": MONKEY, - "ransomware": RANSOMWARE, - "internal": INTERNAL, - }, - "options": {"collapsed": True}, -} From 4eb7472977cb91407d7a639867a129d2e7714637 Mon Sep 17 00:00:00 2001 From: Shreya Malviya Date: Tue, 28 Jun 2022 20:12:55 -0700 Subject: [PATCH 04/13] Island: Remove functions from ConfigService that used the old config schema This breaks some stuff: the IslandConfiguration resource, the reset config functionality, and probably some other things. However, this isn't too much of a concern since all of this will be reimplemented in the coming weeks. It's just really broken for now. --- .../cc/resources/island_configuration.py | 2 +- monkey/monkey_island/cc/services/config.py | 37 +------------------ 2 files changed, 2 insertions(+), 37 deletions(-) diff --git a/monkey/monkey_island/cc/resources/island_configuration.py b/monkey/monkey_island/cc/resources/island_configuration.py index 38f08ff1b..411960f53 100644 --- a/monkey/monkey_island/cc/resources/island_configuration.py +++ b/monkey/monkey_island/cc/resources/island_configuration.py @@ -24,7 +24,7 @@ class IslandConfiguration(AbstractResource): # API Spec: Makes more sense to have a PATCH request for this since the resource, # i.e. the configuration, is being updated. if "reset" in config_json: - ConfigService.reset_config() + pass else: if not ConfigService.update_config(config_json, should_encrypt=True): abort(400) diff --git a/monkey/monkey_island/cc/services/config.py b/monkey/monkey_island/cc/services/config.py index 99f5a589c..5a80f7486 100644 --- a/monkey/monkey_island/cc/services/config.py +++ b/monkey/monkey_island/cc/services/config.py @@ -1,10 +1,9 @@ import collections -import copy import functools import logging from typing import Dict, List -from jsonschema import Draft4Validator, validators +from jsonschema import validators from common.config_value_paths import ( LM_HASH_LIST_PATH, @@ -23,8 +22,6 @@ from monkey_island.cc.server_utils.encryption import ( encrypt_dict, get_datastore_encryptor, ) -from monkey_island.cc.services.config_schema.config_schema import SCHEMA -from monkey_island.cc.services.post_breach_files import PostBreachFilesService logger = logging.getLogger(__name__) @@ -124,10 +121,6 @@ class ConfigService: return flat_config_json - @staticmethod - def get_config_schema(): - return SCHEMA - # Not added to interface because it's doable by get_config_field + set_config_field @staticmethod def add_item_to_config_set_if_dont_exist(item_path_array, item_value, should_encrypt): @@ -216,38 +209,10 @@ class ConfigService: ConfigService.set_config_value(PBA_LINUX_FILENAME_PATH, linux_filename) ConfigService.set_config_value(PBA_WINDOWS_FILENAME_PATH, windows_filename) - @staticmethod - def init_default_config(): - if ConfigService.default_config is None: - default_validating_draft4_validator = ConfigService._extend_config_with_default( - Draft4Validator - ) - config = {} - default_validating_draft4_validator(SCHEMA).validate(config) - ConfigService.default_config = config - - @staticmethod - def get_default_config(should_encrypt=False): - ConfigService.init_default_config() - config = copy.deepcopy(ConfigService.default_config) - - if should_encrypt: - ConfigService.encrypt_config(config) - - logger.info("Default config was called") - - return config - @staticmethod def init_config(): if ConfigService.get_config(should_decrypt=False) != {}: return - ConfigService.reset_config() - - @staticmethod - def reset_config(): - PostBreachFilesService.remove_PBA_files() - logger.info("Monkey config reset was called") @staticmethod def _extend_config_with_default(validator_class): From cbc5e9914037647f5ab8e1a12ed28ebaed51b3f1 Mon Sep 17 00:00:00 2001 From: Shreya Malviya Date: Tue, 28 Jun 2022 22:13:48 -0700 Subject: [PATCH 05/13] Island: Add TODO to fix comment in Config model --- monkey/monkey_island/cc/models/config.py | 1 + 1 file changed, 1 insertion(+) diff --git a/monkey/monkey_island/cc/models/config.py b/monkey/monkey_island/cc/models/config.py index febc3e239..7e8e4a354 100644 --- a/monkey/monkey_island/cc/models/config.py +++ b/monkey/monkey_island/cc/models/config.py @@ -5,6 +5,7 @@ class Config(EmbeddedDocument): COLLECTION_NAME = "config" + # TODO: Fix this comment """ No need to define this schema here. It will change often and is already is defined in monkey_island.cc.services.config_schema. From 98fbc7592cbff8408b1b427b2c1124075a38acf2 Mon Sep 17 00:00:00 2001 From: Shreya Malviya Date: Thu, 30 Jun 2022 21:50:47 -0700 Subject: [PATCH 06/13] Island: Hardcode unscanned message for ATT&CK techniques Remove logic for config schema per attack technique which set the unscanned message previously --- .../attack/technique_reports/__init__.py | 54 ++---------- .../config_schema_per_attack_technique.py | 83 ------------------- 2 files changed, 8 insertions(+), 129 deletions(-) delete mode 100644 monkey/monkey_island/cc/services/config_schema/config_schema_per_attack_technique.py diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/__init__.py b/monkey/monkey_island/cc/services/attack/technique_reports/__init__.py index 34aa11691..8a02deb02 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/__init__.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/__init__.py @@ -6,20 +6,21 @@ from common.utils.attack_utils import ScanStatus from common.utils.code_utils import abstractstatic from monkey_island.cc.database import mongo from monkey_island.cc.models.attack.attack_mitigations import AttackMitigations -from monkey_island.cc.services.config_schema.config_schema import SCHEMA from monkey_island.cc.services.attack.attack_schema import SCHEMA as ATTACK_SCHEMA -from monkey_island.cc.services.config_schema.config_schema_per_attack_technique import ( - ConfigSchemaPerAttackTechnique, -) + logger = logging.getLogger(__name__) +UNSCANNED_MESSAGE = ( + "The configuration options corresponding to this ATT&CK technique were not " + "enabled in the configuration." +) + + class AttackTechnique(object, metaclass=abc.ABCMeta): """Abstract class for ATT&CK report components""" - config_schema_per_attack_technique = None - @property @abc.abstractmethod def unscanned_msg(self): @@ -120,52 +121,13 @@ class AttackTechnique(object, metaclass=abc.ABCMeta): :return: message string """ if status == ScanStatus.UNSCANNED.value: - if not cls.config_schema_per_attack_technique: - cls.config_schema_per_attack_technique = ( - ConfigSchemaPerAttackTechnique().get_config_schema_per_attack_technique(SCHEMA) - ) - unscanned_msg = cls._get_unscanned_msg_with_reasons( - cls.unscanned_msg, cls.config_schema_per_attack_technique - ) + unscanned_msg = UNSCANNED_MESSAGE return unscanned_msg elif status == ScanStatus.SCANNED.value: return cls.scanned_msg else: return cls.used_msg - @classmethod - def _get_unscanned_msg_with_reasons( - cls, unscanned_msg: str, config_schema_per_attack_technique: Dict - ): - reasons = [] - if len(cls.relevant_systems) == 1: - reasons.append(f"- Monkey did not run on any {cls.relevant_systems[0]} systems.") - if cls.tech_id in config_schema_per_attack_technique: - reasons.append( - "- The following configuration options were disabled or empty:
" - f"{cls._get_relevant_config_values(config_schema_per_attack_technique)}" - ) - - if reasons: - unscanned_msg = ( - unscanned_msg.strip(".") - + " due to one of the following reasons:\n" - + "\n".join(reasons) - ) - - return unscanned_msg - - @classmethod - def _get_relevant_config_values(cls, config_schema_per_attack_technique: Dict): - config_options = "" - for config_type in config_schema_per_attack_technique[cls.tech_id]: - config_options += ( - f"- {config_type} — " - f"{', '.join(config_schema_per_attack_technique[cls.tech_id][config_type])}
" - ) - - return config_options - @classmethod def technique_title(cls): """ diff --git a/monkey/monkey_island/cc/services/config_schema/config_schema_per_attack_technique.py b/monkey/monkey_island/cc/services/config_schema/config_schema_per_attack_technique.py deleted file mode 100644 index a760c8d00..000000000 --- a/monkey/monkey_island/cc/services/config_schema/config_schema_per_attack_technique.py +++ /dev/null @@ -1,83 +0,0 @@ -from typing import Dict, List - - -class ConfigSchemaPerAttackTechnique: - def __init__(self) -> None: - self.reverse_schema = {} - - def get_config_schema_per_attack_technique( - self, schema: Dict - ) -> Dict[str, Dict[str, List[str]]]: - """ - example: \ - { \ - "T1003": { \ - "System Info Collectors": [ \ - "Mimikatz collector", \ - ] \ - } \ - } \ - - :return: dictionary mapping each attack technique to relevant config \ - fields - """ - self._crawl_config_schema_definitions_for_reverse_schema(schema) - self._crawl_config_schema_properties_for_reverse_schema(schema) - - return self.reverse_schema - - def _crawl_config_schema_definitions_for_reverse_schema(self, schema: Dict): - definitions = schema["definitions"] - for definition in definitions: - definition_type = definitions[definition]["title"] - for field in definitions[definition].get("anyOf", []): - config_field = field["title"] - for attack_technique in field.get("attack_techniques", []): - self._add_config_field_to_reverse_schema( - definition_type, config_field, attack_technique - ) - - def _crawl_config_schema_properties_for_reverse_schema(self, schema: Dict): - properties = schema["properties"] - for prop in properties: - property_type = properties[prop]["title"] - for category_name in properties[prop].get("properties", []): - category = properties[prop]["properties"][category_name] - self._crawl_properties( - config_option_path=property_type, - config_option=category, - ) - - def _crawl_properties(self, config_option_path: str, config_option: Dict): - config_option_path = ( - f"{config_option_path} -> {config_option['title']}" - if "title" in config_option - else config_option_path - ) - for config_option_name in config_option.get("properties", []): - new_config_option = config_option["properties"][config_option_name] - self._check_related_attack_techniques( - config_option_path=config_option_path, - config_option=new_config_option, - ) - - # check for "properties" and each property's related techniques recursively; - # the levels of nesting and where related techniques are declared won't - # always be fixed in the config schema - self._crawl_properties(config_option_path, new_config_option) - - def _check_related_attack_techniques(self, config_option_path: str, config_option: Dict): - for attack_technique in config_option.get("related_attack_techniques", []): - # No config values could be a reason that related attack techniques are left - # unscanned. See https://github.com/guardicore/monkey/issues/1518 for more. - config_field = config_option["title"] - self._add_config_field_to_reverse_schema( - config_option_path, config_field, attack_technique - ) - - def _add_config_field_to_reverse_schema( - self, definition_type: str, config_field: str, attack_technique: str - ) -> None: - self.reverse_schema.setdefault(attack_technique, {}) - self.reverse_schema[attack_technique].setdefault(definition_type, []) - self.reverse_schema[attack_technique][definition_type].append(config_field) From 9b23cc0befa6a0b17ca4ef6c80f1294309bbcf73 Mon Sep 17 00:00:00 2001 From: Shreya Malviya Date: Thu, 30 Jun 2022 21:52:18 -0700 Subject: [PATCH 07/13] UT: Remove tests related to config schema per attack technique --- .../test_technique_reports.py | 100 +++--------------- ...test_config_schema_per_attack_technique.py | 25 ----- 2 files changed, 16 insertions(+), 109 deletions(-) delete mode 100644 monkey/tests/unit_tests/monkey_island/cc/services/config_schema/test_config_schema_per_attack_technique.py diff --git a/monkey/tests/unit_tests/monkey_island/cc/services/attack/technique_reports/test_technique_reports.py b/monkey/tests/unit_tests/monkey_island/cc/services/attack/technique_reports/test_technique_reports.py index e408a3aff..dc3ffdc11 100644 --- a/monkey/tests/unit_tests/monkey_island/cc/services/attack/technique_reports/test_technique_reports.py +++ b/monkey/tests/unit_tests/monkey_island/cc/services/attack/technique_reports/test_technique_reports.py @@ -1,20 +1,13 @@ from enum import Enum -import pytest - from common.utils.attack_utils import ScanStatus -from monkey_island.cc.services.attack.technique_reports.__init__ import AttackTechnique +from monkey_island.cc.services.attack.technique_reports.__init__ import ( + UNSCANNED_MESSAGE, + AttackTechnique, +) -@pytest.fixture(scope="function", autouse=True) -def mock_config_schema_per_attack_technique(monkeypatch, fake_schema): - monkeypatch.setattr( - ("monkey_island.cc.services.attack.technique_reports.__init__.SCHEMA"), - fake_schema, - ) - - -class FakeAttackTechnique_TwoRelevantSystems(AttackTechnique): +class FakeAttackTechnique(AttackTechnique): tech_id = "T0000" relevant_systems = ["System 1", "System 2"] unscanned_msg = "UNSCANNED" @@ -25,83 +18,22 @@ class FakeAttackTechnique_TwoRelevantSystems(AttackTechnique): pass -class ExpectedMsgs_TwoRelevantSystems(Enum): - UNSCANNED: str = ( - "UNSCANNED due to one of the following reasons:\n" - "- The following configuration options were disabled or empty:
" - "- Definition Type 1 — Config Option 1, Config Option 2
" - "- Definition Type 2 — Config Option 5, Config Option 6
" - "- Property Type 1 -> Category 1 — Config Option 1
" - "- Property Type 2 -> Category 1 — Config Option 1
" - "- Property Type 2 -> Category 2 -> Config Option 1 — Config Option 1.1
" - "- Property Type 2 -> Category 2 -> Config Option 2 — Config Option 2.1
" - "- Property Type 2 -> Category 2 -> Config Option 2 -> Config Option 2.1 — Config Option " - "2.1.1
" - ) +class ExpectedMsgs(Enum): + UNSCANNED: str = UNSCANNED_MESSAGE SCANNED: str = "SCANNED" USED: str = "USED" -class FakeAttackTechnique_OneRelevantSystem(AttackTechnique): - tech_id = "T0001" - relevant_systems = ["System 1"] - unscanned_msg = "UNSCANNED" - scanned_msg = "SCANNED" - used_msg = "USED" - - def get_report_data(): - pass +def test_get_message_by_status_unscanned(): + technique_msg = FakeAttackTechnique.get_message_by_status(ScanStatus.UNSCANNED.value) + assert technique_msg == ExpectedMsgs.UNSCANNED.value -class ExpectedMsgs_OneRelevantSystem(Enum): - UNSCANNED: str = ( - "UNSCANNED due to one of the following reasons:\n" - "- Monkey did not run on any System 1 systems.\n" - "- The following configuration options were disabled or empty:
" - "- Definition Type 1 — Config Option 1
" - "- Definition Type 2 — Config Option 5
" - ) - SCANNED: str = "SCANNED" - USED: str = "USED" +def test_get_message_by_status_scanned(): + technique_msg = FakeAttackTechnique.get_message_by_status(ScanStatus.SCANNED.value) + assert technique_msg == ExpectedMsgs.SCANNED.value -def test_get_message_by_status_unscanned_two_relevant_systems(): - technique_msg = FakeAttackTechnique_TwoRelevantSystems.get_message_by_status( - ScanStatus.UNSCANNED.value - ) - assert technique_msg == ExpectedMsgs_TwoRelevantSystems.UNSCANNED.value - - -def test_get_message_by_status_scanned_two_relevant_systems(): - technique_msg = FakeAttackTechnique_TwoRelevantSystems.get_message_by_status( - ScanStatus.SCANNED.value - ) - assert technique_msg == ExpectedMsgs_TwoRelevantSystems.SCANNED.value - - -def test_get_message_by_status_used_two_relevant_systems(): - technique_msg = FakeAttackTechnique_TwoRelevantSystems.get_message_by_status( - ScanStatus.USED.value - ) - assert technique_msg == ExpectedMsgs_TwoRelevantSystems.USED.value - - -def test_get_message_by_status_unscanned_one_relevant_system(): - technique_msg = FakeAttackTechnique_OneRelevantSystem.get_message_by_status( - ScanStatus.UNSCANNED.value - ) - assert technique_msg == ExpectedMsgs_OneRelevantSystem.UNSCANNED.value - - -def test_get_message_by_status_scanned_one_relevant_system(): - technique_msg = FakeAttackTechnique_OneRelevantSystem.get_message_by_status( - ScanStatus.SCANNED.value - ) - assert technique_msg == ExpectedMsgs_OneRelevantSystem.SCANNED.value - - -def test_get_message_by_status_used_one_relevant_system(): - technique_msg = FakeAttackTechnique_OneRelevantSystem.get_message_by_status( - ScanStatus.USED.value - ) - assert technique_msg == ExpectedMsgs_OneRelevantSystem.USED.value +def test_get_message_by_status_used(): + technique_msg = FakeAttackTechnique.get_message_by_status(ScanStatus.USED.value) + assert technique_msg == ExpectedMsgs.USED.value diff --git a/monkey/tests/unit_tests/monkey_island/cc/services/config_schema/test_config_schema_per_attack_technique.py b/monkey/tests/unit_tests/monkey_island/cc/services/config_schema/test_config_schema_per_attack_technique.py deleted file mode 100644 index 86383366e..000000000 --- a/monkey/tests/unit_tests/monkey_island/cc/services/config_schema/test_config_schema_per_attack_technique.py +++ /dev/null @@ -1,25 +0,0 @@ -from monkey_island.cc.services.config_schema.config_schema_per_attack_technique import ( - ConfigSchemaPerAttackTechnique, -) - -REVERSE_FAKE_SCHEMA = { - "T0000": { - "Definition Type 1": ["Config Option 1", "Config Option 2"], - "Definition Type 2": ["Config Option 5", "Config Option 6"], - "Property Type 1 -> Category 1": ["Config Option 1"], - "Property Type 2 -> Category 1": ["Config Option 1"], - "Property Type 2 -> Category 2 -> Config Option 1": ["Config Option 1.1"], - "Property Type 2 -> Category 2 -> Config Option 2": ["Config Option 2.1"], - "Property Type 2 -> Category 2 -> Config Option 2 -> Config Option 2.1": [ - "Config Option 2.1.1" - ], - }, - "T0001": {"Definition Type 1": ["Config Option 1"], "Definition Type 2": ["Config Option 5"]}, -} - - -def test_get_config_schema_per_attack_technique(monkeypatch, fake_schema): - assert ( - ConfigSchemaPerAttackTechnique().get_config_schema_per_attack_technique(fake_schema) - == REVERSE_FAKE_SCHEMA - ) From 16e8443134fd77f500e57f80c541717c4839168d Mon Sep 17 00:00:00 2001 From: Ilija Lazoroski Date: Wed, 6 Jul 2022 15:45:13 +0200 Subject: [PATCH 08/13] Island: Add TODO to return default config in reporting Notes in services for not fixing the failing tests until we remove the ConfigService --- monkey/monkey_island/cc/services/reporting/report.py | 1 + monkey/tests/unit_tests/monkey_island/cc/services/conftest.py | 4 +++- .../cc/services/telemetry/processing/credentials/conftest.py | 4 +++- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/monkey/monkey_island/cc/services/reporting/report.py b/monkey/monkey_island/cc/services/reporting/report.py index de696cda3..60d2d33ed 100644 --- a/monkey/monkey_island/cc/services/reporting/report.py +++ b/monkey/monkey_island/cc/services/reporting/report.py @@ -392,6 +392,7 @@ class ReportService: @staticmethod def get_config_exploits(): exploits_config_value = EXPLOITER_CLASSES_PATH + # TODO: Return default config here default_exploits = ConfigService.get_default_config(False) for namespace in exploits_config_value: default_exploits = default_exploits[namespace] diff --git a/monkey/tests/unit_tests/monkey_island/cc/services/conftest.py b/monkey/tests/unit_tests/monkey_island/cc/services/conftest.py index aaf3c0abe..10e5d9377 100644 --- a/monkey/tests/unit_tests/monkey_island/cc/services/conftest.py +++ b/monkey/tests/unit_tests/monkey_island/cc/services/conftest.py @@ -15,7 +15,9 @@ def PORT(): @pytest.fixture def config(monkeypatch): - config = ConfigService.get_default_config(True) + # Note: ConfigService is going away, don't try to fix the UT using + # this fixture + config = ConfigService.get_config(True) return config diff --git a/monkey/tests/unit_tests/monkey_island/cc/services/telemetry/processing/credentials/conftest.py b/monkey/tests/unit_tests/monkey_island/cc/services/telemetry/processing/credentials/conftest.py index 0088995f3..e34d232ff 100644 --- a/monkey/tests/unit_tests/monkey_island/cc/services/telemetry/processing/credentials/conftest.py +++ b/monkey/tests/unit_tests/monkey_island/cc/services/telemetry/processing/credentials/conftest.py @@ -14,7 +14,9 @@ fake_ip_address = "192.168.56.1" def fake_mongo(monkeypatch, uses_encryptor): mongo = mongoengine.connection.get_connection() monkeypatch.setattr("monkey_island.cc.services.config.mongo", mongo) - config = ConfigService.get_default_config() + # Note: ConfigService is going away, don't try to fix UT using + # this fixture + config = ConfigService.get_config() ConfigService.update_config(config, should_encrypt=True) From 9f0029d040295c7874492779512783be1f8b9a13 Mon Sep 17 00:00:00 2001 From: Ilija Lazoroski Date: Wed, 6 Jul 2022 15:46:46 +0200 Subject: [PATCH 09/13] Common: Remove credential collector names and validation formats --- monkey/common/common_consts/credential_collector_names.py | 2 -- monkey/common/common_consts/validation_formats.py | 5 ----- 2 files changed, 7 deletions(-) delete mode 100644 monkey/common/common_consts/credential_collector_names.py delete mode 100644 monkey/common/common_consts/validation_formats.py diff --git a/monkey/common/common_consts/credential_collector_names.py b/monkey/common/common_consts/credential_collector_names.py deleted file mode 100644 index 45ee8f889..000000000 --- a/monkey/common/common_consts/credential_collector_names.py +++ /dev/null @@ -1,2 +0,0 @@ -MIMIKATZ_COLLECTOR = "MimikatzCollector" -SSH_COLLECTOR = "SSHCollector" diff --git a/monkey/common/common_consts/validation_formats.py b/monkey/common/common_consts/validation_formats.py deleted file mode 100644 index 41a460a8a..000000000 --- a/monkey/common/common_consts/validation_formats.py +++ /dev/null @@ -1,5 +0,0 @@ -# Defined in UI on ValidationFormats.js -IP_RANGE = "ip-range" -IP = "ip" -VALID_RANSOMWARE_TARGET_PATH_LINUX = "valid-ransomware-target-path-linux" -VALID_RANSOMWARE_TARGET_PATH_WINDOWS = "valid-ransomware-target-path-windows" From 0cb8cfb0785cab3e8bec155ad2791d77b7c0b269 Mon Sep 17 00:00:00 2001 From: Ilija Lazoroski Date: Wed, 6 Jul 2022 15:47:07 +0200 Subject: [PATCH 10/13] Island: Remove typographic symbols --- monkey/monkey_island/cc/services/utils/typographic_symbols.py | 1 - 1 file changed, 1 deletion(-) delete mode 100644 monkey/monkey_island/cc/services/utils/typographic_symbols.py diff --git a/monkey/monkey_island/cc/services/utils/typographic_symbols.py b/monkey/monkey_island/cc/services/utils/typographic_symbols.py deleted file mode 100644 index ab87f169e..000000000 --- a/monkey/monkey_island/cc/services/utils/typographic_symbols.py +++ /dev/null @@ -1 +0,0 @@ -WARNING_SIGN = " \u26A0" From bbf40e446f934ddbea078cd66b0e4c00b2b86ecf Mon Sep 17 00:00:00 2001 From: Ilija Lazoroski Date: Wed, 6 Jul 2022 15:51:12 +0200 Subject: [PATCH 11/13] Island: Remove default_config and validator function from ConfigService --- monkey/monkey_island/cc/services/config.py | 41 ---------------------- 1 file changed, 41 deletions(-) diff --git a/monkey/monkey_island/cc/services/config.py b/monkey/monkey_island/cc/services/config.py index 5a80f7486..e7a16aec5 100644 --- a/monkey/monkey_island/cc/services/config.py +++ b/monkey/monkey_island/cc/services/config.py @@ -3,8 +3,6 @@ import functools import logging from typing import Dict, List -from jsonschema import validators - from common.config_value_paths import ( LM_HASH_LIST_PATH, NTLM_HASH_LIST_PATH, @@ -40,7 +38,6 @@ SENSITIVE_SSH_KEY_FIELDS = [ class ConfigService: - default_config = None def __init__(self): pass @@ -214,44 +211,6 @@ class ConfigService: if ConfigService.get_config(should_decrypt=False) != {}: return - @staticmethod - def _extend_config_with_default(validator_class): - validate_properties = validator_class.VALIDATORS["properties"] - - def set_defaults(validator, properties, instance, schema): - # Do it only for root. - if instance != {}: - return - for property1, subschema1 in list(properties.items()): - main_dict = {} - for property2, subschema2 in list(subschema1["properties"].items()): - sub_dict = {} - for property3, subschema3 in list(subschema2["properties"].items()): - if "default" in subschema3: - sub_dict[property3] = subschema3["default"] - elif "properties" in subschema3: - layer_3_dict = {} - for property4, subschema4 in list(subschema3["properties"].items()): - if "properties" in subschema4: - raise ValueError( - "monkey/monkey_island/cc/services/config.py " - "can't handle 5 level config. " - "Either change back the config or refactor." - ) - if "default" in subschema4: - layer_3_dict[property4] = subschema4["default"] - sub_dict[property3] = layer_3_dict - main_dict[property2] = sub_dict - instance.setdefault(property1, main_dict) - - for error in validate_properties(validator, properties, instance, schema): - yield error - - return validators.extend( - validator_class, - {"properties": set_defaults}, - ) - @staticmethod def decrypt_config(config): ConfigService._encrypt_or_decrypt_config(config, True) From 522376b0657a691ab6f7516d1821e436ae418753 Mon Sep 17 00:00:00 2001 From: Ilija Lazoroski Date: Wed, 6 Jul 2022 16:40:19 +0200 Subject: [PATCH 12/13] Swimm: Remove two swimm units * Add details about your new PBA * Add a new Post Breach Action --- .swm/JFXftJml8DpmuCPBA9rL.swm | 52 -------------------- .swm/afMu3y3ny5lnrYFWl3EI.swm | 90 ----------------------------------- 2 files changed, 142 deletions(-) delete mode 100644 .swm/JFXftJml8DpmuCPBA9rL.swm delete mode 100644 .swm/afMu3y3ny5lnrYFWl3EI.swm diff --git a/.swm/JFXftJml8DpmuCPBA9rL.swm b/.swm/JFXftJml8DpmuCPBA9rL.swm deleted file mode 100644 index b3f3bd080..000000000 --- a/.swm/JFXftJml8DpmuCPBA9rL.swm +++ /dev/null @@ -1,52 +0,0 @@ -{ - "id": "JFXftJml8DpmuCPBA9rL", - "name": "Add details about your new PBA", - "task": { - "dod": "You should add your new PBA's details to the configuration.", - "tests": [], - "hints": [ - "Have a look at the details of the other techniques." - ] - }, - "content": [ - { - "type": "text", - "text": "In order to make sure that the new `ScheduleJobs` PBA is shown in the configuration on the Monkey Island, you need to add its details to the configuration file(s).

\n\nSince this particular PBA is related to the MITRE techniques [T1168](https://attack.mitre.org/techniques/T1168) and [T1053](https://attack.mitre.org/techniques/T1053), make sure to link the PBA with these techniques in the configuration as well.

\n\nEach part of the configuration has an important role \n- *enum* — contains the relevant PBA's class name(s)\n- *title* — holds the name of the PBA which is displayed in the configuration on the Monkey Island\n- *info* — consists of an elaboration on the PBA's working which is displayed in the configuration on the Monkey Island\n- *attack_techniques* — has the IDs of the MITRE techniques associated with the PBA\n\n## Manual test \nOnce you think you're done...\n- Run the Monkey Island\n- You should be able to see your new PBA under the \"Monkey\" tab in the configuration, along with its information when you click on it\n\n" - }, - { - "type": "snippet", - "lines": [ - " \"Removes the file afterwards.\",", - " \"attack_techniques\": [\"T1166\"],", - " },", - "* {", - "+ # Swimmer: ADD DETAILS HERE!", - "* \"type\": \"string\",", - "* \"enum\": [\"ScheduleJobs\"],", - "* \"title\": \"Job Scheduling\",", - "* \"safe\": True,", - "* \"info\": \"Attempts to create a scheduled job on the system and remove it.\",", - "* \"attack_techniques\": [\"T1168\", \"T1053\"],", - "* },", - " {", - " \"type\": \"string\",", - " \"enum\": [\"Timestomping\"]," - ], - "firstLineNumber": 52, - "path": "monkey/monkey_island/cc/services/config_schema/definitions/post_breach_actions.py", - "comments": [] - }, - { - "type": "text", - "text": "- The PBA details in this file are reflected on the Monkey Island in the PBA configuration.\n- PBAs are also linked to the relevant MITRE techniques in this file, whose results can then be seen in the MITRE ATT&CK report on the Monkey Island." - } - ], - "symbols": {}, - "file_version": "2.0.3", - "meta": { - "app_version": "0.5.7-0", - "file_blobs": { - "monkey/monkey_island/cc/services/config_schema/definitions/post_breach_actions.py": "7d62ac36e875ca3c249d808250cb3268e4d3d68d" - } - } -} diff --git a/.swm/afMu3y3ny5lnrYFWl3EI.swm b/.swm/afMu3y3ny5lnrYFWl3EI.swm deleted file mode 100644 index 1da171e62..000000000 --- a/.swm/afMu3y3ny5lnrYFWl3EI.swm +++ /dev/null @@ -1,90 +0,0 @@ -{ - "id": "afMu3y3ny5lnrYFWl3EI", - "name": "Add a new Post Breach Action (PBA)", - "task": { - "dod": "You should add a new PBA to the Monkey which discovers all user accounts on the machine.", - "tests": [], - "hints": [ - "See `ScheduleJobs` PBA for an example of a PBA which only uses shell commands.", - "Make sure to add the PBA to the configuration as well.", - "MITRE ATT&CK technique T1087 articulates that adversaries may attempt to get a listing of accounts on a system or within an environment which can help them determine which accounts can aid in follow-on behavior. Therefore, the AccountDiscovery PBA is relevant to it which will enable the ATT&CK technique and show it in ATT&CK report." - ] - }, - "content": [ - { - "type": "text", - "text": "Read our [documentation](https://www.guardicore.com/infectionmonkey/docs/development/adding-post-breach-actions/) about adding a new PBA.\n\nAfter that we want you to add the AccountDiscovery PBA. The commands that add users for Windows and Linux can be retrieved from \\`get\\_commands\\_to\\_discover\\_accounts\\` — make sure you see how to use this function correctly.\n\nNote that the PBA should impact the T1087 MITRE technique as well.\n\n**Manual test to confirm**\n--------------------------\n\n1. Run the Monkey Island.\n \n2. Make sure your new PBA is enabled by default in the config. For this test, disable network scanning, exploiting, and all other PBAs.\n \n3. Run the Monkey Agent.\n \n4. See the PBA in the security report and in the MITRE report under the relevant technique." - }, - { - "type": "snippet", - "lines": [ - " POST_BREACH_JOB_SCHEDULING = \"Schedule jobs\"", - " POST_BREACH_TIMESTOMPING = \"Modify files' timestamps\"", - " POST_BREACH_SIGNED_SCRIPT_PROXY_EXEC = \"Signed script proxy execution\"", - "*POST_BREACH_ACCOUNT_DISCOVERY = \"Account discovery\"", - "+# SWIMMER: Put the new const here!", - " POST_BREACH_CLEAR_CMD_HISTORY = \"Clear command history\"" - ], - "firstLineNumber": 7, - "path": "monkey/common/common_consts/post_breach_consts.py", - "comments": [] - }, - { - "type": "snippet", - "lines": [ - " ", - " class AccountDiscovery(PBA):", - " def __init__(self, telemetry_messenger: ITelemetryMessenger):", - "* linux_cmds, windows_cmds = get_commands_to_discover_accounts()", - "+ # SWIMMER: Implement here!", - "* super().__init__(", - "+ pass", - "* telemetry_messenger,", - "* POST_BREACH_ACCOUNT_DISCOVERY,", - "* linux_cmd=\" \".join(linux_cmds),", - "* windows_cmd=windows_cmds,", - "* )" - ], - "firstLineNumber": 8, - "path": "monkey/infection_monkey/post_breach/actions/discover_accounts.py", - "comments": [] - }, - { - "type": "snippet", - "lines": [ - " \"with the help of a pre-existing signed script.\",", - " \"attack_techniques\": [\"T1216\"],", - " },", - "* {", - "+ # SWIMMER: Add details here!", - "* \"type\": \"string\",", - "* \"enum\": [\"AccountDiscovery\"],", - "* \"title\": \"Account Discovery\",", - "* \"safe\": True,", - "* \"info\": \"Attempts to get a listing of user accounts on the system.\",", - "* \"attack_techniques\": [\"T1087\"],", - "* },", - " {", - " \"type\": \"string\",", - " \"enum\": [\"ClearCommandHistory\"]," - ], - "firstLineNumber": 78, - "path": "monkey/monkey_island/cc/services/config_schema/definitions/post_breach_actions.py", - "comments": [] - }, - { - "type": "text", - "text": "Many PBAs use shell commands or scripts — see `Timestomping` and `AccountDiscovery`.\n\nOn the other hand, some are less straightforward. You can override functions and implement new classes depending on what is required, to implement complicated PBAs — see `SignedScriptProxyExecution` and `ModifyShellStartupFiles`. \n \n\nThis PBA, along with the others, will run on a system after it has been breached. The purpose of this code is to test whether target systems allow attackers to gather details about all the user accounts that are present on a system or in an environment." - } - ], - "symbols": {}, - "file_version": "2.0.3", - "meta": { - "app_version": "0.6.6-2", - "file_blobs": { - "monkey/common/common_consts/post_breach_consts.py": "19b6c4f19b7223f115976a0050ca04ab97e52f8e", - "monkey/infection_monkey/post_breach/actions/discover_accounts.py": "a153cf5b6185c9771414fc5ae49d441efc7294b6", - "monkey/monkey_island/cc/services/config_schema/definitions/post_breach_actions.py": "d6831ed63b17f327d719a05840d7e51202fa5ccb" - } - } -} From 439b4aca86b7cc907ef18ea478db1dbbd3f40e73 Mon Sep 17 00:00:00 2001 From: Ilija Lazoroski Date: Wed, 6 Jul 2022 16:43:52 +0200 Subject: [PATCH 13/13] Island: Reformat ConfigService using black --- monkey/monkey_island/cc/services/config.py | 1 - 1 file changed, 1 deletion(-) diff --git a/monkey/monkey_island/cc/services/config.py b/monkey/monkey_island/cc/services/config.py index e7a16aec5..ac7844ca2 100644 --- a/monkey/monkey_island/cc/services/config.py +++ b/monkey/monkey_island/cc/services/config.py @@ -38,7 +38,6 @@ SENSITIVE_SSH_KEY_FIELDS = [ class ConfigService: - def __init__(self): pass