From 8ccdba7528fbdd8ff9a304c6ff35e6a2d1590ef4 Mon Sep 17 00:00:00 2001
From: Ilija Lazoroski
Date: Thu, 14 Jul 2022 16:50:04 +0200
Subject: [PATCH] UI: Grab credentials from endpoint and render them
---
.../report-components/SecurityReport.js | 108 ++++++++++++------
1 file changed, 76 insertions(+), 32 deletions(-)
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 d91d2d0fc..04b05f04f 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
@@ -45,6 +45,8 @@ import {
zerologonOverviewWithFailedPassResetWarning
} from './security/issues/ZerologonIssue';
import {powershellIssueOverview, powershellIssueReport} from './security/issues/PowershellIssue';
+import {getCredentialsSecrets, getCredentialsUsernames} from './credentialParsing';
+import UsedCredentials from './security/UsedCredentials.tsx';
class ReportPageComponent extends AuthComponent {
@@ -161,15 +163,31 @@ class ReportPageComponent extends AuthComponent {
this.state = {
report: props.report,
graph: {nodes: [], edges: []},
- nodeStateList: []
+ nodeStateList: [],
+ stolenCredentials: [],
+ configuredCredentials: []
};
}
componentDidMount() {
this.getNodeStateListFromServer();
+ this.getCredentialsFromServer();
this.updateMapFromServer();
}
+ getCredentialsFromServer = () => {
+ this.authFetch('/api/propagation-credentials/stolen-credentials')
+ .then(res => res.json())
+ .then(creds => {
+ this.setState({stolenCredentials: creds});
+ })
+ this.authFetch('/api/propagation-credentials/configured-credentials')
+ .then(res => res.json())
+ .then(creds => {
+ this.setState({configuredCredentials: creds});
+ })
+ }
+
getNodeStateListFromServer = () => {
this.authFetch('/api/netmap/node-states')
.then(res => res.json())
@@ -184,10 +202,19 @@ class ReportPageComponent extends AuthComponent {
componentDidUpdate(prevProps) {
if (this.props.report !== prevProps.report) {
- this.setState({report: this.props.report})
+ this.updateReport(this.props.report);
}
}
+ updateReport(report) {
+ let newReport = this.addIssuesToOverviewIssues(report);
+
+ this.setState({
+ report: newReport
+ })
+ }
+
+
render() {
let content;
@@ -273,39 +300,20 @@ class ReportPageComponent extends AuthComponent {
The monkeys were run with the following configuration:
- {
- this.state.report.overview.config_users.length > 0 ?
- <>
-
- Usernames used for brute-forcing:
-
-
- {this.state.report.overview.config_users.map(x => - {x}
)}
-
-
- Passwords used for brute-forcing:
-
-
- {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
- configuration.
-
- }
+
{
this.state.report.overview.config_exploits.length > 0 ?
-
- The Monkey uses the following exploit methods:
-
- {this.state.report.overview.config_exploits.map(x => - {x}
)}
-
-
+ (
+
+ The Monkey attempted the following exploitation methods:
+
+ {this.state.report.overview.config_exploits.map(x => - {x}
)}
+
+
+ )
:
- No exploits are used by the Monkey.
+ No exploiters were enabled.
}
{
@@ -535,7 +543,7 @@ class ReportPageComponent extends AuthComponent {
-
+
@@ -582,6 +590,42 @@ class ReportPageComponent extends AuthComponent {
}
return ;
};
+
+ addIssuesToOverviewIssues(report) {
+ let issues = report.overview.issues;
+ let overview_issues = [];
+
+ for(let i=0; i < issues.length; i++) {
+ if (this.isWeakCredentialsIssue(issues[i])) {
+ overview_issues.push('weak_password')
+ } else if (this.isStolenCredentialsIssue(issues[i])) {
+ overview_issues.push('stolen_creds');
+ } else {
+ overview_issues.push(issues[i])
+ }
+ }
+
+ const newOverview = { ...report.overview, issues : overview_issues };
+
+ const newReport = { ...report, overview : newOverview };
+
+
+ return newReport;
+ }
+
+ isWeakCredentialsIssue(issue) {
+ return (Object.prototype.hasOwnProperty.call(issue, 'credential_type') &&
+ issue.credential_type === 'PASSWORD' &&
+ getCredentialsSecrets(this.state.configuredCredentials, 'password').includes(issue.password) &&
+ getCredentialsUsernames(this.state.configuredCredentials).includes(issue.username))
+ }
+
+ isStolenCredentialsIssue(issue) {
+ return ( Object.prototype.hasOwnProperty.call(issue, 'credential_type') &&
+ (issue.credential_type === 'PASSWORD' ||
+ issue.credential_type === 'NT_HASH' ||
+ issue.credential_type === 'LM_HASH'))
+ }
}
export default ReportPageComponent;