Merge pull request #575 from guardicore/enhancement/mitre-ui-review-fixes
[WIP] Enhancing MITRE UX
This commit is contained in:
commit
f89cbdbdbc
|
@ -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
|
|
@ -85,7 +85,7 @@ fi
|
||||||
log_message "Cloning files from git"
|
log_message "Cloning files from git"
|
||||||
branch=${2:-"develop"}
|
branch=${2:-"develop"}
|
||||||
if [[ ! -d "$monkey_home/monkey" ]]; then # If not already cloned
|
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}"
|
chmod 774 -R "${monkey_home}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,7 @@ function Deploy-Windows([String] $monkey_home = (Get-Item -Path ".\").FullName,
|
||||||
}
|
}
|
||||||
|
|
||||||
# Download the monkey
|
# 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
|
Write-Output $command
|
||||||
$output = cmd.exe /c $command
|
$output = cmd.exe /c $command
|
||||||
$binDir = (Join-Path -Path $monkey_home -ChildPath $MONKEY_ISLAND_DIR | Join-Path -ChildPath "\bin")
|
$binDir = (Join-Path -Path $monkey_home -ChildPath $MONKEY_ISLAND_DIR | Join-Path -ChildPath "\bin")
|
||||||
|
|
|
@ -1,4 +1,16 @@
|
||||||
from monkey_island.cc.main import main
|
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__:
|
if "__main__" == __name__:
|
||||||
main()
|
is_setup_only = parse_cli_args()
|
||||||
|
main(is_setup_only)
|
||||||
|
|
|
@ -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 monkey_island.cc.resources.monkey_download import MonkeyDownload
|
||||||
from common.version import get_version
|
from common.version import get_version
|
||||||
from monkey_island.cc.bootloader_server import BootloaderHttpServer
|
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")
|
logger.info("Starting bootloader server")
|
||||||
mongo_url = os.environ.get('MONGO_URL', env.get_mongo_url())
|
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 = Thread(target=BootloaderHttpServer(mongo_url).serve_forever, daemon=True)
|
||||||
|
|
||||||
bootloader_server_thread.start()
|
bootloader_server_thread.start()
|
||||||
start_island_server()
|
start_island_server(should_setup_only)
|
||||||
bootloader_server_thread.join()
|
bootloader_server_thread.join()
|
||||||
|
|
||||||
|
|
||||||
def start_island_server():
|
def start_island_server(should_setup_only):
|
||||||
from tornado.wsgi import WSGIContainer
|
from tornado.wsgi import WSGIContainer
|
||||||
from tornado.httpserver import HTTPServer
|
from tornado.httpserver import HTTPServer
|
||||||
from tornado.ioloop import IOLoop
|
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')
|
crt_path = os.path.join(MONKEY_ISLAND_ABS_PATH, 'cc', 'server.crt')
|
||||||
key_path = os.path.join(MONKEY_ISLAND_ABS_PATH, 'cc', 'server.key')
|
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():
|
if env.is_debug():
|
||||||
app.run(host='0.0.0.0', debug=True, ssl_context=(crt_path, key_path))
|
app.run(host='0.0.0.0', debug=True, ssl_context=(crt_path, key_path))
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -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()}
|
|
@ -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)
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit c139e37bdc51acbc7d0488a5be48553caffdbbd7
|
|
@ -57,7 +57,6 @@ class AttackReportService:
|
||||||
'meta': {'latest_monkey_modifytime': Monkey.get_latest_modifytime()},
|
'meta': {'latest_monkey_modifytime': Monkey.get_latest_modifytime()},
|
||||||
'name': REPORT_NAME
|
'name': REPORT_NAME
|
||||||
}
|
}
|
||||||
|
|
||||||
for tech_id, tech_info in list(AttackConfig.get_techniques_for_report().items()):
|
for tech_id, tech_info in list(AttackConfig.get_techniques_for_report().items()):
|
||||||
try:
|
try:
|
||||||
technique_report_data = TECHNIQUES[tech_id].get_report_data()
|
technique_report_data = TECHNIQUES[tech_id].get_report_data()
|
||||||
|
|
|
@ -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 ''
|
|
@ -24,6 +24,7 @@ class T1003(AttackTechnique):
|
||||||
else:
|
else:
|
||||||
status = ScanStatus.UNSCANNED.value
|
status = ScanStatus.UNSCANNED.value
|
||||||
data.update(T1003.get_message_and_status(status))
|
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'] = ReportService.get_stolen_creds()
|
||||||
data['stolen_creds'].extend(ReportService.get_ssh_keys())
|
data['stolen_creds'].extend(ReportService.get_ssh_keys())
|
||||||
return data
|
return data
|
||||||
|
|
|
@ -30,4 +30,5 @@ class T1059(AttackTechnique):
|
||||||
else:
|
else:
|
||||||
status = ScanStatus.UNSCANNED.value
|
status = ScanStatus.UNSCANNED.value
|
||||||
data.update(T1059.get_message_and_status(status))
|
data.update(T1059.get_message_and_status(status))
|
||||||
|
data.update(T1059.get_mitigation_by_status(status))
|
||||||
return data
|
return data
|
||||||
|
|
|
@ -40,4 +40,5 @@ class T1075(AttackTechnique):
|
||||||
else:
|
else:
|
||||||
status = ScanStatus.UNSCANNED.value
|
status = ScanStatus.UNSCANNED.value
|
||||||
data.update(T1075.get_message_and_status(status))
|
data.update(T1075.get_message_and_status(status))
|
||||||
|
data.update(T1075.get_mitigation_by_status(status))
|
||||||
return data
|
return data
|
||||||
|
|
|
@ -44,5 +44,6 @@ class T1082(AttackTechnique):
|
||||||
status = ScanStatus.USED.value
|
status = ScanStatus.USED.value
|
||||||
else:
|
else:
|
||||||
status = ScanStatus.UNSCANNED.value
|
status = ScanStatus.UNSCANNED.value
|
||||||
|
data.update(T1082.get_mitigation_by_status(status))
|
||||||
data.update(T1082.get_message_and_status(status))
|
data.update(T1082.get_message_and_status(status))
|
||||||
return data
|
return data
|
||||||
|
|
|
@ -31,5 +31,7 @@ class T1086(AttackTechnique):
|
||||||
status = ScanStatus.USED.value
|
status = ScanStatus.USED.value
|
||||||
else:
|
else:
|
||||||
status = ScanStatus.UNSCANNED.value
|
status = ScanStatus.UNSCANNED.value
|
||||||
|
|
||||||
|
data.update(T1086.get_mitigation_by_status(status))
|
||||||
data.update(T1086.get_message_and_status(status))
|
data.update(T1086.get_message_and_status(status))
|
||||||
return data
|
return data
|
||||||
|
|
|
@ -23,6 +23,7 @@ class T1210(AttackTechnique):
|
||||||
else:
|
else:
|
||||||
status = ScanStatus.UNSCANNED.value
|
status = ScanStatus.UNSCANNED.value
|
||||||
data.update(T1210.get_message_and_status(status))
|
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})
|
data.update({'scanned_services': scanned_services, 'exploited_services': exploited_services})
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ from monkey_island.cc.database import mongo
|
||||||
from common.utils.attack_utils import ScanStatus
|
from common.utils.attack_utils import ScanStatus
|
||||||
from monkey_island.cc.services.attack.attack_config import AttackConfig
|
from monkey_island.cc.services.attack.attack_config import AttackConfig
|
||||||
from common.utils.code_utils import abstractstatic
|
from common.utils.code_utils import abstractstatic
|
||||||
|
from cc.models.attack.attack_mitigations import AttackMitigations
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -40,7 +41,7 @@ class AttackTechnique(object, metaclass=abc.ABCMeta):
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def tech_id(self):
|
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
|
pass
|
||||||
|
|
||||||
|
@ -111,10 +112,21 @@ class AttackTechnique(object, metaclass=abc.ABCMeta):
|
||||||
data.update({'status': status,
|
data.update({'status': status,
|
||||||
'title': title,
|
'title': title,
|
||||||
'message': cls.get_message_by_status(status)})
|
'message': cls.get_message_by_status(status)})
|
||||||
|
data.update(cls.get_mitigation_by_status(status))
|
||||||
return data
|
return data
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_base_data_by_status(cls, status):
|
def get_base_data_by_status(cls, status):
|
||||||
data = cls.get_message_and_status(status)
|
data = cls.get_message_and_status(status)
|
||||||
data.update({'title': cls.technique_title()})
|
data.update({'title': cls.technique_title()})
|
||||||
|
data.update(cls.get_mitigation_by_status(status))
|
||||||
return data
|
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 {}
|
||||||
|
|
||||||
|
|
|
@ -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'])
|
|
@ -3,6 +3,7 @@ import logging
|
||||||
from monkey_island.cc.services.config import ConfigService
|
from monkey_island.cc.services.config import ConfigService
|
||||||
from monkey_island.cc.services.attack.attack_config import AttackConfig
|
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.services.post_breach_files import remove_PBA_files
|
||||||
|
from monkey_island.cc.models.attack.attack_mitigations import AttackMitigations
|
||||||
from flask import jsonify
|
from flask import jsonify
|
||||||
from monkey_island.cc.database import mongo
|
from monkey_island.cc.database import mongo
|
||||||
|
|
||||||
|
@ -15,14 +16,21 @@ class Database(object):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def reset_db():
|
def reset_db():
|
||||||
|
logger.info('Resetting database')
|
||||||
remove_PBA_files()
|
remove_PBA_files()
|
||||||
# We can't drop system collections.
|
# 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()
|
ConfigService.init_config()
|
||||||
AttackConfig.reset_config()
|
AttackConfig.reset_config()
|
||||||
logger.info('DB was reset')
|
logger.info('DB was reset')
|
||||||
return jsonify(status='OK')
|
return jsonify(status='OK')
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def drop_collection(collection_name: str):
|
||||||
|
mongo.db[collection_name].drop()
|
||||||
|
logger.info("Dropped collection {}".format(collection_name))
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def init_db():
|
def init_db():
|
||||||
if not mongo.db.collection_names():
|
if not mongo.db.collection_names():
|
||||||
|
|
|
@ -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()
|
|
@ -10567,6 +10567,11 @@
|
||||||
"object-visit": "1.0.1"
|
"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": {
|
"md5.js": {
|
||||||
"version": "1.3.5",
|
"version": "1.3.5",
|
||||||
"resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
|
"resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
|
||||||
|
|
|
@ -81,6 +81,7 @@
|
||||||
"filepond": "^4.7.3",
|
"filepond": "^4.7.3",
|
||||||
"json-loader": "^0.5.7",
|
"json-loader": "^0.5.7",
|
||||||
"jwt-decode": "^2.2.0",
|
"jwt-decode": "^2.2.0",
|
||||||
|
"marked": "^0.8.2",
|
||||||
"moment": "^2.24.0",
|
"moment": "^2.24.0",
|
||||||
"node-sass": "^4.13.0",
|
"node-sass": "^4.13.0",
|
||||||
"normalize.css": "^8.0.0",
|
"normalize.css": "^8.0.0",
|
||||||
|
|
|
@ -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 => (<div dangerouslySetInnerHTML={{__html: this.parseDescription(x.description)}} />),
|
||||||
|
style: {'whiteSpace': 'unset'}}
|
||||||
|
]
|
||||||
|
}])
|
||||||
|
}
|
||||||
|
|
||||||
|
static getMitigationName(name, url) {
|
||||||
|
if(url){
|
||||||
|
return (<a href={url} target={'_blank'}>{name}</a>)
|
||||||
|
} else {
|
||||||
|
return (<p>{name}</p>)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<br/>
|
||||||
|
{this.state.mitigations ?
|
||||||
|
<ReactTable
|
||||||
|
columns={MitigationsComponent.getMitigations()}
|
||||||
|
data={this.state.mitigations}
|
||||||
|
showPagination={false}
|
||||||
|
defaultPageSize={this.state.mitigations.length}
|
||||||
|
className={'attack-mitigation'}
|
||||||
|
/> : ''}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MitigationsComponent;
|
|
@ -2,6 +2,7 @@ import React from 'react';
|
||||||
import '../../report-components/security/StolenPasswords'
|
import '../../report-components/security/StolenPasswords'
|
||||||
import StolenPasswordsComponent from '../../report-components/security/StolenPasswords';
|
import StolenPasswordsComponent from '../../report-components/security/StolenPasswords';
|
||||||
import {ScanStatus} from './Helpers'
|
import {ScanStatus} from './Helpers'
|
||||||
|
import MitigationsComponent from './MitigationsComponent';
|
||||||
|
|
||||||
|
|
||||||
class T1003 extends React.Component {
|
class T1003 extends React.Component {
|
||||||
|
@ -19,6 +20,7 @@ class T1003 extends React.Component {
|
||||||
<StolenPasswordsComponent
|
<StolenPasswordsComponent
|
||||||
data={this.props.data.stolen_creds}/>
|
data={this.props.data.stolen_creds}/>
|
||||||
: ''}
|
: ''}
|
||||||
|
<MitigationsComponent mitigations={this.props.data.mitigations}/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactTable from 'react-table';
|
import ReactTable from 'react-table';
|
||||||
import {renderMachineFromSystemData, ScanStatus} from './Helpers';
|
import {renderMachineFromSystemData, ScanStatus} from './Helpers';
|
||||||
|
import MitigationsComponent from './MitigationsComponent';
|
||||||
|
|
||||||
class T1005 extends React.Component {
|
class T1005 extends React.Component {
|
||||||
|
|
||||||
|
@ -36,6 +37,7 @@ class T1005 extends React.Component {
|
||||||
showPagination={false}
|
showPagination={false}
|
||||||
defaultPageSize={this.props.data.collected_data.length}
|
defaultPageSize={this.props.data.collected_data.length}
|
||||||
/> : ''}
|
/> : ''}
|
||||||
|
<MitigationsComponent mitigations={this.props.data.mitigations}/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactTable from 'react-table';
|
import ReactTable from 'react-table';
|
||||||
import {renderMachineFromSystemData, renderUsageFields, ScanStatus} from './Helpers'
|
import {renderMachineFromSystemData, renderUsageFields, ScanStatus} from './Helpers'
|
||||||
|
import MitigationsComponent from './MitigationsComponent';
|
||||||
|
|
||||||
|
|
||||||
class T1016 extends React.Component {
|
class T1016 extends React.Component {
|
||||||
|
@ -36,6 +37,7 @@ class T1016 extends React.Component {
|
||||||
showPagination={false}
|
showPagination={false}
|
||||||
defaultPageSize={this.props.data.network_info.length}
|
defaultPageSize={this.props.data.network_info.length}
|
||||||
/> : ''}
|
/> : ''}
|
||||||
|
<MitigationsComponent mitigations={this.props.data.mitigations}/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactTable from 'react-table';
|
import ReactTable from 'react-table';
|
||||||
import {renderMachineFromSystemData, renderMachine, ScanStatus} from './Helpers'
|
import {renderMachineFromSystemData, renderMachine, ScanStatus} from './Helpers'
|
||||||
|
import MitigationsComponent from './MitigationsComponent';
|
||||||
|
|
||||||
|
|
||||||
class T1018 extends React.Component {
|
class T1018 extends React.Component {
|
||||||
|
@ -50,6 +51,7 @@ class T1018 extends React.Component {
|
||||||
showPagination={false}
|
showPagination={false}
|
||||||
defaultPageSize={this.props.data.scan_info.length}
|
defaultPageSize={this.props.data.scan_info.length}
|
||||||
/> : ''}
|
/> : ''}
|
||||||
|
<MitigationsComponent mitigations={this.props.data.mitigations}/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactTable from 'react-table';
|
import ReactTable from 'react-table';
|
||||||
import {renderMachine, ScanStatus} from './Helpers'
|
import {renderMachine, ScanStatus} from './Helpers'
|
||||||
|
import MitigationsComponent from './MitigationsComponent';
|
||||||
|
|
||||||
|
|
||||||
class T1021 extends React.Component {
|
class T1021 extends React.Component {
|
||||||
|
@ -16,7 +17,13 @@ class T1021 extends React.Component {
|
||||||
Header: 'Machine', id: 'machine', accessor: x => renderMachine(x.machine),
|
Header: 'Machine', id: 'machine', accessor: x => renderMachine(x.machine),
|
||||||
style: {'whiteSpace': 'unset'}, width: 160
|
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',
|
Header: 'Valid account used',
|
||||||
id: 'credentials',
|
id: 'credentials',
|
||||||
|
@ -43,6 +50,7 @@ class T1021 extends React.Component {
|
||||||
showPagination={false}
|
showPagination={false}
|
||||||
defaultPageSize={this.props.data.services.length}
|
defaultPageSize={this.props.data.services.length}
|
||||||
/> : ''}
|
/> : ''}
|
||||||
|
<MitigationsComponent mitigations={this.props.data.mitigations}/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactTable from 'react-table';
|
import ReactTable from 'react-table';
|
||||||
import {getUsageColumns} from './Helpers'
|
import {getUsageColumns} from './Helpers'
|
||||||
|
import MitigationsComponent from './MitigationsComponent';
|
||||||
|
|
||||||
|
|
||||||
class T1035 extends React.Component {
|
class T1035 extends React.Component {
|
||||||
|
@ -21,6 +22,7 @@ class T1035 extends React.Component {
|
||||||
showPagination={false}
|
showPagination={false}
|
||||||
defaultPageSize={this.props.data.services.length}
|
defaultPageSize={this.props.data.services.length}
|
||||||
/> : ''}
|
/> : ''}
|
||||||
|
<MitigationsComponent mitigations={this.props.data.mitigations}/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactTable from 'react-table';
|
import ReactTable from 'react-table';
|
||||||
import {ScanStatus} from './Helpers';
|
import {ScanStatus} from './Helpers';
|
||||||
|
import MitigationsComponent from './MitigationsComponent';
|
||||||
|
|
||||||
class T1041 extends React.Component {
|
class T1041 extends React.Component {
|
||||||
|
|
||||||
|
@ -30,6 +31,7 @@ class T1041 extends React.Component {
|
||||||
showPagination={false}
|
showPagination={false}
|
||||||
defaultPageSize={this.props.data.command_control_channel.length}
|
defaultPageSize={this.props.data.command_control_channel.length}
|
||||||
/> : ''}
|
/> : ''}
|
||||||
|
<MitigationsComponent mitigations={this.props.data.mitigations}/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactTable from 'react-table';
|
import ReactTable from 'react-table';
|
||||||
import {renderMachine, ScanStatus} from './Helpers'
|
import {renderMachine, ScanStatus} from './Helpers'
|
||||||
|
import MitigationsComponent from './MitigationsComponent';
|
||||||
|
|
||||||
|
|
||||||
class T1059 extends React.Component {
|
class T1059 extends React.Component {
|
||||||
|
@ -38,6 +39,7 @@ class T1059 extends React.Component {
|
||||||
showPagination={false}
|
showPagination={false}
|
||||||
defaultPageSize={this.props.data.cmds.length}
|
defaultPageSize={this.props.data.cmds.length}
|
||||||
/> : ''}
|
/> : ''}
|
||||||
|
<MitigationsComponent mitigations={this.props.data.mitigations}/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactTable from 'react-table';
|
import ReactTable from 'react-table';
|
||||||
import {getUsageColumns} from './Helpers'
|
import {getUsageColumns} from './Helpers'
|
||||||
|
import MitigationsComponent from './MitigationsComponent';
|
||||||
|
|
||||||
|
|
||||||
class T1064 extends React.Component {
|
class T1064 extends React.Component {
|
||||||
|
@ -21,6 +22,7 @@ class T1064 extends React.Component {
|
||||||
showPagination={false}
|
showPagination={false}
|
||||||
defaultPageSize={this.props.data.scripts.length}
|
defaultPageSize={this.props.data.scripts.length}
|
||||||
/> : ''}
|
/> : ''}
|
||||||
|
<MitigationsComponent mitigations={this.props.data.mitigations}/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import MitigationsComponent from './MitigationsComponent';
|
||||||
|
|
||||||
|
|
||||||
class T1065 extends React.Component {
|
class T1065 extends React.Component {
|
||||||
|
@ -7,6 +8,7 @@ class T1065 extends React.Component {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div>{this.props.data.message}</div>
|
<div>{this.props.data.message}</div>
|
||||||
|
<MitigationsComponent mitigations={this.props.data.mitigations}/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactTable from 'react-table';
|
import ReactTable from 'react-table';
|
||||||
import {renderMachine, ScanStatus} from './Helpers'
|
import {renderMachine, ScanStatus} from './Helpers'
|
||||||
|
import MitigationsComponent from './MitigationsComponent';
|
||||||
|
|
||||||
|
|
||||||
class T1075 extends React.Component {
|
class T1075 extends React.Component {
|
||||||
|
@ -41,6 +42,7 @@ class T1075 extends React.Component {
|
||||||
showPagination={false}
|
showPagination={false}
|
||||||
defaultPageSize={this.props.data.successful_logins.length}
|
defaultPageSize={this.props.data.successful_logins.length}
|
||||||
/> : ''}
|
/> : ''}
|
||||||
|
<MitigationsComponent mitigations={this.props.data.mitigations}/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactTable from 'react-table';
|
import ReactTable from 'react-table';
|
||||||
import {renderMachineFromSystemData, renderUsageFields, ScanStatus} from './Helpers'
|
import {renderMachineFromSystemData, renderUsageFields, ScanStatus} from './Helpers'
|
||||||
|
import MitigationsComponent from './MitigationsComponent';
|
||||||
|
|
||||||
|
|
||||||
class T1082 extends React.Component {
|
class T1082 extends React.Component {
|
||||||
|
@ -12,14 +13,18 @@ class T1082 extends React.Component {
|
||||||
static getSystemInfoColumns() {
|
static getSystemInfoColumns() {
|
||||||
return ([{
|
return ([{
|
||||||
columns: [
|
columns: [
|
||||||
{ Header: 'Machine',
|
{
|
||||||
|
Header: 'Machine',
|
||||||
id: 'machine',
|
id: 'machine',
|
||||||
accessor: x => renderMachineFromSystemData(x.machine),
|
accessor: x => renderMachineFromSystemData(x.machine),
|
||||||
style: {'whiteSpace': 'unset'}},
|
style: {'whiteSpace': 'unset'}
|
||||||
{ Header: 'Gathered info',
|
},
|
||||||
|
{
|
||||||
|
Header: 'Gathered info',
|
||||||
id: 'info',
|
id: 'info',
|
||||||
accessor: x => renderUsageFields(x.collections),
|
accessor: x => renderUsageFields(x.collections),
|
||||||
style: {'whiteSpace': 'unset'}}
|
style: {'whiteSpace': 'unset'}
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}])
|
}])
|
||||||
}
|
}
|
||||||
|
@ -36,6 +41,7 @@ class T1082 extends React.Component {
|
||||||
showPagination={false}
|
showPagination={false}
|
||||||
defaultPageSize={this.props.data.system_info.length}
|
defaultPageSize={this.props.data.system_info.length}
|
||||||
/> : ''}
|
/> : ''}
|
||||||
|
<MitigationsComponent mitigations={this.props.data.mitigations}/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactTable from 'react-table';
|
import ReactTable from 'react-table';
|
||||||
import {renderMachine, ScanStatus} from './Helpers'
|
import {renderMachine, ScanStatus} from './Helpers'
|
||||||
|
import MitigationsComponent from './MitigationsComponent';
|
||||||
|
|
||||||
|
|
||||||
class T1086 extends React.Component {
|
class T1086 extends React.Component {
|
||||||
|
@ -21,7 +22,12 @@ class T1086 extends React.Component {
|
||||||
width: 160
|
width: 160
|
||||||
},
|
},
|
||||||
{Header: 'Approx. Time', id: 'time', accessor: x => x.data[0].info.finished, style: {'whiteSpace': 'unset'}},
|
{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}
|
showPagination={false}
|
||||||
defaultPageSize={this.props.data.cmds.length}
|
defaultPageSize={this.props.data.cmds.length}
|
||||||
/> : ''}
|
/> : ''}
|
||||||
|
<MitigationsComponent mitigations={this.props.data.mitigations}/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactTable from 'react-table';
|
import ReactTable from 'react-table';
|
||||||
import {renderMachineFromSystemData, ScanStatus} from './Helpers'
|
import {renderMachineFromSystemData, ScanStatus} from './Helpers'
|
||||||
|
import MitigationsComponent from './MitigationsComponent';
|
||||||
|
|
||||||
|
|
||||||
class T1090 extends React.Component {
|
class T1090 extends React.Component {
|
||||||
|
@ -33,6 +34,7 @@ class T1090 extends React.Component {
|
||||||
showPagination={false}
|
showPagination={false}
|
||||||
defaultPageSize={this.props.data.proxies.length}
|
defaultPageSize={this.props.data.proxies.length}
|
||||||
/> : ''}
|
/> : ''}
|
||||||
|
<MitigationsComponent mitigations={this.props.data.mitigations}/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactTable from 'react-table';
|
import ReactTable from 'react-table';
|
||||||
import {ScanStatus} from './Helpers'
|
import {ScanStatus} from './Helpers'
|
||||||
|
import MitigationsComponent from './MitigationsComponent';
|
||||||
|
|
||||||
|
|
||||||
class T1105 extends React.Component {
|
class T1105 extends React.Component {
|
||||||
|
@ -32,6 +33,7 @@ class T1105 extends React.Component {
|
||||||
showPagination={false}
|
showPagination={false}
|
||||||
defaultPageSize={this.props.data.files.length}
|
defaultPageSize={this.props.data.files.length}
|
||||||
/> : ''}
|
/> : ''}
|
||||||
|
<MitigationsComponent mitigations={this.props.data.mitigations}/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactTable from 'react-table';
|
import ReactTable from 'react-table';
|
||||||
import {getUsageColumns} from './Helpers'
|
import {getUsageColumns} from './Helpers'
|
||||||
|
import MitigationsComponent from './MitigationsComponent';
|
||||||
|
|
||||||
|
|
||||||
class T1106 extends React.Component {
|
class T1106 extends React.Component {
|
||||||
|
@ -21,6 +22,7 @@ class T1106 extends React.Component {
|
||||||
showPagination={false}
|
showPagination={false}
|
||||||
defaultPageSize={this.props.data.api_uses.length}
|
defaultPageSize={this.props.data.api_uses.length}
|
||||||
/> : ''}
|
/> : ''}
|
||||||
|
<MitigationsComponent mitigations={this.props.data.mitigations}/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactTable from 'react-table';
|
import ReactTable from 'react-table';
|
||||||
import {renderMachineFromSystemData, ScanStatus} from './Helpers'
|
import {renderMachineFromSystemData, ScanStatus} from './Helpers'
|
||||||
|
import MitigationsComponent from './MitigationsComponent';
|
||||||
|
|
||||||
|
|
||||||
class T1107 extends React.Component {
|
class T1107 extends React.Component {
|
||||||
|
@ -46,6 +47,7 @@ class T1107 extends React.Component {
|
||||||
showPagination={false}
|
showPagination={false}
|
||||||
defaultPageSize={this.props.data.deleted_files.length}
|
defaultPageSize={this.props.data.deleted_files.length}
|
||||||
/> : ''}
|
/> : ''}
|
||||||
|
<MitigationsComponent mitigations={this.props.data.mitigations}/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactTable from 'react-table';
|
import ReactTable from 'react-table';
|
||||||
import {renderMachine, ScanStatus} from './Helpers'
|
import {renderMachine, ScanStatus} from './Helpers'
|
||||||
|
import MitigationsComponent from './MitigationsComponent'
|
||||||
|
|
||||||
|
|
||||||
class T1110 extends React.Component {
|
class T1110 extends React.Component {
|
||||||
|
@ -46,6 +47,7 @@ class T1110 extends React.Component {
|
||||||
showPagination={false}
|
showPagination={false}
|
||||||
defaultPageSize={this.props.data.services.length}
|
defaultPageSize={this.props.data.services.length}
|
||||||
/> : ''}
|
/> : ''}
|
||||||
|
<MitigationsComponent mitigations={this.props.data.mitigations}/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactTable from 'react-table';
|
import ReactTable from 'react-table';
|
||||||
import {getUsageColumns} from './Helpers';
|
import {getUsageColumns} from './Helpers';
|
||||||
|
import MitigationsComponent from './MitigationsComponent';
|
||||||
|
|
||||||
class T1129 extends React.Component {
|
class T1129 extends React.Component {
|
||||||
|
|
||||||
|
@ -20,6 +21,7 @@ class T1129 extends React.Component {
|
||||||
showPagination={false}
|
showPagination={false}
|
||||||
defaultPageSize={this.props.data.dlls.length}
|
defaultPageSize={this.props.data.dlls.length}
|
||||||
/> : ''}
|
/> : ''}
|
||||||
|
<MitigationsComponent mitigations={this.props.data.mitigations}/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactTable from 'react-table';
|
import ReactTable from 'react-table';
|
||||||
import {renderMachineFromSystemData, ScanStatus} from './Helpers'
|
import {renderMachineFromSystemData, ScanStatus} from './Helpers'
|
||||||
|
import MitigationsComponent from './MitigationsComponent';
|
||||||
|
|
||||||
|
|
||||||
class T1145 extends React.Component {
|
class T1145 extends React.Component {
|
||||||
|
@ -49,6 +50,7 @@ class T1145 extends React.Component {
|
||||||
showPagination={false}
|
showPagination={false}
|
||||||
defaultPageSize={this.props.data.ssh_info.length}
|
defaultPageSize={this.props.data.ssh_info.length}
|
||||||
/> : ''}
|
/> : ''}
|
||||||
|
<MitigationsComponent mitigations={this.props.data.mitigations}/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactTable from 'react-table';
|
import ReactTable from 'react-table';
|
||||||
import {renderMachineFromSystemData, ScanStatus} from './Helpers'
|
import {renderMachineFromSystemData, ScanStatus} from './Helpers'
|
||||||
|
import MitigationsComponent from './MitigationsComponent';
|
||||||
|
|
||||||
|
|
||||||
class T1188 extends React.Component {
|
class T1188 extends React.Component {
|
||||||
|
@ -47,6 +48,7 @@ class T1188 extends React.Component {
|
||||||
showPagination={false}
|
showPagination={false}
|
||||||
defaultPageSize={this.props.data.hops.length}
|
defaultPageSize={this.props.data.hops.length}
|
||||||
/> : ''}
|
/> : ''}
|
||||||
|
<MitigationsComponent mitigations={this.props.data.mitigations}/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactTable from 'react-table';
|
import ReactTable from 'react-table';
|
||||||
import {renderMachine} from './Helpers'
|
import {renderMachine} from './Helpers'
|
||||||
|
import MitigationsComponent from './MitigationsComponent';
|
||||||
|
|
||||||
|
|
||||||
class T1210 extends React.Component {
|
class T1210 extends React.Component {
|
||||||
|
@ -49,6 +50,7 @@ class T1210 extends React.Component {
|
||||||
</div>
|
</div>
|
||||||
<br/>
|
<br/>
|
||||||
{this.renderExploitedMachines()}
|
{this.renderExploitedMachines()}
|
||||||
|
<MitigationsComponent mitigations={this.props.data.mitigations}/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactTable from 'react-table';
|
import ReactTable from 'react-table';
|
||||||
import {renderMachine} from './Helpers'
|
import {renderMachine} from './Helpers'
|
||||||
|
import MitigationsComponent from './MitigationsComponent';
|
||||||
|
|
||||||
|
|
||||||
class T1210 extends React.Component {
|
class T1210 extends React.Component {
|
||||||
|
@ -99,6 +100,7 @@ class T1210 extends React.Component {
|
||||||
this.renderScannedServices(scanned_services) : ''}
|
this.renderScannedServices(scanned_services) : ''}
|
||||||
{this.props.data.exploited_services.length > 0 ?
|
{this.props.data.exploited_services.length > 0 ?
|
||||||
this.renderExploitedServices(this.props.data.exploited_services) : ''}
|
this.renderExploitedServices(this.props.data.exploited_services) : ''}
|
||||||
|
<MitigationsComponent mitigations={this.props.data.mitigations}/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactTable from 'react-table';
|
import ReactTable from 'react-table';
|
||||||
import {renderMachine, ScanStatus} from './Helpers'
|
import {renderMachine, ScanStatus} from './Helpers'
|
||||||
|
import MitigationsComponent from './MitigationsComponent';
|
||||||
|
|
||||||
|
|
||||||
class T1222 extends React.Component {
|
class T1222 extends React.Component {
|
||||||
|
@ -31,6 +32,7 @@ class T1222 extends React.Component {
|
||||||
showPagination={false}
|
showPagination={false}
|
||||||
defaultPageSize={this.props.data.commands.length}
|
defaultPageSize={this.props.data.commands.length}
|
||||||
/> : ''}
|
/> : ''}
|
||||||
|
<MitigationsComponent mitigations={this.props.data.mitigations}/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,7 +57,7 @@ class AttackReport extends React.Component {
|
||||||
static getComponentClass(tech_id, techniques) {
|
static getComponentClass(tech_id, techniques) {
|
||||||
switch (techniques[tech_id].status) {
|
switch (techniques[tech_id].status) {
|
||||||
case ScanStatus.SCANNED:
|
case ScanStatus.SCANNED:
|
||||||
return 'collapse-info';
|
return 'collapse-warning';
|
||||||
case ScanStatus.USED:
|
case ScanStatus.USED:
|
||||||
return 'collapse-danger';
|
return 'collapse-danger';
|
||||||
default:
|
default:
|
||||||
|
@ -79,16 +79,16 @@ class AttackReport extends React.Component {
|
||||||
renderLegend() {
|
renderLegend() {
|
||||||
return (<div id='header' className='row justify-content-between attack-legend'>
|
return (<div id='header' className='row justify-content-between attack-legend'>
|
||||||
<Col xs={4}>
|
<Col xs={4}>
|
||||||
<FontAwesomeIcon icon={faCircle} className='icon-default'/>
|
<FontAwesomeIcon icon={faCircle} className='technique-not-attempted'/>
|
||||||
<span> - Not scanned</span>
|
<span> - Not attempted</span>
|
||||||
</Col>
|
</Col>
|
||||||
<Col xs={4}>
|
<Col xs={4}>
|
||||||
<FontAwesomeIcon icon={faCircle} className='icon-info'/>
|
<FontAwesomeIcon icon={faCircle} className='technique-attempted'/>
|
||||||
<span> - Scanned</span>
|
<span> - Tried (but failed)</span>
|
||||||
</Col>
|
</Col>
|
||||||
<Col xs={4}>
|
<Col xs={4}>
|
||||||
<FontAwesomeIcon icon={faCircle} className='icon-danger'/>
|
<FontAwesomeIcon icon={faCircle} className='technique-used'/>
|
||||||
<span> - Used</span>
|
<span> - Successfully used</span>
|
||||||
</Col>
|
</Col>
|
||||||
</div>)
|
</div>)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
$transition: 300ms cubic-bezier(0.6, 0.3, 0.3, 0.6);
|
$transition: 300ms cubic-bezier(0.6, 0.3, 0.3, 0.6);
|
||||||
|
|
||||||
$danger-color: #d9acac;
|
$danger-color: #ebbcba;
|
||||||
$info-color: #ade3eb;
|
$info-color: #ade3eb;
|
||||||
$default-color: #e0ddde;
|
$default-color: #e0ddde;
|
||||||
|
$warning-color: #ffe28d;
|
||||||
|
|
||||||
.collapse-item button {
|
.collapse-item button {
|
||||||
font-size: inherit;
|
font-size: inherit;
|
||||||
|
@ -41,6 +42,10 @@ $default-color: #e0ddde;
|
||||||
background-color: $danger-color !important;
|
background-color: $danger-color !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.collapse-warning {
|
||||||
|
background-color: $warning-color !important;
|
||||||
|
}
|
||||||
|
|
||||||
.collapse-info {
|
.collapse-info {
|
||||||
background-color: $info-color !important;
|
background-color: $info-color !important;
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,3 +80,16 @@
|
||||||
padding-right:5px;
|
padding-right:5px;
|
||||||
margin-bottom: 1px;
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -1,21 +1,21 @@
|
||||||
// colors
|
// colors
|
||||||
$light-grey: #e0ddde;
|
$not-attempted: #e0ddde;
|
||||||
$light-blue: #ade3eb;
|
$attempted: #ffe28d;
|
||||||
$light-red: #d9acac;
|
$used: #ebbcba;
|
||||||
$black: #3a3a3a;
|
$black: #3a3a3a;
|
||||||
|
|
||||||
.attack-matrix .status-0 {
|
.attack-matrix .status-0 {
|
||||||
background-color: $light-grey !important;
|
background-color: $not-attempted !important;
|
||||||
color: $black;
|
color: $black;
|
||||||
}
|
}
|
||||||
|
|
||||||
.attack-matrix .status-1 {
|
.attack-matrix .status-1 {
|
||||||
background-color: $light-blue !important;
|
background-color: $attempted !important;
|
||||||
color: $black;
|
color: $black;
|
||||||
}
|
}
|
||||||
|
|
||||||
.attack-matrix .status-2 {
|
.attack-matrix .status-2 {
|
||||||
background-color: $light-red !important;
|
background-color: $used !important;
|
||||||
color: $black;
|
color: $black;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,3 +29,14 @@ $black: #3a3a3a;
|
||||||
border-bottom: 1px solid #0000000f;
|
border-bottom: 1px solid #0000000f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.technique-not-attempted {
|
||||||
|
color: $not-attempted;
|
||||||
|
}
|
||||||
|
|
||||||
|
.technique-attempted {
|
||||||
|
color: $attempted;
|
||||||
|
}
|
||||||
|
|
||||||
|
.technique-used {
|
||||||
|
color: $used;
|
||||||
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
top: 0;
|
top: 0;
|
||||||
z-index: 1000000;
|
z-index: 1000000;
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
|
font-size: large;
|
||||||
}
|
}
|
||||||
|
|
||||||
.report-nav > li > a{
|
.report-nav > li > a{
|
||||||
|
|
|
@ -23,3 +23,4 @@ mongomock
|
||||||
requests
|
requests
|
||||||
dpath
|
dpath
|
||||||
ring
|
ring
|
||||||
|
stix2
|
||||||
|
|
Loading…
Reference in New Issue