forked from p15670423/monkey
T1210 implemented, T1197 started
This commit is contained in:
parent
c3d717a6bf
commit
993736a973
|
@ -8,3 +8,6 @@ class ScanStatus(Enum):
|
||||||
SCANNED = 1
|
SCANNED = 1
|
||||||
# Technique was attempted and succeeded
|
# Technique was attempted and succeeded
|
||||||
USED = 2
|
USED = 2
|
||||||
|
|
||||||
|
|
||||||
|
BITS_UPLOAD_STRING = "Bits job was used to upload monkey to a remote system."
|
|
@ -11,6 +11,8 @@ from infection_monkey.exploit.web_rce import WebRCE
|
||||||
from infection_monkey.model import WGET_HTTP_UPLOAD, RDP_CMDLINE_HTTP, CHECK_COMMAND, ID_STRING, CMD_PREFIX,\
|
from infection_monkey.model import WGET_HTTP_UPLOAD, RDP_CMDLINE_HTTP, CHECK_COMMAND, ID_STRING, CMD_PREFIX,\
|
||||||
DOWNLOAD_TIMEOUT
|
DOWNLOAD_TIMEOUT
|
||||||
from infection_monkey.network.elasticfinger import ES_PORT, ES_SERVICE
|
from infection_monkey.network.elasticfinger import ES_PORT, ES_SERVICE
|
||||||
|
from infection_monkey.transport.attack_telems.victim_host_telem import VictimHostTelem
|
||||||
|
from common.utils.attack_utils import ScanStatus, BITS_UPLOAD_STRING
|
||||||
|
|
||||||
import re
|
import re
|
||||||
|
|
||||||
|
@ -58,6 +60,12 @@ class ElasticGroovyExploiter(WebRCE):
|
||||||
return False
|
return False
|
||||||
return result[0]
|
return result[0]
|
||||||
|
|
||||||
|
def upload_monkey(self, url, commands=None):
|
||||||
|
result = super(ElasticGroovyExploiter, self).upload_monkey(url, commands)
|
||||||
|
if 'windows' in self.host.os['type'] and result:
|
||||||
|
VictimHostTelem("T1197", ScanStatus.USED.value, self.host, BITS_UPLOAD_STRING)
|
||||||
|
return result
|
||||||
|
|
||||||
def get_results(self, response):
|
def get_results(self, response):
|
||||||
"""
|
"""
|
||||||
Extracts the result data from our attack
|
Extracts the result data from our attack
|
||||||
|
|
|
@ -17,6 +17,8 @@ from infection_monkey.network.tools import check_tcp_port
|
||||||
from infection_monkey.exploit.tools import build_monkey_commandline
|
from infection_monkey.exploit.tools import build_monkey_commandline
|
||||||
from infection_monkey.utils import utf_to_ascii
|
from infection_monkey.utils import utf_to_ascii
|
||||||
from common.utils.exploit_enum import ExploitType
|
from common.utils.exploit_enum import ExploitType
|
||||||
|
from infection_monkey.transport.attack_telems.victim_host_telem import VictimHostTelem
|
||||||
|
from common.utils.attack_utils import ScanStatus, BITS_UPLOAD_STRING
|
||||||
|
|
||||||
__author__ = 'hoffer'
|
__author__ = 'hoffer'
|
||||||
|
|
||||||
|
@ -312,6 +314,7 @@ class RdpExploiter(HostExploiter):
|
||||||
client_factory.done_event.wait()
|
client_factory.done_event.wait()
|
||||||
|
|
||||||
if client_factory.success:
|
if client_factory.success:
|
||||||
|
VictimHostTelem("T1197", ScanStatus.USED.value, self.host, BITS_UPLOAD_STRING)
|
||||||
exploited = True
|
exploited = True
|
||||||
self.report_login_attempt(True, user, password)
|
self.report_login_attempt(True, user, password)
|
||||||
break
|
break
|
||||||
|
|
|
@ -7,6 +7,8 @@ from infection_monkey.exploit import HostExploiter
|
||||||
from infection_monkey.model import *
|
from infection_monkey.model import *
|
||||||
from infection_monkey.exploit.tools import get_target_monkey, get_monkey_depth, build_monkey_commandline, HTTPTools
|
from infection_monkey.exploit.tools import get_target_monkey, get_monkey_depth, build_monkey_commandline, HTTPTools
|
||||||
from infection_monkey.network.tools import check_tcp_port, tcp_port_to_service
|
from infection_monkey.network.tools import check_tcp_port, tcp_port_to_service
|
||||||
|
from infection_monkey.transport.attack_telems.victim_host_telem import VictimHostTelem
|
||||||
|
from common.utils.attack_utils import ScanStatus, BITS_UPLOAD_STRING
|
||||||
|
|
||||||
__author__ = 'VakarisZ'
|
__author__ = 'VakarisZ'
|
||||||
|
|
||||||
|
@ -307,6 +309,7 @@ class WebRCE(HostExploiter):
|
||||||
if not isinstance(resp, bool) and POWERSHELL_NOT_FOUND in resp:
|
if not isinstance(resp, bool) and POWERSHELL_NOT_FOUND in resp:
|
||||||
LOG.info("Powershell not found in host. Using bitsadmin to download.")
|
LOG.info("Powershell not found in host. Using bitsadmin to download.")
|
||||||
backup_command = RDP_CMDLINE_HTTP % {'monkey_path': dest_path, 'http_path': http_path}
|
backup_command = RDP_CMDLINE_HTTP % {'monkey_path': dest_path, 'http_path': http_path}
|
||||||
|
VictimHostTelem("T1197", ScanStatus.USED.value, self.host, BITS_UPLOAD_STRING)
|
||||||
resp = self.exploit(url, backup_command)
|
resp = self.exploit(url, backup_command)
|
||||||
return resp
|
return resp
|
||||||
|
|
||||||
|
|
|
@ -17,8 +17,6 @@ from infection_monkey.system_info import SystemInfoCollector
|
||||||
from infection_monkey.system_singleton import SystemSingleton
|
from infection_monkey.system_singleton import SystemSingleton
|
||||||
from infection_monkey.windows_upgrader import WindowsUpgrader
|
from infection_monkey.windows_upgrader import WindowsUpgrader
|
||||||
from infection_monkey.post_breach.post_breach_handler import PostBreach
|
from infection_monkey.post_breach.post_breach_handler import PostBreach
|
||||||
from common.utils.attack_status_enum import ScanStatus
|
|
||||||
from infection_monkey.transport.attack_telems.victim_host_telem import VictimHostTelem
|
|
||||||
|
|
||||||
__author__ = 'itamar'
|
__author__ = 'itamar'
|
||||||
|
|
||||||
|
@ -181,11 +179,9 @@ class InfectionMonkey(object):
|
||||||
for exploiter in [exploiter(machine) for exploiter in self._exploiters]:
|
for exploiter in [exploiter(machine) for exploiter in self._exploiters]:
|
||||||
if self.try_exploiting(machine, exploiter):
|
if self.try_exploiting(machine, exploiter):
|
||||||
host_exploited = True
|
host_exploited = True
|
||||||
VictimHostTelem('T1210', ScanStatus.USED.value, machine=machine).send()
|
|
||||||
break
|
break
|
||||||
if not host_exploited:
|
if not host_exploited:
|
||||||
self._fail_exploitation_machines.add(machine)
|
self._fail_exploitation_machines.add(machine)
|
||||||
VictimHostTelem('T1210', ScanStatus.SCANNED.value, machine=machine).send()
|
|
||||||
if not self._keep_running:
|
if not self._keep_running:
|
||||||
break
|
break
|
||||||
|
|
||||||
|
|
|
@ -3,11 +3,11 @@ from flask import jsonify
|
||||||
from cc.auth import jwt_required
|
from cc.auth import jwt_required
|
||||||
from cc.services.attack.attack_report import AttackReportService
|
from cc.services.attack.attack_report import AttackReportService
|
||||||
|
|
||||||
__author__ = "itay.mizeretz"
|
__author__ = "VakarisZ"
|
||||||
|
|
||||||
|
|
||||||
class AttackReport(flask_restful.Resource):
|
class AttackReport(flask_restful.Resource):
|
||||||
|
|
||||||
@jwt_required()
|
@jwt_required()
|
||||||
def get(self):
|
def get(self):
|
||||||
return jsonify(AttackReportService.get_report())
|
return jsonify(AttackReportService.get_latest_report()['techniques'])
|
|
@ -69,10 +69,12 @@ class Root(flask_restful.Resource):
|
||||||
infection_done = NodeService.is_monkey_finished_running()
|
infection_done = NodeService.is_monkey_finished_running()
|
||||||
if not infection_done:
|
if not infection_done:
|
||||||
report_done = False
|
report_done = False
|
||||||
|
attack_report_done = False
|
||||||
else:
|
else:
|
||||||
if is_any_exists:
|
if is_any_exists:
|
||||||
ReportService.get_report()
|
ReportService.get_report()
|
||||||
AttackReportService.get_report()
|
AttackReportService.get_latest_report()
|
||||||
report_done = ReportService.is_report_generated()
|
report_done = ReportService.is_report_generated()
|
||||||
attack_report_done = AttackReportService.is_report_generated()
|
attack_report_done = AttackReportService.is_report_generated()
|
||||||
return dict(run_server=True, run_monkey=is_any_exists, infection_done=infection_done, report_done=report_done)
|
return dict(run_server=True, run_monkey=is_any_exists, infection_done=infection_done,
|
||||||
|
report_done=report_done, attack_report_done=attack_report_done)
|
||||||
|
|
|
@ -1,37 +1,58 @@
|
||||||
import logging
|
import logging
|
||||||
from cc.services.attack.technique_reports import T1210
|
from cc.services.attack.technique_reports import T1210
|
||||||
from cc.services.attack.attack_telem import get_latest_telem
|
from cc.services.attack.attack_telem import get_latest_telem
|
||||||
|
from cc.services.attack.attack_config import get_technique_values
|
||||||
from cc.database import mongo
|
from cc.database import mongo
|
||||||
|
|
||||||
__author__ = "VakarisZ"
|
__author__ = "VakarisZ"
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
TECHNIQUES = {'T1210': T1210}
|
TECHNIQUES = {'T1210': T1210}
|
||||||
|
|
||||||
|
REPORT_NAME = 'new_report'
|
||||||
|
|
||||||
|
|
||||||
class AttackReportService:
|
class AttackReportService:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def generate_new_report():
|
def generate_new_report():
|
||||||
report = {'techniques': {}, 'meta': {get_latest_telem()}}
|
"""
|
||||||
for tech_id, value in
|
Generates new report based on telemetries, replaces old report in db with new one.
|
||||||
report.update({'T1210': T1210.get_report_data()})
|
:return: Report object
|
||||||
report.update({''})
|
"""
|
||||||
|
report = {'techniques': {}, 'meta': get_latest_telem(), 'name': REPORT_NAME}
|
||||||
|
for tech_id, value in get_technique_values().items():
|
||||||
|
if value:
|
||||||
|
try:
|
||||||
|
report['techniques'].update({tech_id: TECHNIQUES[tech_id].get_report_data()})
|
||||||
|
except KeyError as e:
|
||||||
|
LOG.error("Attack technique does not have it's report component added "
|
||||||
|
"to attack report service. %s" % e)
|
||||||
|
mongo.db.attack_report.replace_one({'name': REPORT_NAME}, report, upsert=True)
|
||||||
return report
|
return report
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_latest_report():
|
def get_latest_report():
|
||||||
|
"""
|
||||||
|
Gets latest report (by retrieving it from db or generating a new one).
|
||||||
|
:return: report dict.
|
||||||
|
"""
|
||||||
if AttackReportService.is_report_generated():
|
if AttackReportService.is_report_generated():
|
||||||
telem_time = get_latest_telem_time()
|
telem_time = get_latest_telem()
|
||||||
lates_report = mongo.db.attack_report.find_one({'name': 'new_report'})
|
latest_report = mongo.db.attack_report.find_one({'name': REPORT_NAME})
|
||||||
if telem_time == lates_report['telem_time']:
|
if telem_time and telem_time['timestamp'] == latest_report['meta']['timestamp']:
|
||||||
return lates_report
|
return latest_report
|
||||||
return AttackReportService.generate_new_report()
|
return AttackReportService.generate_new_report()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def is_report_generated():
|
def is_report_generated():
|
||||||
|
"""
|
||||||
|
Checks if report is generated
|
||||||
|
:return: True if report exists, False otherwise
|
||||||
|
"""
|
||||||
generated_report = mongo.db.attack_report.find_one({})
|
generated_report = mongo.db.attack_report.find_one({})
|
||||||
return generated_report is not None
|
return generated_report is not None
|
||||||
|
|
|
@ -22,4 +22,4 @@ def set_results(technique, data):
|
||||||
|
|
||||||
|
|
||||||
def get_latest_telem():
|
def get_latest_telem():
|
||||||
return mongo.db.attack_results.find({'name': 'latest'})
|
return mongo.db.attack_results.find_one({'name': 'latest'})
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
from monkey_island.cc.services.attack.technique_reports.technique_service import *
|
||||||
|
from cc.services.report import ReportService
|
||||||
|
|
||||||
|
__author__ = "VakarisZ"
|
||||||
|
|
||||||
|
TECHNIQUE = "T1197"
|
||||||
|
MESSAGES = {
|
||||||
|
'unscanned': "Monkey didn't try to use any bits jobs.",
|
||||||
|
'scanned': "Monkey tried to use bits jobs but failed.",
|
||||||
|
'used': "Monkey successfully used bits jobs at least once in the network."
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def get_report_data():
|
||||||
|
data = get_tech_base_data(TECHNIQUE, MESSAGES)
|
||||||
|
return data
|
|
@ -1,27 +1,18 @@
|
||||||
from monkey_island.cc.services.attack.technique_reports.technique_service import technique_status, technique_title
|
from monkey_island.cc.services.attack.technique_reports.technique_service import *
|
||||||
from common.utils.attack_status_enum import ScanStatus
|
|
||||||
from cc.services.report import ReportService
|
from cc.services.report import ReportService
|
||||||
|
|
||||||
__author__ = "VakarisZ"
|
__author__ = "VakarisZ"
|
||||||
|
|
||||||
TECHNIQUE = "T1210"
|
TECHNIQUE = "T1210"
|
||||||
UNSCANNED_MSG = "Monkey didn't scan any remote services. Maybe it didn't find any machines on the network?"
|
MESSAGES = {
|
||||||
SCANNED_MSG = "Monkey scanned for remote services on the network, but couldn't exploit any of them."
|
'unscanned': "Monkey didn't scan any remote services. Maybe it didn't find any machines on the network?",
|
||||||
USED_MSG = "Monkey scanned for remote services and exploited some on the network."
|
'scanned': "Monkey scanned for remote services on the network, but couldn't exploit any of them.",
|
||||||
|
'used': "Monkey scanned for remote services and exploited some on the network."
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def get_report_data():
|
def get_report_data():
|
||||||
data = {}
|
data = get_tech_base_data(TECHNIQUE, MESSAGES)
|
||||||
status = technique_status(TECHNIQUE)
|
|
||||||
title = technique_title(TECHNIQUE)
|
|
||||||
data.update({'status': status.name, 'title': title})
|
|
||||||
if status == ScanStatus.UNSCANNED:
|
|
||||||
data.update({'message': UNSCANNED_MSG})
|
|
||||||
return data
|
|
||||||
elif status == ScanStatus.SCANNED:
|
|
||||||
data.update({'message': SCANNED_MSG})
|
|
||||||
else:
|
|
||||||
data.update({'message': USED_MSG})
|
|
||||||
data.update({'scanned_machines': ReportService.get_scanned()})
|
data.update({'scanned_machines': ReportService.get_scanned()})
|
||||||
data.update({'exploited_machines': ReportService.get_exploited()})
|
data.update({'exploited_machines': ReportService.get_exploited()})
|
||||||
return data
|
return data
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
from cc.database import mongo
|
from cc.database import mongo
|
||||||
from common.utils.attack_status_enum import ScanStatus
|
from common.utils.attack_utils import ScanStatus
|
||||||
from cc.services.attack.attack_config import get_technique
|
from cc.services.attack.attack_config import get_technique
|
||||||
|
|
||||||
__author__ = "VakarisZ"
|
__author__ = "VakarisZ"
|
||||||
|
@ -16,3 +16,17 @@ def technique_status(technique):
|
||||||
|
|
||||||
def technique_title(technique):
|
def technique_title(technique):
|
||||||
return get_technique(technique)['title']
|
return get_technique(technique)['title']
|
||||||
|
|
||||||
|
|
||||||
|
def get_tech_base_data(technique, messages):
|
||||||
|
data = {}
|
||||||
|
status = technique_status(technique)
|
||||||
|
title = technique_title(technique)
|
||||||
|
data.update({'status': status.name, 'title': title})
|
||||||
|
if status == ScanStatus.UNSCANNED:
|
||||||
|
data.update({'message': messages['unscanned']})
|
||||||
|
elif status == ScanStatus.SCANNED:
|
||||||
|
data.update({'message': messages['scanned']})
|
||||||
|
else:
|
||||||
|
data.update({'message': messages['used']})
|
||||||
|
return data
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
import React from 'react';
|
||||||
|
import '../../styles/Collapse.scss'
|
||||||
|
import {Link} from "react-router-dom";
|
||||||
|
|
||||||
|
let renderArray = function(val) {
|
||||||
|
return <span>{val.map(x => <span key={x.toString()}>{x} </span>)}</span>;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
let renderMachine = function (val, index, exploited=false) {
|
||||||
|
return (
|
||||||
|
<div key={index}>
|
||||||
|
{renderArray(val.ip_addresses)}
|
||||||
|
{(val.domain_name ? " (".concat(val.domain_name, ")") : " (".concat(val.label, ")"))} :
|
||||||
|
{exploited ? renderArray(val.exploits) : renderArray(val.services)}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
class T1210 extends React.Component {
|
||||||
|
|
||||||
|
renderScannedMachines = (machines) => {
|
||||||
|
let content = [];
|
||||||
|
for (let i = 0; i < machines.length; i++ ){
|
||||||
|
if (machines[i].services.length !== 0){
|
||||||
|
content.push(renderMachine(machines[i], i))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return <div>{content}</div>;
|
||||||
|
};
|
||||||
|
|
||||||
|
renderExploitedMachines = (machines) => {
|
||||||
|
let content = [];
|
||||||
|
for (let i = 0; i < machines.length; i++ ){
|
||||||
|
if (machines[i].exploits.length !== 0){
|
||||||
|
content.push(renderMachine(machines[i], i, true))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return <div>{content}</div>;
|
||||||
|
};
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
console.log(this.props);
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div>{this.props.data.message}</div>
|
||||||
|
<div>Found services: </div>
|
||||||
|
{this.renderScannedMachines(this.props.data.scanned_machines)}
|
||||||
|
<div>Successful exploiters:</div>
|
||||||
|
{this.renderExploitedMachines(this.props.data.exploited_machines)}
|
||||||
|
<div className="attack-report footer-text">
|
||||||
|
To get more info about scanned and exploited machines view <Link to="/report">standard report.</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default T1210;
|
|
@ -1,30 +1,61 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactTable from 'react-table'
|
|
||||||
import '../../styles/Collapse.scss'
|
import '../../styles/Collapse.scss'
|
||||||
import Collapse from '@kunukn/react-collapse';
|
import {Link} from "react-router-dom";
|
||||||
|
|
||||||
let renderArray = function(val) {
|
let renderArray = function(val) {
|
||||||
return <div>{val.map(x => <div>{x}</div>)}</div>;
|
return <span>{val.map(x => <span key={x.toString()}>{x} </span>)}</span>;
|
||||||
};
|
};
|
||||||
|
|
||||||
let renderIpAddresses = function (val) {
|
|
||||||
return <div>{renderArray(val.ip_addresses)} {(val.domain_name ? " (".concat(val.domain_name, ")") : "")} </div>;
|
let renderMachine = function (val, index, exploited=false) {
|
||||||
|
return (
|
||||||
|
<div key={index}>
|
||||||
|
{renderArray(val.ip_addresses)}
|
||||||
|
{(val.domain_name ? " (".concat(val.domain_name, ")") : " (".concat(val.label, ")"))} :
|
||||||
|
{exploited ? renderArray(val.exploits) : renderArray(val.services)}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
const columns = [
|
|
||||||
];
|
|
||||||
|
|
||||||
const pageSize = 10;
|
|
||||||
|
|
||||||
class T1210 extends React.Component {
|
class T1210 extends React.Component {
|
||||||
|
|
||||||
|
renderScannedMachines = (machines) => {
|
||||||
|
let content = [];
|
||||||
|
for (let i = 0; i < machines.length; i++ ){
|
||||||
|
if (machines[i].services.length !== 0){
|
||||||
|
content.push(renderMachine(machines[i], i))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return <div>{content}</div>;
|
||||||
|
};
|
||||||
|
|
||||||
|
renderExploitedMachines = (machines) => {
|
||||||
|
let content = [];
|
||||||
|
for (let i = 0; i < machines.length; i++ ){
|
||||||
|
if (machines[i].exploits.length !== 0){
|
||||||
|
content.push(renderMachine(machines[i], i, true))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return <div>{content}</div>;
|
||||||
|
};
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
console.log(this.props);
|
||||||
return (
|
return (
|
||||||
<Collapse isOpen={true || false}>
|
<div>
|
||||||
<div>{this.props.data.message}</div>
|
<div>{this.props.data.message}</div>
|
||||||
</Collapse>
|
<div>Found services: </div>
|
||||||
|
{this.renderScannedMachines(this.props.data.scanned_machines)}
|
||||||
|
<div>Successful exploiters:</div>
|
||||||
|
{this.renderExploitedMachines(this.props.data.exploited_machines)}
|
||||||
|
<div className="attack-report footer-text">
|
||||||
|
To get more info about scanned and exploited machines view <Link to="/report">standard report.</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ class AttackReportPageComponent extends AuthComponent {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
report: {},
|
report: false,
|
||||||
allMonkeysAreDead: false,
|
allMonkeysAreDead: false,
|
||||||
runStarted: true,
|
runStarted: true,
|
||||||
index: 1
|
index: 1
|
||||||
|
@ -105,27 +105,8 @@ class AttackReportPageComponent extends AuthComponent {
|
||||||
Object.keys(this.state.report).forEach((tech_id) => {
|
Object.keys(this.state.report).forEach((tech_id) => {
|
||||||
content = this.getTechniqueCollapse(tech_id)
|
content = this.getTechniqueCollapse(tech_id)
|
||||||
});
|
});
|
||||||
return <section className="app">{content}</section>
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
let content;
|
|
||||||
if (Object.keys(this.state.report).length === 0) {
|
|
||||||
if (this.state.runStarted) {
|
|
||||||
content = (<h1>Generating Report...</h1>);
|
|
||||||
} else {
|
|
||||||
content =
|
|
||||||
<p className="alert alert-warning">
|
|
||||||
<i className="glyphicon glyphicon-warning-sign" style={{'marginRight': '5px'}}/>
|
|
||||||
You have to run a monkey before generating a report!
|
|
||||||
</p>;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
content = this.generateReportContent();
|
|
||||||
}
|
|
||||||
return (
|
return (
|
||||||
<Col xs={12} lg={8}>
|
<div>
|
||||||
<h1 className="page-title no-print">5. ATT&CK Report</h1>
|
|
||||||
<div id="header" className="row justify-content-between attack-legend">
|
<div id="header" className="row justify-content-between attack-legend">
|
||||||
<Col xs={4}>
|
<Col xs={4}>
|
||||||
<i className="fa fa-circle icon-default"></i>
|
<i className="fa fa-circle icon-default"></i>
|
||||||
|
@ -140,6 +121,32 @@ class AttackReportPageComponent extends AuthComponent {
|
||||||
<span> - Used</span>
|
<span> - Used</span>
|
||||||
</Col>
|
</Col>
|
||||||
</div>
|
</div>
|
||||||
|
<section className="app">{content}</section>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
let content;
|
||||||
|
console.log(this.state.report);
|
||||||
|
if (this.state.report === false){
|
||||||
|
content = (<h1>Generating Report...</h1>);
|
||||||
|
} else if (Object.keys(this.state.report).length === 0) {
|
||||||
|
if (this.state.runStarted) {
|
||||||
|
content = (<h1>No techniques were scanned</h1>);
|
||||||
|
} else {
|
||||||
|
content =
|
||||||
|
<p className="alert alert-warning">
|
||||||
|
<i className="glyphicon glyphicon-warning-sign" style={{'marginRight': '5px'}}/>
|
||||||
|
You have to run a monkey before generating a report!
|
||||||
|
</p>;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
content = this.generateReportContent();
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<Col xs={12} lg={8}>
|
||||||
|
<h1 className="page-title no-print">5. ATT&CK Report</h1>
|
||||||
<div style={{'fontSize': '1.2em'}}>
|
<div style={{'fontSize': '1.2em'}}>
|
||||||
{content}
|
{content}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -541,3 +541,9 @@ body {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.attack-report.footer-text{
|
||||||
|
text-align: right;
|
||||||
|
font-size: 0.8em;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue