diff --git a/monkey/monkey_island/cc/ui/.babelrc b/monkey/monkey_island/cc/ui/.babelrc index f099584fc..c88dd184d 100644 --- a/monkey/monkey_island/cc/ui/.babelrc +++ b/monkey/monkey_island/cc/ui/.babelrc @@ -3,7 +3,8 @@ [ "@babel/preset-env", { - "useBuiltIns": "entry" + "useBuiltIns": "entry", + "corejs": 3 } ], "@babel/preset-react" diff --git a/monkey/monkey_island/cc/ui/package-lock.json b/monkey/monkey_island/cc/ui/package-lock.json index 6f2983441..21cbef143 100644 --- a/monkey/monkey_island/cc/ui/package-lock.json +++ b/monkey/monkey_island/cc/ui/package-lock.json @@ -952,15 +952,6 @@ "@babel/helper-plugin-utils": "^7.8.3" } }, - "@babel/polyfill": { - "version": "7.8.7", - "resolved": "https://registry.npmjs.org/@babel/polyfill/-/polyfill-7.8.7.tgz", - "integrity": "sha512-LeSfP9bNZH2UOZgcGcZ0PIHUt1ZuHub1L3CVmEyqLxCeDLm4C5Gi8jRH8ZX2PNpDhQCo0z6y/+DIs2JlliXW8w==", - "requires": { - "core-js": "^2.6.5", - "regenerator-runtime": "^0.13.4" - } - }, "@babel/preset-env": { "version": "7.9.6", "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.9.6.tgz", @@ -1071,6 +1062,13 @@ "requires": { "core-js": "^2.6.5", "regenerator-runtime": "^0.13.4" + }, + "dependencies": { + "core-js": { + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", + "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==" + } } }, "@babel/runtime-corejs3": { @@ -2896,6 +2894,11 @@ "regenerator-runtime": "^0.11.0" }, "dependencies": { + "core-js": { + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", + "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==" + }, "regenerator-runtime": { "version": "0.11.1", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", @@ -4017,9 +4020,9 @@ } }, "core-js": { - "version": "2.6.11", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", - "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==" + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.5.tgz", + "integrity": "sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA==" }, "core-js-compat": { "version": "3.6.5", @@ -13659,6 +13662,13 @@ "react-is": "^16.8.4", "react-lifecycles-compat": "^3.0.4", "shortid": "^2.2.14" + }, + "dependencies": { + "core-js": { + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", + "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==" + } } }, "react-jsonschema-form-bs4": { @@ -13678,6 +13688,13 @@ "react-is": "^16.8.4", "react-lifecycles-compat": "^3.0.4", "shortid": "^2.2.14" + }, + "dependencies": { + "core-js": { + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", + "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==" + } } }, "react-lifecycles-compat": { diff --git a/monkey/monkey_island/cc/ui/package.json b/monkey/monkey_island/cc/ui/package.json index f65436983..801a6d17e 100644 --- a/monkey/monkey_island/cc/ui/package.json +++ b/monkey/monkey_island/cc/ui/package.json @@ -59,7 +59,6 @@ "webpack-dev-server": "^3.11.0" }, "dependencies": { - "@babel/polyfill": "^7.8.0", "@emotion/core": "^10.0.22", "@fortawesome/fontawesome-svg-core": "^1.2.29", "@fortawesome/free-regular-svg-icons": "^5.13.1", @@ -68,7 +67,7 @@ "@kunukn/react-collapse": "^1.2.7", "bootstrap": "^4.5.0", "classnames": "^2.2.6", - "core-js": "^2.6.10", + "core-js": "^3.6.5", "d3": "^5.14.1", "downloadjs": "^1.4.7", "fetch": "^1.1.0", diff --git a/monkey/monkey_island/cc/ui/src/components/pages/ReportPage.js b/monkey/monkey_island/cc/ui/src/components/pages/ReportPage.js index 3c2bbf09b..131190905 100644 --- a/monkey/monkey_island/cc/ui/src/components/pages/ReportPage.js +++ b/monkey/monkey_island/cc/ui/src/components/pages/ReportPage.js @@ -121,7 +121,7 @@ class ReportPageComponent extends AuthComponent { renderNavButton = (section) => { return ( - + { diff --git a/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage.js b/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage.js index ff2b15442..155dca40b 100644 --- a/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage.js +++ b/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage.js @@ -277,7 +277,7 @@ class RunMonkeyPageComponent extends AuthComponent { this.state.ips.length > 1 ? :
} @@ -400,7 +400,7 @@ class RunMonkeyPageComponent extends AuthComponent { diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/SecurityReport.js b/monkey/monkey_island/cc/ui/src/components/report-components/SecurityReport.js index a3c29f163..e0d433537 100644 --- a/monkey/monkey_island/cc/ui/src/components/report-components/SecurityReport.js +++ b/monkey/monkey_island/cc/ui/src/components/report-components/SecurityReport.js @@ -161,25 +161,29 @@ class ReportPageComponent extends AuthComponent {

The monkey started propagating from the following machines where it was manually installed: -

    - {this.state.report.overview.manual_monkeys.map(x =>
  • {x}
  • )} -

+
    + {this.state.report.overview.manual_monkeys.map(x =>
  • {x}
  • )} +

The monkeys were run with the following configuration:

{ this.state.report.overview.config_users.length > 0 ? -

- Usernames used for brute-forcing: + <> +

+ Usernames used for brute-forcing: +

    - {this.state.report.overview.config_users.map(x =>
  • {x}
  • )} + {this.state.report.overview.config_users.map(x =>
  • {x}
  • )}
- Passwords used for brute-forcing: +

+ Passwords used for brute-forcing: +

    - {this.state.report.overview.config_passwords.map(x =>
  • {x.substr(0, 3) + '******'}
  • )} + {this.state.report.overview.config_passwords.map(x =>
  • {x.substr(0, 3) + '******'}
  • )}
-

+ :

Brute forcing uses stolen credentials only. No credentials were supplied during Monkey’s @@ -195,7 +199,7 @@ class ReportPageComponent extends AuthComponent {

The Monkey uses the following exploit methods:

    - {this.state.report.overview.config_exploits.map(x =>
  • {x}
  • )} + {this.state.report.overview.config_exploits.map(x =>
  • {x}
  • )}

) @@ -209,7 +213,7 @@ class ReportPageComponent extends AuthComponent {

The Monkey scans the following IPs:

    - {this.state.report.overview.config_ips.map(x =>
  • {x}
  • )} + {this.state.report.overview.config_ips.map(x =>
  • {x}
  • )}

: @@ -313,15 +317,15 @@ class ReportPageComponent extends AuthComponent { The Monkey uncovered the following possible set of issues:
    {this.state.report.overview.warnings[this.Warning.CROSS_SEGMENT] ? -
  • Weak segmentation - Machines from different segments are able to +
  • Weak segmentation - Machines from different segments are able to communicate.
  • : null} {this.state.report.overview.warnings[this.Warning.TUNNEL] ? -
  • Weak segmentation - Machines were able to communicate over unused ports.
  • : null} +
  • Weak segmentation - Machines were able to communicate over unused ports.
  • : null} {this.state.report.overview.warnings[this.Warning.SHARED_LOCAL_ADMIN] ? -
  • Shared local administrator account - Different machines have the same account as a local +
  • Shared local administrator account - Different machines have the same account as a local administrator.
  • : null} {this.state.report.overview.warnings[this.Warning.SHARED_PASSWORDS] ? -
  • Multiple users have the same password
  • : null} +
  • Multiple users have the same password
  • : null}
: @@ -443,21 +447,22 @@ class ReportPageComponent extends AuthComponent { } generateInfoBadges(data_array) { - return data_array.map(badge_data => {badge_data}); + return data_array.map(badge_data => {badge_data}); } generateCrossSegmentIssue(crossSegmentIssue) { - return
  • - {'Communication possible from ' + crossSegmentIssue['source_subnet'] + ' to ' + crossSegmentIssue['target_subnet']} + let crossSegmentIssueOverview = 'Communication possible from ' + crossSegmentIssue['source_subnet'] + ' to ' + crossSegmentIssue['target_subnet'] + return
  • + {crossSegmentIssueOverview}
      {crossSegmentIssue['issues'].map(x => x['is_self'] ? -
    • +
    • {'Machine ' + x['hostname'] + ' has both ips: ' + x['source'] + ' and ' + x['target']}
    • : -
    • +
    • {'IP ' + x['source'] + ' (' + x['hostname'] + ') connected to IP ' + x['target'] + ' using the services: ' + Object.keys(x['services']).join(', ')}
    • @@ -473,7 +478,7 @@ class ReportPageComponent extends AuthComponent { generateSmbPasswordIssue(issue) { return ( -
    • + <> Change {issue.username}'s password to a complex one-use password that is not shared with other computers on the network. @@ -484,13 +489,13 @@ class ReportPageComponent extends AuthComponent { The Monkey authenticated over the SMB protocol with user {issue.username} and its password. -
    • + ); } generateSmbPthIssue(issue) { return ( -
    • + <> Change {issue.username}'s password to a complex one-use password that is not shared with other computers on the network. @@ -501,13 +506,13 @@ class ReportPageComponent extends AuthComponent { The Monkey used a pass-the-hash attack over SMB protocol with user {issue.username}. -
    • + ); } generateWmiPasswordIssue(issue) { return ( -
    • + <> Change {issue.username}'s password to a complex one-use password that is not shared with other computers on the network. @@ -518,13 +523,13 @@ class ReportPageComponent extends AuthComponent { The Monkey authenticated over the WMI protocol with user {issue.username} and its password. -
    • + ); } generateWmiPthIssue(issue) { return ( -
    • + <> Change {issue.username}'s password to a complex one-use password that is not shared with other computers on the network. @@ -535,13 +540,13 @@ class ReportPageComponent extends AuthComponent { The Monkey used a pass-the-hash attack over WMI protocol with user {issue.username}. -
    • + ); } generateSshIssue(issue) { return ( -
    • + <> Change {issue.username}'s password to a complex one-use password that is not shared with other computers on the network. @@ -552,13 +557,13 @@ class ReportPageComponent extends AuthComponent { The Monkey authenticated over the SSH protocol with user {issue.username} and its password. -
    • + ); } generateSshKeysIssue(issue) { return ( -
    • + <> Protect {issue.ssh_key} private key with a pass phrase. The machine {issue.machine} ({issue.ssh_key}. -
    • + ); } generateSambaCryIssue(issue) { return ( -
    • + <> Change {issue.username}'s password to a complex one-use password that is not shared with other computers on the network.
      @@ -589,13 +594,13 @@ class ReportPageComponent extends AuthComponent { className="badge badge-success">{issue.username} and its password, and used the SambaCry vulnerability. -
    • + ); } generateVsftpdBackdoorIssue(issue) { return ( -
    • + <> Update your VSFTPD server to the latest version vsftpd-3.0.3. The machine {issue.machine} (here. -
    • + ); } generateElasticIssue(issue) { return ( -
    • + <> Update your Elastic Search server to version 1.4.3 and up. The machine {issue.machine} ( The attack was made possible because the Elastic Search server was not patched against CVE-2015-1427. -
    • + ); } generateShellshockIssue(issue) { return ( -
    • + <> Update your Bash to a ShellShock-patched version. The machine {issue.machine} ({issue.port} was vulnerable to a shell injection attack on the paths: {this.generateShellshockPathListBadges(issue.paths)}. -
    • + ); } generateAzureIssue(issue) { return ( -
    • + <> Delete VM Access plugin configuration files. Credentials could be stolen from here. -
    • + ); } generateConfickerIssue(issue) { return ( -
    • + <> Install the latest Windows updates or upgrade to a newer operating system. The machine {issue.machine} ( -
    • + ); } generateIslandCrossSegmentIssue(issue) { return ( -
    • + <> Segment your network and make sure there is no communication between machines from different segments. The network can probably be segmented. A monkey instance on -
    • + ); } generateSharedCredsDomainIssue(issue) { return ( -
    • + <> Some domain users are sharing passwords, this should be fixed by changing passwords. These users are sharing access password: {this.generateInfoBadges(issue.shared_with)}. -
    • + ); } generateSharedCredsIssue(issue) { return ( -
    • + <> Some users are sharing passwords, this should be fixed by changing passwords. These users are sharing access password: {this.generateInfoBadges(issue.shared_with)}. -
    • + ); } generateSharedLocalAdminsIssue(issue) { return ( -
    • + <> Make sure the right administrator accounts are managing the right machines, and that there isn’t an unintentional local admin sharing. @@ -730,13 +735,13 @@ class ReportPageComponent extends AuthComponent { className="badge badge-primary">{issue.username} is defined as an administrator: {this.generateInfoBadges(issue.shared_machines)} -
    • + ); } generateStrongUsersOnCritIssue(issue) { return ( -
    • + <> This critical machine is open to attacks via strong users with access to it. The services: {this.generateInfoBadges(issue.services)} have been found on the machine @@ -744,26 +749,26 @@ class ReportPageComponent extends AuthComponent { These users has access to it: {this.generateInfoBadges(issue.threatening_users)}. -
    • + ); } generateTunnelIssue(issue) { return ( -
    • + <> Use micro-segmentation policies to disable communication other than the required. Machines are not locked down at port level. Network tunnel was set up from {issue.machine} to {issue.dest}. -
    • + ); } generateStruts2Issue(issue) { return ( -
    • + <> Upgrade Struts2 to version 2.3.32 or 2.5.10.1 or any later versions. Struts2 server at {issue.machine} (here. -
    • + ); } generateWebLogicIssue(issue) { return ( -
    • + <> Update Oracle WebLogic server to the latest supported version. Oracle WebLogic server at {issue.machine} ( CVE-2017-10271 or CVE-2019-2725 -
    • + ); } generateHadoopIssue(issue) { return ( -
    • + <> Run Hadoop in secure mode ( add Kerberos authentication). @@ -809,13 +814,13 @@ class ReportPageComponent extends AuthComponent {
      The attack was made possible due to default Hadoop/Yarn configuration being insecure. -
    • + ); } generateMSSQLIssue(issue) { return ( -
    • + <> Disable the xp_cmdshell option. The machine {issue.machine} ( Microsoft's documentation. -
    • + ); } generateIssue = (issue) => { - let data; + let issueData; switch (issue.type) { case 'vsftp': - data = this.generateVsftpdBackdoorIssue(issue); + issueData = this.generateVsftpdBackdoorIssue(issue); break; case 'smb_password': - data = this.generateSmbPasswordIssue(issue); + issueData = this.generateSmbPasswordIssue(issue); break; case 'smb_pth': - data = this.generateSmbPthIssue(issue); + issueData = this.generateSmbPthIssue(issue); break; case 'wmi_password': - data = this.generateWmiPasswordIssue(issue); + issueData = this.generateWmiPasswordIssue(issue); break; case 'wmi_pth': - data = this.generateWmiPthIssue(issue); + issueData = this.generateWmiPthIssue(issue); break; case 'ssh': - data = this.generateSshIssue(issue); + issueData = this.generateSshIssue(issue); break; case 'ssh_key': - data = this.generateSshKeysIssue(issue); + issueData = this.generateSshKeysIssue(issue); break; case 'sambacry': - data = this.generateSambaCryIssue(issue); + issueData = this.generateSambaCryIssue(issue); break; case 'elastic': - data = this.generateElasticIssue(issue); + issueData = this.generateElasticIssue(issue); break; case 'shellshock': - data = this.generateShellshockIssue(issue); + issueData = this.generateShellshockIssue(issue); break; case 'conficker': - data = this.generateConfickerIssue(issue); + issueData = this.generateConfickerIssue(issue); break; case 'island_cross_segment': - data = this.generateIslandCrossSegmentIssue(issue); + issueData = this.generateIslandCrossSegmentIssue(issue); break; case 'shared_passwords': - data = this.generateSharedCredsIssue(issue); + issueData = this.generateSharedCredsIssue(issue); break; case 'shared_passwords_domain': - data = this.generateSharedCredsDomainIssue(issue); + issueData = this.generateSharedCredsDomainIssue(issue); break; case 'shared_admins_domain': - data = this.generateSharedLocalAdminsIssue(issue); + issueData = this.generateSharedLocalAdminsIssue(issue); break; case 'strong_users_on_crit': - data = this.generateStrongUsersOnCritIssue(issue); + issueData = this.generateStrongUsersOnCritIssue(issue); break; case 'tunnel': - data = this.generateTunnelIssue(issue); + issueData = this.generateTunnelIssue(issue); break; case 'azure_password': - data = this.generateAzureIssue(issue); + issueData = this.generateAzureIssue(issue); break; case 'struts2': - data = this.generateStruts2Issue(issue); + issueData = this.generateStruts2Issue(issue); break; case 'weblogic': - data = this.generateWebLogicIssue(issue); + issueData = this.generateWebLogicIssue(issue); break; case 'hadoop': - data = this.generateHadoopIssue(issue); + issueData = this.generateHadoopIssue(issue); break; case 'mssql': - data = this.generateMSSQLIssue(issue); + issueData = this.generateMSSQLIssue(issue); break; } - return data; + return
    • {issueData}
    • ; }; generateIssues = (issues) => { let issuesDivArray = []; for (let machine of Object.keys(issues)) { issuesDivArray.push( -
    • +
    • {machine}

        {issues[machine].map(this.generateIssue)} diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/common/RenderArrays.js b/monkey/monkey_island/cc/ui/src/components/report-components/common/RenderArrays.js new file mode 100644 index 000000000..936a2825b --- /dev/null +++ b/monkey/monkey_island/cc/ui/src/components/report-components/common/RenderArrays.js @@ -0,0 +1,8 @@ +import React from "react"; + +export let renderArray = function (val) { + return <>{val.map(x =>
        {x}
        )}; +}; +export let renderIpAddresses = function (val) { + return
        {renderArray(val.ip_addresses)} {(val.domain_name ? ' ('.concat(val.domain_name, ')') : '')}
        ; +}; diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/security/BreachedServers.js b/monkey/monkey_island/cc/ui/src/components/report-components/security/BreachedServers.js index fdd9398fb..1a4b02efe 100644 --- a/monkey/monkey_island/cc/ui/src/components/report-components/security/BreachedServers.js +++ b/monkey/monkey_island/cc/ui/src/components/report-components/security/BreachedServers.js @@ -1,14 +1,8 @@ import React from 'react'; import ReactTable from 'react-table'; import Pluralize from 'pluralize'; +import {renderArray, renderIpAddresses} from "../common/RenderArrays"; -let renderArray = function (val) { - return
        {val.map(x =>
        {x}
        )}
        ; -}; - -let renderIpAddresses = function (val) { - return
        {renderArray(val.ip_addresses)} {(val.domain_name ? ' ('.concat(val.domain_name, ')') : '')}
        ; -}; const columns = [ { diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/security/PostBreach.js b/monkey/monkey_island/cc/ui/src/components/report-components/security/PostBreach.js index 6bbe6b809..cc9ea1c20 100644 --- a/monkey/monkey_island/cc/ui/src/components/report-components/security/PostBreach.js +++ b/monkey/monkey_island/cc/ui/src/components/report-components/security/PostBreach.js @@ -1,14 +1,7 @@ import React from 'react'; import ReactTable from 'react-table'; import Pluralize from 'pluralize'; - -let renderArray = function (val) { - return {val.map(x => {x})}; -}; - -let renderIpAddresses = function (val) { - return {renderArray(val.ip_addresses)} {(val.domain_name ? ' ('.concat(val.domain_name, ')') : '')} ; -}; +import {renderIpAddresses} from "../common/RenderArrays"; let renderMachine = function (data) { return
        {data.label} ( {renderIpAddresses(data)} )
        diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/security/ScannedServers.js b/monkey/monkey_island/cc/ui/src/components/report-components/security/ScannedServers.js index 94c3d4a0e..bf0eee7d6 100644 --- a/monkey/monkey_island/cc/ui/src/components/report-components/security/ScannedServers.js +++ b/monkey/monkey_island/cc/ui/src/components/report-components/security/ScannedServers.js @@ -1,14 +1,8 @@ import React from 'react'; import ReactTable from 'react-table'; import Pluralize from 'pluralize'; +import {renderArray, renderIpAddresses} from "../common/RenderArrays"; -let renderArray = function (val) { - return
        {val.map(x =>
        {x}
        )}
        ; -}; - -let renderIpAddresses = function (val) { - return
        {renderArray(val.ip_addresses)} {(val.domain_name ? ' ('.concat(val.domain_name, ')') : '')}
        ; -}; const columns = [ { diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/security/StrongUsers.js b/monkey/monkey_island/cc/ui/src/components/report-components/security/StrongUsers.js index 2c2a79c07..013426657 100644 --- a/monkey/monkey_island/cc/ui/src/components/report-components/security/StrongUsers.js +++ b/monkey/monkey_island/cc/ui/src/components/report-components/security/StrongUsers.js @@ -1,10 +1,7 @@ import React from 'react'; import ReactTable from 'react-table' +import {renderArray} from "../common/RenderArrays"; -let renderArray = function (val) { - console.log(val); - return
        {val.map(x =>
        {x}
        )}
        ; -}; const columns = [ { diff --git a/monkey/monkey_island/cc/ui/src/index.js b/monkey/monkey_island/cc/ui/src/index.js index e6264f2ad..a80de72fe 100644 --- a/monkey/monkey_island/cc/ui/src/index.js +++ b/monkey/monkey_island/cc/ui/src/index.js @@ -1,4 +1,5 @@ -import '@babel/polyfill'; +import 'core-js/stable'; +import 'regenerator-runtime/runtime'; import 'core-js/fn/object/assign'; import React from 'react'; import ReactDOM from 'react-dom';