forked from p15670423/monkey
Refactored zerologon exploiters report part to conform to new report structure
This commit is contained in:
parent
c504b21d33
commit
e96b8eec38
|
@ -7,6 +7,8 @@ from monkey_island.cc.services.reporting.issue_processing.exploit_processing.pro
|
|||
from monkey_island.cc.services.reporting.issue_processing.exploit_processing.processors.exploit import ExploitProcessor
|
||||
from monkey_island.cc.services.reporting.issue_processing.exploit_processing.processors.shellshock_exploit import \
|
||||
ShellShockExploitProcessor
|
||||
from monkey_island.cc.services.reporting.issue_processing.exploit_processing.processors.zerologon import \
|
||||
ZerologonExploitProcessor
|
||||
|
||||
|
||||
@dataclass
|
||||
|
@ -31,3 +33,4 @@ class ExploiterDescriptorEnum(Enum):
|
|||
MSSQL = ExploiterDescriptor('MSSQLExploiter', 'MSSQL Exploiter', ExploitProcessor)
|
||||
VSFTPD = ExploiterDescriptor('VSFTPDExploiter', 'VSFTPD Backdoor Exploiter', CredExploitProcessor)
|
||||
DRUPAL = ExploiterDescriptor('DrupalExploiter', 'Drupal Server Exploiter', ExploitProcessor)
|
||||
ZEROLOGON = ExploiterDescriptor('ZerologonExploiter', 'ZeroLogon Exploiter', ZerologonExploitProcessor)
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
from monkey_island.cc.services.reporting.issue_processing.exploit_processing.processors.exploit import ExploitProcessor, \
|
||||
ExploiterReportInfo
|
||||
|
||||
|
||||
class ZerologonExploitProcessor:
|
||||
|
||||
@staticmethod
|
||||
def get_exploit_info_by_dict(class_name: str, exploit_dict: dict) -> ExploiterReportInfo:
|
||||
exploit_info = ExploitProcessor.get_exploit_info_by_dict(class_name, exploit_dict)
|
||||
exploit_info.password_restored = exploit_dict['data']['info']['password_restored']
|
||||
return exploit_info
|
|
@ -45,6 +45,7 @@ class ReportService:
|
|||
class DerivedIssueEnum:
|
||||
WEAK_PASSWORD = "weak_password"
|
||||
STOLEN_CREDS = "stolen_creds"
|
||||
ZEROLOGON_PASS_RESTORE_FAILED = "zerologon_pass_restore_failed"
|
||||
|
||||
@staticmethod
|
||||
def get_first_monkey_time():
|
||||
|
@ -264,7 +265,7 @@ class ReportService:
|
|||
return exploiter_info
|
||||
|
||||
@staticmethod
|
||||
def get_exploits() -> dict:
|
||||
def get_exploits() -> List[dict]:
|
||||
query = [{'$match': {'telem_category': 'exploit', 'data.result': True}},
|
||||
{'$group': {'_id': {'ip_address': '$data.machine.ip_addr'},
|
||||
'data': {'$first': '$$ROOT'},
|
||||
|
@ -439,7 +440,6 @@ class ReportService:
|
|||
|
||||
@staticmethod
|
||||
def get_domain_issues():
|
||||
|
||||
ISSUE_GENERATORS = [
|
||||
PTHReportService.get_duplicated_passwords_issues,
|
||||
PTHReportService.get_shared_admins_issues,
|
||||
|
@ -491,8 +491,7 @@ class ReportService:
|
|||
if exploits == default_exploits:
|
||||
return ['default']
|
||||
|
||||
# TODO investigate strange code
|
||||
return [exploit for exploit in exploits]
|
||||
return exploits
|
||||
|
||||
@staticmethod
|
||||
def get_config_ips():
|
||||
|
@ -508,13 +507,12 @@ class ReportService:
|
|||
|
||||
for machine in issues:
|
||||
for issue in issues[machine]:
|
||||
# TODO check if this actually works, because stolen passwords get added to config
|
||||
# so any password will be in config. We need to separate stolen passwords from initial
|
||||
# passwords in config.
|
||||
if ReportService._is_weak_credential_issue(issue, config_users, config_passwords):
|
||||
issue_set.add(ReportService.DerivedIssueEnum.WEAK_PASSWORD)
|
||||
elif ReportService._is_stolen_credential_issue(issue):
|
||||
issue_set.add(ReportService.DerivedIssueEnum.STOLEN_CREDS)
|
||||
elif ReportService._is_zerologon_pass_restore_failed(issue):
|
||||
issue_set.add(ReportService.DerivedIssueEnum.ZEROLOGON_PASS_RESTORE_FAILED)
|
||||
|
||||
issue_set.add(issue['type'])
|
||||
|
||||
|
@ -535,6 +533,11 @@ class ReportService:
|
|||
(issue['credential_type'] == CredentialType.PASSWORD.value or
|
||||
issue['credential_type'] == CredentialType.HASH.value)
|
||||
|
||||
@staticmethod
|
||||
def _is_zerologon_pass_restore_failed(issue: dict):
|
||||
return issue['type'] == ExploiterDescriptorEnum.ZEROLOGON.value.class_name \
|
||||
and not issue['password_restored']
|
||||
|
||||
@staticmethod
|
||||
def is_report_generated():
|
||||
generated_report = mongo.db.report.find_one({})
|
||||
|
@ -594,7 +597,6 @@ class ReportService:
|
|||
|
||||
@staticmethod
|
||||
def get_issues():
|
||||
# Todo refactor these into separate files with a method signature -> dict
|
||||
ISSUE_GENERATORS = [
|
||||
ReportService.get_exploits,
|
||||
ReportService.get_tunnels,
|
||||
|
|
|
@ -46,6 +46,11 @@ import {StolenCredsIssueOverview} from './security/issues/StolenCredsIssue';
|
|||
import {WeakPasswordIssueOverview} from './security/issues/WeakPasswordIssue';
|
||||
import {AzurePasswordIssueOverview, AzurePasswordIssueReport} from './security/issues/AzurePasswordIssue';
|
||||
import {generateStrongUsersOnCritIssue} from './security/issues/StrongUsersOnCritIssue';
|
||||
import {
|
||||
ZerologonIssueOverview,
|
||||
ZerologonIssueReport,
|
||||
ZerologonOverviewWithFailedPassResetWarning
|
||||
} from './security/issues/ZerologonIssue';
|
||||
|
||||
|
||||
class ReportPageComponent extends AuthComponent {
|
||||
|
@ -139,7 +144,12 @@ class ReportPageComponent extends AuthComponent {
|
|||
[this.issueContentTypes.TYPE]: this.issueTypes.DANGER
|
||||
},
|
||||
'ZerologonExploiter': {
|
||||
//TODO add
|
||||
[this.issueContentTypes.OVERVIEW]: ZerologonIssueOverview,
|
||||
[this.issueContentTypes.REPORT]: ZerologonIssueReport,
|
||||
[this.issueContentTypes.TYPE]: this.issueTypes.DANGER
|
||||
},
|
||||
'zerologon_pass_restore_failed': {
|
||||
[this.issueContentTypes.OVERVIEW]: ZerologonOverviewWithFailedPassResetWarning,
|
||||
},
|
||||
'island_cross_segment': {
|
||||
[this.issueContentTypes.OVERVIEW]: crossSegmentIssueOverview,
|
||||
|
@ -162,11 +172,9 @@ class ReportPageComponent extends AuthComponent {
|
|||
[this.issueContentTypes.TYPE]: this.issueTypes.WARNING
|
||||
},
|
||||
'shared_passwords_domain': {
|
||||
[this.issueContentTypes.REPORT]: generateSharedCredsDomainIssue(),
|
||||
[this.issueContentTypes.REPORT]: generateSharedCredsDomainIssue,
|
||||
[this.issueContentTypes.TYPE]: this.issueTypes.WARNING
|
||||
},
|
||||
|
||||
// This issue was missing overview section
|
||||
'strong_users_on_crit': {
|
||||
[this.issueContentTypes.REPORT]: generateStrongUsersOnCritIssue,
|
||||
[this.issueContentTypes.TYPE]: this.issueTypes.DANGER
|
||||
|
@ -224,8 +232,6 @@ class ReportPageComponent extends AuthComponent {
|
|||
if (this.stillLoadingDataFromServer()) {
|
||||
content = <ReportLoader loading={true}/>;
|
||||
} else {
|
||||
|
||||
console.log(this.state.report);
|
||||
content =
|
||||
<div>
|
||||
{this.generateReportOverviewSection()}
|
||||
|
@ -386,7 +392,7 @@ class ReportPageComponent extends AuthComponent {
|
|||
<div>
|
||||
The Monkey uncovered the following possible set of issues:
|
||||
<ul>
|
||||
{overviews}
|
||||
{this.getPotentialSecurityIssuesOverviews()}
|
||||
</ul>
|
||||
</div>
|
||||
:
|
||||
|
@ -416,15 +422,18 @@ class ReportPageComponent extends AuthComponent {
|
|||
|
||||
getPotentialSecurityIssuesOverviews() {
|
||||
let overviews = [];
|
||||
let issues = this.state.report.overview.issues;
|
||||
|
||||
for (let issueKey of this.state.report.overview.issues) {
|
||||
overviews.push(this.IssueDescriptorEnum[issueKey][this.issueContentTypes.OVERVIEW]);
|
||||
for(let i=0; i < issues.length; i++) {
|
||||
if (this.isIssuePotentialSecurityIssue(issues[i])) {
|
||||
overviews.push(this.getIssueOverview(this.IssueDescriptorEnum[issues[i]]));
|
||||
}
|
||||
}
|
||||
return overviews;
|
||||
}
|
||||
|
||||
getImmediateThreats() {
|
||||
let threatCount = this.countImmediateThreats()
|
||||
let threatCount = this.getImmediateThreatCount()
|
||||
return (
|
||||
<div>
|
||||
<h3>
|
||||
|
@ -436,18 +445,19 @@ class ReportPageComponent extends AuthComponent {
|
|||
<span className="badge badge-warning">
|
||||
{threatCount} threats
|
||||
</span>:
|
||||
{this.getImmediateThreatsOverviews()}
|
||||
</>
|
||||
}
|
||||
</div>
|
||||
</div>)
|
||||
}
|
||||
|
||||
countImmediateThreats() {
|
||||
getImmediateThreatCount() {
|
||||
let threatCount = 0;
|
||||
let issues = this.state.report.overview.issues;
|
||||
|
||||
for(let i=0; i < issues.length; i++) {
|
||||
if (this.IssueDescriptorEnum[issues[i]][this.issueContentTypes.TYPE] === this.issueTypes.DANGER) {
|
||||
if(this.isIssueImmediateThreat(issues[i])) {
|
||||
threatCount++;
|
||||
}
|
||||
}
|
||||
|
@ -551,8 +561,7 @@ class ReportPageComponent extends AuthComponent {
|
|||
generateIssue = (issue) => {
|
||||
let issueDescriptor = this.IssueDescriptorEnum[issue.type];
|
||||
|
||||
let reportFnc = (issue) => {
|
||||
};
|
||||
let reportFnc = (issue) => {};
|
||||
if (issue.hasOwnProperty('credential_type')) {
|
||||
reportFnc = issueDescriptor[this.issueContentTypes.REPORT][issue.credential_type];
|
||||
} else {
|
||||
|
|
Loading…
Reference in New Issue