From ab461ef8d395735be2dedfb19f7a1bd41382dcf9 Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Thu, 18 Jul 2019 09:47:31 +0300 Subject: [PATCH 1/3] Implemented data collection from local system attack technique --- .../system_info/SSH_info_collector.py | 4 ++ .../system_info/azure_cred_collector.py | 5 +++ .../telemetry/attack/t1005_telem.py | 22 +++++++++++ .../cc/services/attack/attack_report.py | 5 ++- .../cc/services/attack/attack_schema.py | 14 +++++++ .../attack/technique_reports/T1005.py | 34 +++++++++++++++++ .../cc/services/config_schema.py | 2 +- .../src/components/attack/techniques/T1005.js | 38 +++++++++++++++++++ .../report-components/AttackReport.js | 4 +- 9 files changed, 124 insertions(+), 4 deletions(-) create mode 100644 monkey/infection_monkey/telemetry/attack/t1005_telem.py create mode 100644 monkey/monkey_island/cc/services/attack/technique_reports/T1005.py create mode 100644 monkey/monkey_island/cc/ui/src/components/attack/techniques/T1005.js diff --git a/monkey/infection_monkey/system_info/SSH_info_collector.py b/monkey/infection_monkey/system_info/SSH_info_collector.py index af1915e4d..60c509fc6 100644 --- a/monkey/infection_monkey/system_info/SSH_info_collector.py +++ b/monkey/infection_monkey/system_info/SSH_info_collector.py @@ -3,6 +3,9 @@ import pwd import os import glob +from common.utils.attack_utils import ScanStatus +from infection_monkey.telemetry.attack.t1005_telem import T1005Telem + __author__ = 'VakarisZ' LOG = logging.getLogger(__name__) @@ -71,6 +74,7 @@ class SSHCollector(object): if private_key.find('ENCRYPTED') == -1: info['private_key'] = private_key LOG.info("Found private key in %s" % private) + T1005Telem(ScanStatus.USED, 'SSH key', "Path: %s" % private).send() else: continue except (IOError, OSError): diff --git a/monkey/infection_monkey/system_info/azure_cred_collector.py b/monkey/infection_monkey/system_info/azure_cred_collector.py index 3b1127e44..80d9f064f 100644 --- a/monkey/infection_monkey/system_info/azure_cred_collector.py +++ b/monkey/infection_monkey/system_info/azure_cred_collector.py @@ -5,6 +5,9 @@ import json import glob import subprocess +from common.utils.attack_utils import ScanStatus +from infection_monkey.telemetry.attack.t1005_telem import T1005Telem + __author__ = 'danielg' LOG = logging.getLogger(__name__) @@ -54,6 +57,7 @@ class AzureCollector(object): decrypt_proc = subprocess.Popen(decrypt_command.split(), stdout=subprocess.PIPE, stdin=subprocess.PIPE) decrypt_raw = decrypt_proc.communicate(input=b64_result)[0] decrypt_data = json.loads(decrypt_raw) + T1005Telem(ScanStatus.USED, 'Azure credentials', "Path: %s" % filepath).send() return decrypt_data['username'], decrypt_data['password'] except IOError: LOG.warning("Failed to parse VM Access plugin file. Could not open file") @@ -92,6 +96,7 @@ class AzureCollector(object): # this is disgusting but the alternative is writing the file to disk... password_raw = ps_out.split('\n')[-2].split(">")[1].split("$utf8content")[1] password = json.loads(password_raw)["Password"] + T1005Telem(ScanStatus.USED, 'Azure credentials', "Path: %s" % filepath).send() return username, password except IOError: LOG.warning("Failed to parse VM Access plugin file. Could not open file") diff --git a/monkey/infection_monkey/telemetry/attack/t1005_telem.py b/monkey/infection_monkey/telemetry/attack/t1005_telem.py new file mode 100644 index 000000000..228ccb67c --- /dev/null +++ b/monkey/infection_monkey/telemetry/attack/t1005_telem.py @@ -0,0 +1,22 @@ +from infection_monkey.telemetry.attack.attack_telem import AttackTelem + + +class T1005Telem(AttackTelem): + def __init__(self, status, _type, info=""): + """ + T1005 telemetry. + :param status: ScanStatus of technique + :param _type: Type of data collected + :param info: Additional info about data + """ + super(T1005Telem, self).__init__('T1005', status) + self._type = _type + self.info = info + + def get_data(self): + data = super(T1005Telem, self).get_data() + data.update({ + 'type': self._type, + 'info': self.info + }) + return data diff --git a/monkey/monkey_island/cc/services/attack/attack_report.py b/monkey/monkey_island/cc/services/attack/attack_report.py index fab00c213..0cf15051c 100644 --- a/monkey/monkey_island/cc/services/attack/attack_report.py +++ b/monkey/monkey_island/cc/services/attack/attack_report.py @@ -3,7 +3,7 @@ import logging from monkey_island.cc.models import Monkey from monkey_island.cc.services.attack.technique_reports import T1210, T1197, T1110, T1075, T1003, T1059, T1086, T1082 from monkey_island.cc.services.attack.technique_reports import T1145, T1105, T1065, T1035, T1129, T1106, T1107, T1188 -from monkey_island.cc.services.attack.technique_reports import T1090, T1041, T1222 +from monkey_island.cc.services.attack.technique_reports import T1090, T1041, T1222, T1005 from monkey_island.cc.services.attack.attack_config import AttackConfig from monkey_island.cc.database import mongo @@ -30,7 +30,8 @@ TECHNIQUES = {'T1210': T1210.T1210, 'T1188': T1188.T1188, 'T1090': T1090.T1090, 'T1041': T1041.T1041, - 'T1222': T1222.T1222} + 'T1222': T1222.T1222, + 'T1005': T1005.T1005} REPORT_NAME = 'new_report' diff --git a/monkey/monkey_island/cc/services/attack/attack_schema.py b/monkey/monkey_island/cc/services/attack/attack_schema.py index caa058df4..f86d4ed02 100644 --- a/monkey/monkey_island/cc/services/attack/attack_schema.py +++ b/monkey/monkey_island/cc/services/attack/attack_schema.py @@ -182,6 +182,20 @@ SCHEMA = { } } }, + "collection": { + "title": "Collection", + "type": "object", + "properties": { + "T1005": { + "title": "T1005 Data from local system", + "type": "bool", + "value": True, + "necessary": False, + "description": "Sensitive data can be collected from local system sources, such as the file system " + "or databases of information residing on the system prior to Exfiltration." + } + } + }, "command_and_control": { "title": "Command and Control", "type": "object", diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/T1005.py b/monkey/monkey_island/cc/services/attack/technique_reports/T1005.py new file mode 100644 index 000000000..06f408784 --- /dev/null +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1005.py @@ -0,0 +1,34 @@ +from monkey_island.cc.services.attack.technique_reports import AttackTechnique +from monkey_island.cc.database import mongo + +__author__ = "VakarisZ" + + +class T1005(AttackTechnique): + + tech_id = "T1005" + unscanned_msg = "Monkey didn't gather any sensitive data from local system." + scanned_msg = "" + used_msg = "Monkey successfully gathered sensitive data from local system." + + query = [{'$match': {'telem_category': 'attack', + 'data.technique': tech_id}}, + {'$lookup': {'from': 'monkey', + 'localField': 'monkey_guid', + 'foreignField': 'guid', + 'as': 'monkey'}}, + {'$project': {'monkey': {'$arrayElemAt': ['$monkey', 0]}, + 'status': '$data.status', + 'type': '$data.type', + 'info': '$data.info'}}, + {'$addFields': {'_id': 0, + 'machine': {'hostname': '$monkey.hostname', 'ips': '$monkey.ip_addresses'}, + 'monkey': 0}}, + {'$group': {'_id': {'machine': '$machine', 'type': '$type', 'info': '$info'}}}, + {"$replaceRoot": {"newRoot": "$_id"}}] + + @staticmethod + def get_report_data(): + data = T1005.get_tech_base_data() + data.update({'collected_data': list(mongo.db.telemetry.aggregate(T1005.query))}) + return data diff --git a/monkey/monkey_island/cc/services/config_schema.py b/monkey/monkey_island/cc/services/config_schema.py index 07596cf51..72a70812c 100644 --- a/monkey/monkey_island/cc/services/config_schema.py +++ b/monkey/monkey_island/cc/services/config_schema.py @@ -422,7 +422,7 @@ SCHEMA = { "title": "Collect system info", "type": "boolean", "default": True, - "attack_techniques": ["T1082"], + "attack_techniques": ["T1082", "T1005"], "description": "Determines whether to collect system info" }, "should_use_mimikatz": { 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 new file mode 100644 index 000000000..6746d16ed --- /dev/null +++ b/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1005.js @@ -0,0 +1,38 @@ +import React from 'react'; +import '../../../styles/Collapse.scss' +import ReactTable from "react-table"; +import {renderMachineFromSystemData, scanStatus} from "./Helpers"; + +class T1005 extends React.Component { + + constructor(props) { + super(props); + } + + static getDataColumns() { + return ([{ + Header: "Data gathered from local systems", + columns: [ + {Header: 'Machine', id: 'machine', accessor: x => renderMachineFromSystemData(x.machine), style: { 'whiteSpace': 'unset' }}, + {Header: 'Type', id: 'type', accessor: x => x.type, style: { 'whiteSpace': 'unset' }}, + {Header: 'Info', id: 'info', accessor: x => x.info, style: { 'whiteSpace': 'unset' }}, + ]}])}; + + render() { + return ( +
+
{this.props.data.message}
+
+ {this.props.data.status === scanStatus.USED ? + : ""} +
+ ); + } +} + +export default T1005; 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 0aed990d8..3e1fe9501 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 @@ -25,6 +25,7 @@ import T1188 from "../attack/techniques/T1188"; import T1090 from "../attack/techniques/T1090"; import T1041 from "../attack/techniques/T1041"; import T1222 from "../attack/techniques/T1222"; +import T1005 from "../attack/techniques/T1005"; const tech_components = { 'T1210': T1210, @@ -45,7 +46,8 @@ const tech_components = { 'T1188': T1188, 'T1090': T1090, 'T1041': T1041, - 'T1222': T1222 + 'T1222': T1222, + 'T1005': T1005 }; const classNames = require('classnames'); From 5b074158ec4dca222908b4881561a418db60366c Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Tue, 20 Aug 2019 15:05:14 +0300 Subject: [PATCH 2/3] Renamed '_type' to 'gathered_data_type' in data from local system attack technique. --- monkey/infection_monkey/telemetry/attack/t1005_telem.py | 8 ++++---- .../cc/services/attack/technique_reports/T1005.py | 4 ++-- .../cc/ui/src/components/attack/techniques/T1005.js | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/monkey/infection_monkey/telemetry/attack/t1005_telem.py b/monkey/infection_monkey/telemetry/attack/t1005_telem.py index 228ccb67c..999d8622a 100644 --- a/monkey/infection_monkey/telemetry/attack/t1005_telem.py +++ b/monkey/infection_monkey/telemetry/attack/t1005_telem.py @@ -2,21 +2,21 @@ from infection_monkey.telemetry.attack.attack_telem import AttackTelem class T1005Telem(AttackTelem): - def __init__(self, status, _type, info=""): + def __init__(self, status, gathered_data_type, info=""): """ T1005 telemetry. :param status: ScanStatus of technique - :param _type: Type of data collected + :param gathered_data_type: Type of data collected from local system :param info: Additional info about data """ super(T1005Telem, self).__init__('T1005', status) - self._type = _type + self.gathered_data_type = gathered_data_type self.info = info def get_data(self): data = super(T1005Telem, self).get_data() data.update({ - 'type': self._type, + 'gathered_data_type': self.gathered_data_type, 'info': self.info }) return data diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/T1005.py b/monkey/monkey_island/cc/services/attack/technique_reports/T1005.py index 06f408784..b84fe4a6f 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/T1005.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1005.py @@ -19,12 +19,12 @@ class T1005(AttackTechnique): 'as': 'monkey'}}, {'$project': {'monkey': {'$arrayElemAt': ['$monkey', 0]}, 'status': '$data.status', - 'type': '$data.type', + 'gathered_data_type': '$data.gathered_data_type', 'info': '$data.info'}}, {'$addFields': {'_id': 0, 'machine': {'hostname': '$monkey.hostname', 'ips': '$monkey.ip_addresses'}, 'monkey': 0}}, - {'$group': {'_id': {'machine': '$machine', 'type': '$type', 'info': '$info'}}}, + {'$group': {'_id': {'machine': '$machine', 'gathered_data_type': '$gathered_data_type', 'info': '$info'}}}, {"$replaceRoot": {"newRoot": "$_id"}}] @staticmethod 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 6746d16ed..afc676797 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 @@ -11,10 +11,10 @@ class T1005 extends React.Component { static getDataColumns() { return ([{ - Header: "Data gathered from local systems", + Header: "Sensitive data", columns: [ {Header: 'Machine', id: 'machine', accessor: x => renderMachineFromSystemData(x.machine), style: { 'whiteSpace': 'unset' }}, - {Header: 'Type', id: 'type', accessor: x => x.type, style: { 'whiteSpace': 'unset' }}, + {Header: 'Type', id: 'type', accessor: x => x.gathered_data_type, style: { 'whiteSpace': 'unset' }}, {Header: 'Info', id: 'info', accessor: x => x.info, style: { 'whiteSpace': 'unset' }}, ]}])}; From bfa524b3ea24567b205cdda7aa048e86e17b38e6 Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Tue, 20 Aug 2019 15:20:38 +0300 Subject: [PATCH 3/3] Fixed typos in UI (renamed scanStatus to ScanStatus) --- .../cc/ui/src/components/attack/techniques/T1005.js | 4 ++-- .../cc/ui/src/components/attack/techniques/T1222.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) 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 afc676797..6d46c2285 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,7 +1,7 @@ import React from 'react'; import '../../../styles/Collapse.scss' import ReactTable from "react-table"; -import {renderMachineFromSystemData, scanStatus} from "./Helpers"; +import {renderMachineFromSystemData, ScanStatus} from "./Helpers"; class T1005 extends React.Component { @@ -23,7 +23,7 @@ class T1005 extends React.Component {
{this.props.data.message}

- {this.props.data.status === scanStatus.USED ? + {this.props.data.status === ScanStatus.USED ?
{this.props.data.message}

- {this.props.data.status === scanStatus.USED ? + {this.props.data.status === ScanStatus.USED ?