diff --git a/infection_monkey/exploit/struts2.py b/infection_monkey/exploit/struts2.py index be8ba8f0f..5bd26fbb7 100644 --- a/infection_monkey/exploit/struts2.py +++ b/infection_monkey/exploit/struts2.py @@ -59,8 +59,7 @@ class Struts2Exploiter(HostExploiter): if port == 443: current_host = "https://%s:%d" % (self.host.ip_addr, port) else: - # TODO remove struts from url - current_host = "http://%s:%d/struts" % (self.host.ip_addr, port) + current_host = "http://%s:%d" % (self.host.ip_addr, port) # Get full URL url = self.get_redirected(current_host) # Get os architecture so that we don't have to update monkey @@ -154,8 +153,8 @@ class Struts2Exploiter(HostExploiter): command = POWERSHELL_HTTP % {'monkey_path': re.sub(r"\\", r"\\\\", dropper_path), 'http_path': http_path, 'parameters': cmdline} - # TODO Add timeout - self.exploit(url, command) + + self.exploit(url, command, RESPONSE_TIMEOUT) http_thread.join(DOWNLOAD_TIMEOUT) http_thread.stop() diff --git a/monkey_island/cc/services/report.py b/monkey_island/cc/services/report.py index 13b52422c..369b29c25 100644 --- a/monkey_island/cc/services/report.py +++ b/monkey_island/cc/services/report.py @@ -30,6 +30,7 @@ class ReportService: 'ElasticGroovyExploiter': 'Elastic Groovy Exploiter', 'Ms08_067_Exploiter': 'Conficker Exploiter', 'ShellShockExploiter': 'ShellShock Exploiter', + 'Struts2Exploiter': 'Struts2 Exploiter' } class ISSUES_DICT(Enum): @@ -41,6 +42,7 @@ class ReportService: CONFICKER = 5 AZURE = 6 STOLEN_SSH_KEYS = 7 + STRUTS2 = 8 class WARNINGS_DICT(Enum): CROSS_SEGMENT = 0 @@ -290,6 +292,12 @@ class ReportService: processed_exploit['paths'] = ['/' + url.split(':')[2].split('/')[1] for url in urls] return processed_exploit + @staticmethod + def process_struts2_exploit(exploit): + processed_exploit = ReportService.process_general_exploit(exploit) + processed_exploit['type'] = 'struts2' + return processed_exploit + @staticmethod def process_exploit(exploit): exploiter_type = exploit['data']['exploiter'] @@ -302,6 +310,7 @@ class ReportService: 'ElasticGroovyExploiter': ReportService.process_elastic_exploit, 'Ms08_067_Exploiter': ReportService.process_conficker_exploit, 'ShellShockExploiter': ReportService.process_shellshock_exploit, + 'Struts2Exploiter': ReportService.process_struts2_exploit } return EXPLOIT_PROCESS_FUNCTION_DICT[exploiter_type](exploit) @@ -419,6 +428,8 @@ class ReportService: issues_byte_array[ReportService.ISSUES_DICT.AZURE.value] = True elif issue['type'] == 'ssh_key': issues_byte_array[ReportService.ISSUES_DICT.STOLEN_SSH_KEYS.value] = True + elif issue['type'] == 'struts2': + issues_byte_array[ReportService.ISSUES_DICT.STRUTS2.value] = True elif issue['type'].endswith('_password') and issue['password'] in config_passwords and \ issue['username'] in config_users or issue['type'] == 'ssh': issues_byte_array[ReportService.ISSUES_DICT.WEAK_PASSWORD.value] = True diff --git a/monkey_island/cc/ui/src/components/pages/ReportPage.js b/monkey_island/cc/ui/src/components/pages/ReportPage.js index f018254b0..2a02a092d 100644 --- a/monkey_island/cc/ui/src/components/pages/ReportPage.js +++ b/monkey_island/cc/ui/src/components/pages/ReportPage.js @@ -23,7 +23,8 @@ class ReportPageComponent extends AuthComponent { SHELLSHOCK: 4, CONFICKER: 5, AZURE: 6, - STOLEN_SSH_KEYS: 7 + STOLEN_SSH_KEYS: 7, + STRUTS2: 8 }; Warning = @@ -321,7 +322,10 @@ class ReportPageComponent extends AuthComponent {
  • Azure machines expose plaintext passwords. (More info)
  • : null} - + {this.state.report.overview.issues[this.Issue.STRUTS2] ? +
  • Struts2 servers are vulnerable to remote code execution. ( + CVE-2017-5638)
  • : null } : @@ -671,6 +675,24 @@ class ReportPageComponent extends AuthComponent { ); } + generateStruts2Issue(issue) { + return ( +
  • + Upgrade Struts2 to version 2.3.32 or 2.5.10.1 or any later versions. + + Struts2 server at {issue.machine} ({issue.ip_address}) is vulnerable to remote code execution attack. +
    + The attack was made possible because the server is using an old version of Jakarta based file upload + Multipart parser. For possible work-arounds and more info read here. +
    +
  • + ); + } + generateIssue = (issue) => { @@ -718,6 +740,9 @@ class ReportPageComponent extends AuthComponent { case 'azure_password': data = this.generateAzureIssue(issue); break; + case 'struts2': + data = this.generateStruts2Issue(issue); + break; } return data; };