diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..92a84cb37 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "monkey/monkey_island/cc/services/attack/attack_data"] + path = monkey/monkey_island/cc/services/attack/attack_data + url = https://github.com/mitre/cti diff --git a/deployment_scripts/deploy_linux.sh b/deployment_scripts/deploy_linux.sh index 65fdd48e6..d13478018 100755 --- a/deployment_scripts/deploy_linux.sh +++ b/deployment_scripts/deploy_linux.sh @@ -85,7 +85,7 @@ fi log_message "Cloning files from git" branch=${2:-"develop"} if [[ ! -d "$monkey_home/monkey" ]]; then # If not already cloned - git clone --single-branch -b "$branch" "${MONKEY_GIT_URL}" "${monkey_home}" 2>&1 || handle_error + git clone --single-branch --recurse-submodules -b "$branch" "${MONKEY_GIT_URL}" "${monkey_home}" 2>&1 || handle_error chmod 774 -R "${monkey_home}" fi diff --git a/deployment_scripts/deploy_windows.ps1 b/deployment_scripts/deploy_windows.ps1 index 003fdd061..6872f5c3a 100644 --- a/deployment_scripts/deploy_windows.ps1 +++ b/deployment_scripts/deploy_windows.ps1 @@ -48,7 +48,7 @@ function Deploy-Windows([String] $monkey_home = (Get-Item -Path ".\").FullName, } # Download the monkey - $command = "git clone --single-branch -b $branch $MONKEY_GIT_URL $monkey_home 2>&1" + $command = "git clone --single-branch --recurse-submodules -b $branch $MONKEY_GIT_URL $monkey_home 2>&1" Write-Output $command $output = cmd.exe /c $command $binDir = (Join-Path -Path $monkey_home -ChildPath $MONKEY_ISLAND_DIR | Join-Path -ChildPath "\bin") diff --git a/monkey/monkey_island.py b/monkey/monkey_island.py index 8f31c83f8..b3b74e6b3 100644 --- a/monkey/monkey_island.py +++ b/monkey/monkey_island.py @@ -1,4 +1,16 @@ from monkey_island.cc.main import main + +def parse_cli_args(): + import argparse + parser = argparse.ArgumentParser(description="Infection Monkey Island CnC Server. See https://infectionmonkey.com") + parser.add_argument("-s", "--setup-only", action="store_true", + help="Pass this flag to cause the Island to setup and exit without actually starting. This is useful " + "for preparing Island to boot faster later-on, so for compiling/packaging Islands.") + args = parser.parse_args() + return args.setup_only + + if "__main__" == __name__: - main() + is_setup_only = parse_cli_args() + main(is_setup_only) diff --git a/monkey/monkey_island/cc/main.py b/monkey/monkey_island/cc/main.py index f02aebafa..09f079c19 100644 --- a/monkey/monkey_island/cc/main.py +++ b/monkey/monkey_island/cc/main.py @@ -28,19 +28,20 @@ from monkey_island.cc.database import is_db_server_up, get_db_version from monkey_island.cc.resources.monkey_download import MonkeyDownload from common.version import get_version from monkey_island.cc.bootloader_server import BootloaderHttpServer +from monkey_island.cc.setup import setup -def main(): +def main(should_setup_only): logger.info("Starting bootloader server") mongo_url = os.environ.get('MONGO_URL', env.get_mongo_url()) bootloader_server_thread = Thread(target=BootloaderHttpServer(mongo_url).serve_forever, daemon=True) bootloader_server_thread.start() - start_island_server() + start_island_server(should_setup_only) bootloader_server_thread.join() -def start_island_server(): +def start_island_server(should_setup_only): from tornado.wsgi import WSGIContainer from tornado.httpserver import HTTPServer from tornado.ioloop import IOLoop @@ -55,6 +56,12 @@ def start_island_server(): crt_path = os.path.join(MONKEY_ISLAND_ABS_PATH, 'cc', 'server.crt') key_path = os.path.join(MONKEY_ISLAND_ABS_PATH, 'cc', 'server.key') + setup() + + if should_setup_only: + logger.warning("Setup only flag passed. Exiting.") + return + if env.is_debug(): app.run(host='0.0.0.0', debug=True, ssl_context=(crt_path, key_path)) else: diff --git a/monkey/monkey_island/cc/models/attack/__init__.py b/monkey/monkey_island/cc/models/attack/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/monkey/monkey_island/cc/models/attack/attack_mitigations.py b/monkey/monkey_island/cc/models/attack/attack_mitigations.py new file mode 100644 index 000000000..a51778c48 --- /dev/null +++ b/monkey/monkey_island/cc/models/attack/attack_mitigations.py @@ -0,0 +1,45 @@ +from typing import Dict + +from mongoengine import Document, StringField, DoesNotExist, EmbeddedDocumentField, ListField +from monkey_island.cc.models.attack.mitigation import Mitigation +from stix2 import AttackPattern, CourseOfAction + +from monkey_island.cc.services.attack.test_mitre_api_interface import MitreApiInterface + + +class AttackMitigations(Document): + + COLLECTION_NAME = "attack_mitigations" + + technique_id = StringField(required=True, primary_key=True) + mitigations = ListField(EmbeddedDocumentField('Mitigation')) + + @staticmethod + def get_mitigation_by_technique_id(technique_id: str) -> Document: + try: + return AttackMitigations.objects.get(technique_id=technique_id) + except DoesNotExist: + raise Exception("Attack technique with id {} does not exist!".format(technique_id)) + + def add_mitigation(self, mitigation: CourseOfAction): + mitigation_external_ref_id = MitreApiInterface.get_stix2_external_reference_id(mitigation) + if mitigation_external_ref_id.startswith('M'): + self.mitigations.append(Mitigation.get_from_stix2_data(mitigation)) + + def add_no_mitigations_info(self, mitigation: CourseOfAction): + mitigation_external_ref_id = MitreApiInterface.get_stix2_external_reference_id(mitigation) + if mitigation_external_ref_id.startswith('T') and len(self.mitigations) == 0: + mitigation_mongo_object = Mitigation.get_from_stix2_data(mitigation) + mitigation_mongo_object['description'] = mitigation_mongo_object['description'].splitlines()[0] + mitigation_mongo_object['url'] = '' + self.mitigations.append(mitigation_mongo_object) + + @staticmethod + def mitigations_from_attack_pattern(attack_pattern: AttackPattern): + return AttackMitigations(technique_id=MitreApiInterface.get_stix2_external_reference_id(attack_pattern), + mitigations=[]) + + @staticmethod + def dict_from_stix2_attack_patterns(stix2_dict: Dict[str, AttackPattern]): + return {key: AttackMitigations.mitigations_from_attack_pattern(attack_pattern) + for key, attack_pattern in stix2_dict.items()} diff --git a/monkey/monkey_island/cc/models/attack/mitigation.py b/monkey/monkey_island/cc/models/attack/mitigation.py new file mode 100644 index 000000000..670462257 --- /dev/null +++ b/monkey/monkey_island/cc/models/attack/mitigation.py @@ -0,0 +1,19 @@ +from mongoengine import StringField, EmbeddedDocument +from stix2 import CourseOfAction + +from monkey_island.cc.services.attack.test_mitre_api_interface import MitreApiInterface + + +class Mitigation(EmbeddedDocument): + + name = StringField(required=True) + description = StringField(required=True) + url = StringField() + + @staticmethod + def get_from_stix2_data(mitigation: CourseOfAction): + name = mitigation['name'] + description = mitigation['description'] + url = MitreApiInterface.get_stix2_external_reference_url(mitigation) + return Mitigation(name=name, description=description, url=url) + diff --git a/monkey/monkey_island/cc/services/attack/attack_data b/monkey/monkey_island/cc/services/attack/attack_data new file mode 160000 index 000000000..c139e37bd --- /dev/null +++ b/monkey/monkey_island/cc/services/attack/attack_data @@ -0,0 +1 @@ +Subproject commit c139e37bdc51acbc7d0488a5be48553caffdbbd7 diff --git a/monkey/monkey_island/cc/services/attack/attack_report.py b/monkey/monkey_island/cc/services/attack/attack_report.py index 7184ce202..db80c76c6 100644 --- a/monkey/monkey_island/cc/services/attack/attack_report.py +++ b/monkey/monkey_island/cc/services/attack/attack_report.py @@ -57,7 +57,6 @@ class AttackReportService: 'meta': {'latest_monkey_modifytime': Monkey.get_latest_modifytime()}, 'name': REPORT_NAME } - for tech_id, tech_info in list(AttackConfig.get_techniques_for_report().items()): try: technique_report_data = TECHNIQUES[tech_id].get_report_data() diff --git a/monkey/monkey_island/cc/services/attack/mitre_api_interface.py b/monkey/monkey_island/cc/services/attack/mitre_api_interface.py new file mode 100644 index 000000000..af169ec5f --- /dev/null +++ b/monkey/monkey_island/cc/services/attack/mitre_api_interface.py @@ -0,0 +1,47 @@ +from typing import List, Dict + +from stix2 import FileSystemSource, Filter, CourseOfAction, AttackPattern +from stix2.core import STIXDomainObject + + +class MitreApiInterface: + + ATTACK_DATA_PATH = 'monkey_island/cc/services/attack/attack_data/enterprise-attack' + + @staticmethod + def get_all_mitigations() -> Dict[str, CourseOfAction]: + file_system = FileSystemSource(MitreApiInterface.ATTACK_DATA_PATH) + mitigation_filter = [Filter('type', '=', 'course-of-action')] + all_mitigations = file_system.query(mitigation_filter) + all_mitigations = {mitigation['id']: mitigation for mitigation in all_mitigations} + return all_mitigations + + @staticmethod + def get_all_attack_techniques() -> Dict[str, AttackPattern]: + file_system = FileSystemSource(MitreApiInterface.ATTACK_DATA_PATH) + technique_filter = [Filter('type', '=', 'attack-pattern')] + all_techniques = file_system.query(technique_filter) + all_techniques = {technique['id']: technique for technique in all_techniques} + return all_techniques + + @staticmethod + def get_technique_and_mitigation_relationships() -> List[CourseOfAction]: + file_system = FileSystemSource(MitreApiInterface.ATTACK_DATA_PATH) + technique_filter = [Filter('type', '=', 'relationship'), + Filter('relationship_type', '=', 'mitigates')] + all_techniques = file_system.query(technique_filter) + return all_techniques + + @staticmethod + def get_stix2_external_reference_id(stix2_data: STIXDomainObject) -> str: + for reference in stix2_data['external_references']: + if reference['source_name'] == "mitre-attack" and 'external_id' in reference: + return reference['external_id'] + return '' + + @staticmethod + def get_stix2_external_reference_url(stix2_data: STIXDomainObject) -> str: + for reference in stix2_data['external_references']: + if 'url' in reference: + return reference['url'] + return '' diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/T1003.py b/monkey/monkey_island/cc/services/attack/technique_reports/T1003.py index f3bd9b180..cbd3bf8bf 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1003.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1003.py @@ -24,6 +24,7 @@ class T1003(AttackTechnique): else: status = ScanStatus.UNSCANNED.value data.update(T1003.get_message_and_status(status)) + data.update(T1003.get_mitigation_by_status(status)) data['stolen_creds'] = ReportService.get_stolen_creds() data['stolen_creds'].extend(ReportService.get_ssh_keys()) return data diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/T1059.py b/monkey/monkey_island/cc/services/attack/technique_reports/T1059.py index a2eb3ffd0..c0e4dc3f6 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1059.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1059.py @@ -30,4 +30,5 @@ class T1059(AttackTechnique): else: status = ScanStatus.UNSCANNED.value data.update(T1059.get_message_and_status(status)) + data.update(T1059.get_mitigation_by_status(status)) return data diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/T1075.py b/monkey/monkey_island/cc/services/attack/technique_reports/T1075.py index 655da767d..370db3ca2 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1075.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1075.py @@ -40,4 +40,5 @@ class T1075(AttackTechnique): else: status = ScanStatus.UNSCANNED.value data.update(T1075.get_message_and_status(status)) + data.update(T1075.get_mitigation_by_status(status)) return data diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/T1082.py b/monkey/monkey_island/cc/services/attack/technique_reports/T1082.py index 1aaef57f4..cdbdb42ec 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1082.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1082.py @@ -44,5 +44,6 @@ class T1082(AttackTechnique): status = ScanStatus.USED.value else: status = ScanStatus.UNSCANNED.value + data.update(T1082.get_mitigation_by_status(status)) data.update(T1082.get_message_and_status(status)) return data diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/T1086.py b/monkey/monkey_island/cc/services/attack/technique_reports/T1086.py index fe4b6ccec..897ccdaaf 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1086.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1086.py @@ -31,5 +31,7 @@ class T1086(AttackTechnique): status = ScanStatus.USED.value else: status = ScanStatus.UNSCANNED.value + + data.update(T1086.get_mitigation_by_status(status)) data.update(T1086.get_message_and_status(status)) return data diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/T1210.py b/monkey/monkey_island/cc/services/attack/technique_reports/T1210.py index 5b9a23c62..babe5c788 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1210.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1210.py @@ -23,6 +23,7 @@ class T1210(AttackTechnique): else: status = ScanStatus.UNSCANNED.value data.update(T1210.get_message_and_status(status)) + data.update(T1210.get_mitigation_by_status(status)) data.update({'scanned_services': scanned_services, 'exploited_services': exploited_services}) return data diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/__init__.py b/monkey/monkey_island/cc/services/attack/technique_reports/__init__.py index b9a2fd795..80dbe7518 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/__init__.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/__init__.py @@ -5,6 +5,7 @@ from monkey_island.cc.database import mongo from common.utils.attack_utils import ScanStatus from monkey_island.cc.services.attack.attack_config import AttackConfig from common.utils.code_utils import abstractstatic +from cc.models.attack.attack_mitigations import AttackMitigations logger = logging.getLogger(__name__) @@ -40,7 +41,7 @@ class AttackTechnique(object, metaclass=abc.ABCMeta): @abc.abstractmethod def tech_id(self): """ - :return: Message that will be displayed in case of attack technique not being scanned. + :return: Id of attack technique. E.g. T1003 """ pass @@ -111,10 +112,21 @@ class AttackTechnique(object, metaclass=abc.ABCMeta): data.update({'status': status, 'title': title, 'message': cls.get_message_by_status(status)}) + data.update(cls.get_mitigation_by_status(status)) return data @classmethod def get_base_data_by_status(cls, status): data = cls.get_message_and_status(status) data.update({'title': cls.technique_title()}) + data.update(cls.get_mitigation_by_status(status)) return data + + @classmethod + def get_mitigation_by_status(cls, status: ScanStatus) -> dict: + if status == ScanStatus.USED.value: + mitigation_document = AttackMitigations.get_mitigation_by_technique_id(str(cls.tech_id)) + return {'mitigations': mitigation_document.to_mongo().to_dict()['mitigations']} + else: + return {} + diff --git a/monkey/monkey_island/cc/services/attack/test_mitre_api_interface.py b/monkey/monkey_island/cc/services/attack/test_mitre_api_interface.py new file mode 100644 index 000000000..4866a6729 --- /dev/null +++ b/monkey/monkey_island/cc/services/attack/test_mitre_api_interface.py @@ -0,0 +1,15 @@ +from unittest import TestCase + +from monkey_island.cc.services.attack.mitre_api_interface import MitreApiInterface + + +class TestMitreApiInterface(TestCase): + + def test_get_all_mitigations(self): + mitigations = MitreApiInterface.get_all_mitigations() + self.assertIsNotNone((len(mitigations.items()) >= 282)) + mitigation = next(iter(mitigations.values())) + self.assertEqual(mitigation['type'], "course-of-action") + self.assertIsNotNone(mitigation['name']) + self.assertIsNotNone(mitigation['description']) + self.assertIsNotNone(mitigation['external_references']) diff --git a/monkey/monkey_island/cc/services/database.py b/monkey/monkey_island/cc/services/database.py index 7062d71c3..85812dd6e 100644 --- a/monkey/monkey_island/cc/services/database.py +++ b/monkey/monkey_island/cc/services/database.py @@ -3,6 +3,7 @@ import logging from monkey_island.cc.services.config import ConfigService from monkey_island.cc.services.attack.attack_config import AttackConfig from monkey_island.cc.services.post_breach_files import remove_PBA_files +from monkey_island.cc.models.attack.attack_mitigations import AttackMitigations from flask import jsonify from monkey_island.cc.database import mongo @@ -15,14 +16,21 @@ class Database(object): @staticmethod def reset_db(): + logger.info('Resetting database') remove_PBA_files() # We can't drop system collections. - [mongo.db[x].drop() for x in mongo.db.collection_names() if not x.startswith('system.')] + [Database.drop_collection(x) for x in mongo.db.collection_names() if not x.startswith('system.') + and not x == AttackMitigations.COLLECTION_NAME] ConfigService.init_config() AttackConfig.reset_config() logger.info('DB was reset') return jsonify(status='OK') + @staticmethod + def drop_collection(collection_name: str): + mongo.db[collection_name].drop() + logger.info("Dropped collection {}".format(collection_name)) + @staticmethod def init_db(): if not mongo.db.collection_names(): diff --git a/monkey/monkey_island/cc/setup.py b/monkey/monkey_island/cc/setup.py new file mode 100644 index 000000000..007fca6ef --- /dev/null +++ b/monkey/monkey_island/cc/setup.py @@ -0,0 +1,42 @@ +import logging + +from monkey_island.cc.services.attack.mitre_api_interface import MitreApiInterface +from monkey_island.cc.models.attack.attack_mitigations import AttackMitigations +from monkey_island.cc.database import mongo +from pymongo import errors + + +logger = logging.getLogger(__name__) + + +def setup(): + logger.info("Setting up the Monkey Island, this might take a while...") + try_store_mitigations_on_mongo() + + +def try_store_mitigations_on_mongo(): + mitigation_collection_name = AttackMitigations.COLLECTION_NAME + try: + mongo.db.validate_collection(mitigation_collection_name) + if mongo.db.attack_mitigations.count() == 0: + raise errors.OperationFailure("Mitigation collection empty. Try dropping the collection and running again") + except errors.OperationFailure: + try: + mongo.db.create_collection(mitigation_collection_name) + except errors.CollectionInvalid: + pass + finally: + store_mitigations_on_mongo() + + +def store_mitigations_on_mongo(): + stix2_mitigations = MitreApiInterface.get_all_mitigations() + mongo_mitigations = AttackMitigations.dict_from_stix2_attack_patterns(MitreApiInterface.get_all_attack_techniques()) + mitigation_technique_relationships = MitreApiInterface.get_technique_and_mitigation_relationships() + for relationship in mitigation_technique_relationships: + mongo_mitigations[relationship['target_ref']].add_mitigation(stix2_mitigations[relationship['source_ref']]) + for relationship in mitigation_technique_relationships: + mongo_mitigations[relationship['target_ref']].\ + add_no_mitigations_info(stix2_mitigations[relationship['source_ref']]) + for key, mongo_object in mongo_mitigations.items(): + mongo_object.save() diff --git a/monkey/monkey_island/cc/ui/package-lock.json b/monkey/monkey_island/cc/ui/package-lock.json index 40b0ce11b..7d3358a3d 100644 --- a/monkey/monkey_island/cc/ui/package-lock.json +++ b/monkey/monkey_island/cc/ui/package-lock.json @@ -10567,6 +10567,11 @@ "object-visit": "1.0.1" } }, + "marked": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/marked/-/marked-0.8.2.tgz", + "integrity": "sha512-EGwzEeCcLniFX51DhTpmTom+dSA/MG/OBUDjnWtHbEnjAH180VzUeAw+oE4+Zv+CoYBWyRlYOTR0N8SO9R1PVw==" + }, "md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", diff --git a/monkey/monkey_island/cc/ui/package.json b/monkey/monkey_island/cc/ui/package.json index a6cdc6d81..45740c0fc 100644 --- a/monkey/monkey_island/cc/ui/package.json +++ b/monkey/monkey_island/cc/ui/package.json @@ -81,6 +81,7 @@ "filepond": "^4.7.3", "json-loader": "^0.5.7", "jwt-decode": "^2.2.0", + "marked": "^0.8.2", "moment": "^2.24.0", "node-sass": "^4.13.0", "normalize.css": "^8.0.0", diff --git a/monkey/monkey_island/cc/ui/src/components/attack/techniques/MitigationsComponent.js b/monkey/monkey_island/cc/ui/src/components/attack/techniques/MitigationsComponent.js new file mode 100644 index 000000000..e026b3e7b --- /dev/null +++ b/monkey/monkey_island/cc/ui/src/components/attack/techniques/MitigationsComponent.js @@ -0,0 +1,76 @@ +import React from 'react'; +import ReactTable from 'react-table'; +import marked from 'marked'; +import '../../../styles/report/AttackReport.scss'; + + +class MitigationsComponent extends React.Component { + + constructor(props) { + super(props); + if (typeof this.props.mitigations !== 'undefined' && this.props.mitigations.length > 0){ + this.state = {mitigations: this.props.mitigations}; + } else { + this.state = {mitigations: null} + } + } + + static createRows(descriptions, references) { + let rows = []; + for(let i = 0; i < descriptions.length; i++){ + rows[i] = {'description': descriptions[i], 'reference': references[i]}; + } + return rows; + } + + static parseDescription(description) { + const citationRegex = /\(Citation:.*\)/gi; + const emptyLineRegex = /^\s*[\r\n]/gm; + description = description.replace(citationRegex, ''); + description = description.replace(emptyLineRegex, ''); + description = marked(description); + return description; + } + + static getMitigations() { + return ([{ + Header: 'Mitigations', + style: {'text-align': 'left'}, + columns: [ + { id: 'name', + accessor: x => this.getMitigationName(x.name, x.url), + width: 200}, + { id: 'description', + accessor: x => (
), + style: {'whiteSpace': 'unset'}} + ] + }]) + } + + static getMitigationName(name, url) { + if(url){ + return ({name}) + } else { + return (

{name}

) + } + } + + + render() { + return ( +
+
+ {this.state.mitigations ? + : ''} +
+ ); + } +} + +export default MitigationsComponent; diff --git a/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1003.js b/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1003.js index c9c127574..f58f870c1 100644 --- a/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1003.js +++ b/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1003.js @@ -2,6 +2,7 @@ import React from 'react'; import '../../report-components/security/StolenPasswords' import StolenPasswordsComponent from '../../report-components/security/StolenPasswords'; import {ScanStatus} from './Helpers' +import MitigationsComponent from './MitigationsComponent'; class T1003 extends React.Component { @@ -19,6 +20,7 @@ class T1003 extends React.Component { : ''} +
); } diff --git a/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1005.js b/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1005.js index fa702f2b2..bb9d8f8e2 100644 --- a/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1005.js +++ b/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1005.js @@ -1,6 +1,7 @@ import React from 'react'; import ReactTable from 'react-table'; import {renderMachineFromSystemData, ScanStatus} from './Helpers'; +import MitigationsComponent from './MitigationsComponent'; class T1005 extends React.Component { @@ -36,6 +37,7 @@ class T1005 extends React.Component { showPagination={false} defaultPageSize={this.props.data.collected_data.length} /> : ''} + ); } diff --git a/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1016.js b/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1016.js index 9c0afa21e..6c96f6312 100644 --- a/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1016.js +++ b/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1016.js @@ -1,6 +1,7 @@ import React from 'react'; import ReactTable from 'react-table'; import {renderMachineFromSystemData, renderUsageFields, ScanStatus} from './Helpers' +import MitigationsComponent from './MitigationsComponent'; class T1016 extends React.Component { @@ -36,6 +37,7 @@ class T1016 extends React.Component { showPagination={false} defaultPageSize={this.props.data.network_info.length} /> : ''} + ); } diff --git a/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1018.js b/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1018.js index fbd34616e..36ce2c8ea 100644 --- a/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1018.js +++ b/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1018.js @@ -1,6 +1,7 @@ import React from 'react'; import ReactTable from 'react-table'; import {renderMachineFromSystemData, renderMachine, ScanStatus} from './Helpers' +import MitigationsComponent from './MitigationsComponent'; class T1018 extends React.Component { @@ -50,6 +51,7 @@ class T1018 extends React.Component { showPagination={false} defaultPageSize={this.props.data.scan_info.length} /> : ''} + ); } diff --git a/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1021.js b/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1021.js index 22f9460e4..a605bbc23 100644 --- a/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1021.js +++ b/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1021.js @@ -1,6 +1,7 @@ import React from 'react'; import ReactTable from 'react-table'; import {renderMachine, ScanStatus} from './Helpers' +import MitigationsComponent from './MitigationsComponent'; class T1021 extends React.Component { @@ -16,7 +17,13 @@ class T1021 extends React.Component { Header: 'Machine', id: 'machine', accessor: x => renderMachine(x.machine), style: {'whiteSpace': 'unset'}, width: 160 }, - {Header: 'Service', id: 'service', accessor: x => x.info.display_name, style: {'whiteSpace': 'unset'}, width: 100}, + { + Header: 'Service', + id: 'service', + accessor: x => x.info.display_name, + style: {'whiteSpace': 'unset'}, + width: 100 + }, { Header: 'Valid account used', id: 'credentials', @@ -43,6 +50,7 @@ class T1021 extends React.Component { showPagination={false} defaultPageSize={this.props.data.services.length} /> : ''} + ); } diff --git a/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1035.js b/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1035.js index d624fbfef..94d917c6c 100644 --- a/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1035.js +++ b/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1035.js @@ -1,6 +1,7 @@ import React from 'react'; import ReactTable from 'react-table'; import {getUsageColumns} from './Helpers' +import MitigationsComponent from './MitigationsComponent'; class T1035 extends React.Component { @@ -21,6 +22,7 @@ class T1035 extends React.Component { showPagination={false} defaultPageSize={this.props.data.services.length} /> : ''} + ); } diff --git a/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1041.js b/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1041.js index 7e6c03c54..ec121e9b1 100644 --- a/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1041.js +++ b/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1041.js @@ -1,6 +1,7 @@ import React from 'react'; import ReactTable from 'react-table'; import {ScanStatus} from './Helpers'; +import MitigationsComponent from './MitigationsComponent'; class T1041 extends React.Component { @@ -30,6 +31,7 @@ class T1041 extends React.Component { showPagination={false} defaultPageSize={this.props.data.command_control_channel.length} /> : ''} + ); } diff --git a/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1059.js b/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1059.js index b48958daa..eb5b77144 100644 --- a/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1059.js +++ b/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1059.js @@ -1,6 +1,7 @@ import React from 'react'; import ReactTable from 'react-table'; import {renderMachine, ScanStatus} from './Helpers' +import MitigationsComponent from './MitigationsComponent'; class T1059 extends React.Component { @@ -38,6 +39,7 @@ class T1059 extends React.Component { showPagination={false} defaultPageSize={this.props.data.cmds.length} /> : ''} + ); } diff --git a/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1064.js b/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1064.js index 984e27f10..68b8af0f1 100644 --- a/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1064.js +++ b/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1064.js @@ -1,6 +1,7 @@ import React from 'react'; import ReactTable from 'react-table'; import {getUsageColumns} from './Helpers' +import MitigationsComponent from './MitigationsComponent'; class T1064 extends React.Component { @@ -21,6 +22,7 @@ class T1064 extends React.Component { showPagination={false} defaultPageSize={this.props.data.scripts.length} /> : ''} + ); } diff --git a/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1065.js b/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1065.js index 3587f85e1..abc2b99e4 100644 --- a/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1065.js +++ b/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1065.js @@ -1,4 +1,5 @@ import React from 'react'; +import MitigationsComponent from './MitigationsComponent'; class T1065 extends React.Component { @@ -7,6 +8,7 @@ class T1065 extends React.Component { return (
{this.props.data.message}
+
); } diff --git a/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1075.js b/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1075.js index 5e0713cd3..330f7d129 100644 --- a/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1075.js +++ b/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1075.js @@ -1,6 +1,7 @@ import React from 'react'; import ReactTable from 'react-table'; import {renderMachine, ScanStatus} from './Helpers' +import MitigationsComponent from './MitigationsComponent'; class T1075 extends React.Component { @@ -41,6 +42,7 @@ class T1075 extends React.Component { showPagination={false} defaultPageSize={this.props.data.successful_logins.length} /> : ''} + ); } diff --git a/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1082.js b/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1082.js index 27dec053e..2e872ac99 100644 --- a/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1082.js +++ b/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1082.js @@ -1,6 +1,7 @@ import React from 'react'; import ReactTable from 'react-table'; import {renderMachineFromSystemData, renderUsageFields, ScanStatus} from './Helpers' +import MitigationsComponent from './MitigationsComponent'; class T1082 extends React.Component { @@ -12,14 +13,18 @@ class T1082 extends React.Component { static getSystemInfoColumns() { return ([{ columns: [ - { Header: 'Machine', + { + Header: 'Machine', id: 'machine', accessor: x => renderMachineFromSystemData(x.machine), - style: {'whiteSpace': 'unset'}}, - { Header: 'Gathered info', + style: {'whiteSpace': 'unset'} + }, + { + Header: 'Gathered info', id: 'info', accessor: x => renderUsageFields(x.collections), - style: {'whiteSpace': 'unset'}} + style: {'whiteSpace': 'unset'} + } ] }]) } @@ -36,6 +41,7 @@ class T1082 extends React.Component { showPagination={false} defaultPageSize={this.props.data.system_info.length} /> : ''} + ); } diff --git a/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1086.js b/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1086.js index 3d69d1205..2978c9ba7 100644 --- a/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1086.js +++ b/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1086.js @@ -1,6 +1,7 @@ import React from 'react'; import ReactTable from 'react-table'; import {renderMachine, ScanStatus} from './Helpers' +import MitigationsComponent from './MitigationsComponent'; class T1086 extends React.Component { @@ -21,7 +22,12 @@ class T1086 extends React.Component { width: 160 }, {Header: 'Approx. Time', id: 'time', accessor: x => x.data[0].info.finished, style: {'whiteSpace': 'unset'}}, - {Header: 'Command', id: 'command', accessor: x => x.data[0].info.executed_cmds[0].cmd, style: {'whiteSpace': 'unset'}} + { + Header: 'Command', + id: 'command', + accessor: x => x.data[0].info.executed_cmds[0].cmd, + style: {'whiteSpace': 'unset'} + } ] }]) } @@ -38,6 +44,7 @@ class T1086 extends React.Component { showPagination={false} defaultPageSize={this.props.data.cmds.length} /> : ''} + ); } diff --git a/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1090.js b/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1090.js index 82077882e..69ccb4adc 100644 --- a/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1090.js +++ b/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1090.js @@ -1,6 +1,7 @@ import React from 'react'; import ReactTable from 'react-table'; import {renderMachineFromSystemData, ScanStatus} from './Helpers' +import MitigationsComponent from './MitigationsComponent'; class T1090 extends React.Component { @@ -33,6 +34,7 @@ class T1090 extends React.Component { showPagination={false} defaultPageSize={this.props.data.proxies.length} /> : ''} + ); } diff --git a/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1105.js b/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1105.js index 836934300..ab4b9481d 100644 --- a/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1105.js +++ b/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1105.js @@ -1,6 +1,7 @@ import React from 'react'; import ReactTable from 'react-table'; import {ScanStatus} from './Helpers' +import MitigationsComponent from './MitigationsComponent'; class T1105 extends React.Component { @@ -32,6 +33,7 @@ class T1105 extends React.Component { showPagination={false} defaultPageSize={this.props.data.files.length} /> : ''} + ); } diff --git a/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1106.js b/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1106.js index b1d9f926c..bdf71d0cc 100644 --- a/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1106.js +++ b/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1106.js @@ -1,6 +1,7 @@ import React from 'react'; import ReactTable from 'react-table'; import {getUsageColumns} from './Helpers' +import MitigationsComponent from './MitigationsComponent'; class T1106 extends React.Component { @@ -21,6 +22,7 @@ class T1106 extends React.Component { showPagination={false} defaultPageSize={this.props.data.api_uses.length} /> : ''} + ); } diff --git a/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1107.js b/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1107.js index 7d416826c..bad80a538 100644 --- a/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1107.js +++ b/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1107.js @@ -1,6 +1,7 @@ import React from 'react'; import ReactTable from 'react-table'; import {renderMachineFromSystemData, ScanStatus} from './Helpers' +import MitigationsComponent from './MitigationsComponent'; class T1107 extends React.Component { @@ -46,6 +47,7 @@ class T1107 extends React.Component { showPagination={false} defaultPageSize={this.props.data.deleted_files.length} /> : ''} + ); } diff --git a/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1110.js b/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1110.js index 8cd5719f3..17b53cda1 100644 --- a/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1110.js +++ b/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1110.js @@ -1,6 +1,7 @@ import React from 'react'; import ReactTable from 'react-table'; import {renderMachine, ScanStatus} from './Helpers' +import MitigationsComponent from './MitigationsComponent' class T1110 extends React.Component { @@ -46,6 +47,7 @@ class T1110 extends React.Component { showPagination={false} defaultPageSize={this.props.data.services.length} /> : ''} + ); } diff --git a/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1129.js b/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1129.js index 4c9cb3c5d..d41151ee2 100644 --- a/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1129.js +++ b/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1129.js @@ -1,6 +1,7 @@ import React from 'react'; import ReactTable from 'react-table'; import {getUsageColumns} from './Helpers'; +import MitigationsComponent from './MitigationsComponent'; class T1129 extends React.Component { @@ -20,6 +21,7 @@ class T1129 extends React.Component { showPagination={false} defaultPageSize={this.props.data.dlls.length} /> : ''} + ); } diff --git a/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1145.js b/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1145.js index 1b14b3415..6855a4b02 100644 --- a/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1145.js +++ b/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1145.js @@ -1,6 +1,7 @@ import React from 'react'; import ReactTable from 'react-table'; import {renderMachineFromSystemData, ScanStatus} from './Helpers' +import MitigationsComponent from './MitigationsComponent'; class T1145 extends React.Component { @@ -49,6 +50,7 @@ class T1145 extends React.Component { showPagination={false} defaultPageSize={this.props.data.ssh_info.length} /> : ''} + ); } diff --git a/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1188.js b/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1188.js index 5c2e5b41f..920f3f22d 100644 --- a/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1188.js +++ b/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1188.js @@ -1,6 +1,7 @@ import React from 'react'; import ReactTable from 'react-table'; import {renderMachineFromSystemData, ScanStatus} from './Helpers' +import MitigationsComponent from './MitigationsComponent'; class T1188 extends React.Component { @@ -47,6 +48,7 @@ class T1188 extends React.Component { showPagination={false} defaultPageSize={this.props.data.hops.length} /> : ''} + ); } diff --git a/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1197.js b/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1197.js index c558b733f..1a92f5e7c 100644 --- a/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1197.js +++ b/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1197.js @@ -1,6 +1,7 @@ import React from 'react'; import ReactTable from 'react-table'; import {renderMachine} from './Helpers' +import MitigationsComponent from './MitigationsComponent'; class T1210 extends React.Component { @@ -49,6 +50,7 @@ class T1210 extends React.Component {
{this.renderExploitedMachines()} + ); } diff --git a/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1210.js b/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1210.js index 9dcf8f544..3bb6ad8c9 100644 --- a/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1210.js +++ b/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1210.js @@ -1,6 +1,7 @@ import React from 'react'; import ReactTable from 'react-table'; import {renderMachine} from './Helpers' +import MitigationsComponent from './MitigationsComponent'; class T1210 extends React.Component { @@ -99,6 +100,7 @@ class T1210 extends React.Component { this.renderScannedServices(scanned_services) : ''} {this.props.data.exploited_services.length > 0 ? this.renderExploitedServices(this.props.data.exploited_services) : ''} + ); } diff --git a/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1222.js b/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1222.js index ce73936b3..f7309665e 100644 --- a/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1222.js +++ b/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1222.js @@ -1,6 +1,7 @@ import React from 'react'; import ReactTable from 'react-table'; import {renderMachine, ScanStatus} from './Helpers' +import MitigationsComponent from './MitigationsComponent'; class T1222 extends React.Component { @@ -31,6 +32,7 @@ class T1222 extends React.Component { showPagination={false} defaultPageSize={this.props.data.commands.length} /> : ''} + ); } diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/AttackReport.js b/monkey/monkey_island/cc/ui/src/components/report-components/AttackReport.js index 39886fee6..5f8e40455 100644 --- a/monkey/monkey_island/cc/ui/src/components/report-components/AttackReport.js +++ b/monkey/monkey_island/cc/ui/src/components/report-components/AttackReport.js @@ -57,7 +57,7 @@ class AttackReport extends React.Component { static getComponentClass(tech_id, techniques) { switch (techniques[tech_id].status) { case ScanStatus.SCANNED: - return 'collapse-info'; + return 'collapse-warning'; case ScanStatus.USED: return 'collapse-danger'; default: @@ -79,16 +79,16 @@ class AttackReport extends React.Component { renderLegend() { return () } diff --git a/monkey/monkey_island/cc/ui/src/styles/Collapse.scss b/monkey/monkey_island/cc/ui/src/styles/Collapse.scss index 30ebaf789..5d49b13a0 100644 --- a/monkey/monkey_island/cc/ui/src/styles/Collapse.scss +++ b/monkey/monkey_island/cc/ui/src/styles/Collapse.scss @@ -1,8 +1,9 @@ $transition: 300ms cubic-bezier(0.6, 0.3, 0.3, 0.6); -$danger-color: #d9acac; +$danger-color: #ebbcba; $info-color: #ade3eb; $default-color: #e0ddde; +$warning-color: #ffe28d; .collapse-item button { font-size: inherit; @@ -41,6 +42,10 @@ $default-color: #e0ddde; background-color: $danger-color !important; } +.collapse-warning { + background-color: $warning-color !important; +} + .collapse-info { background-color: $info-color !important; } diff --git a/monkey/monkey_island/cc/ui/src/styles/report/AttackReport.scss b/monkey/monkey_island/cc/ui/src/styles/report/AttackReport.scss index 60266de08..e1d76bb8a 100644 --- a/monkey/monkey_island/cc/ui/src/styles/report/AttackReport.scss +++ b/monkey/monkey_island/cc/ui/src/styles/report/AttackReport.scss @@ -80,3 +80,16 @@ padding-right:5px; margin-bottom: 1px; } + +.attack-mitigation .rt-thead .rt-tr .rt-th { + text-align: left !important; + padding-left: 10px; +} + +.attack-mitigation p { + padding-left: 7px; +} + +.attack-mitigation .rt-table>.-header { + display: none !important; +} diff --git a/monkey/monkey_island/cc/ui/src/styles/report/ReportAttackMatrix.scss b/monkey/monkey_island/cc/ui/src/styles/report/ReportAttackMatrix.scss index 779db71dc..f6eedf353 100644 --- a/monkey/monkey_island/cc/ui/src/styles/report/ReportAttackMatrix.scss +++ b/monkey/monkey_island/cc/ui/src/styles/report/ReportAttackMatrix.scss @@ -1,21 +1,21 @@ // colors -$light-grey: #e0ddde; -$light-blue: #ade3eb; -$light-red: #d9acac; +$not-attempted: #e0ddde; +$attempted: #ffe28d; +$used: #ebbcba; $black: #3a3a3a; .attack-matrix .status-0 { - background-color: $light-grey !important; + background-color: $not-attempted !important; color: $black; } .attack-matrix .status-1 { - background-color: $light-blue !important; + background-color: $attempted !important; color: $black; } .attack-matrix .status-2 { - background-color: $light-red !important; + background-color: $used !important; color: $black; } @@ -29,3 +29,14 @@ $black: #3a3a3a; border-bottom: 1px solid #0000000f; } +.technique-not-attempted { + color: $not-attempted; +} + +.technique-attempted { + color: $attempted; +} + +.technique-used { + color: $used; +} diff --git a/monkey/monkey_island/cc/ui/src/styles/report/ReportPage.scss b/monkey/monkey_island/cc/ui/src/styles/report/ReportPage.scss index 36a3c005c..4b1bd60c9 100644 --- a/monkey/monkey_island/cc/ui/src/styles/report/ReportPage.scss +++ b/monkey/monkey_island/cc/ui/src/styles/report/ReportPage.scss @@ -4,6 +4,7 @@ top: 0; z-index: 1000000; background-color: #ffffff; + font-size: large; } .report-nav > li > a{ diff --git a/monkey/monkey_island/requirements.txt b/monkey/monkey_island/requirements.txt index 3c59bcc47..cad53d1c8 100644 --- a/monkey/monkey_island/requirements.txt +++ b/monkey/monkey_island/requirements.txt @@ -23,3 +23,4 @@ mongomock requests dpath ring +stix2