From 685362a5f4c5be6aa5832ef6f8fd6488e05a1a6c Mon Sep 17 00:00:00 2001 From: VakarisZ Date: Fri, 5 Jul 2019 16:05:35 +0300 Subject: [PATCH] Implemented file copy technique's report parsing. --- monkey/infection_monkey/exploit/sambacry.py | 6 ++- monkey/infection_monkey/exploit/sshexec.py | 11 ++++- .../exploit/tools/smb_tools.py | 11 ++++- .../post_breach/actions/users_custom_pba.py | 2 + .../telemetry/attack/t1105_telem.py | 17 ++++---- monkey/infection_monkey/transport/http.py | 11 ++++- .../cc/services/attack/attack_report.py | 5 ++- .../cc/services/attack/attack_schema.py | 8 ++++ .../attack/technique_reports/T1105.py | 25 ++++++++++++ .../attack/technique_reports/__init__.py | 12 +++--- .../components/attack/techniques/Helpers.js | 6 ++- .../src/components/attack/techniques/T1105.js | 40 +++++++++++++++++++ .../report-components/AttackReport.js | 4 +- 13 files changed, 134 insertions(+), 24 deletions(-) create mode 100644 monkey/monkey_island/cc/services/attack/technique_reports/T1105.py create mode 100644 monkey/monkey_island/cc/ui/src/components/attack/techniques/T1105.js diff --git a/monkey/infection_monkey/exploit/sambacry.py b/monkey/infection_monkey/exploit/sambacry.py index 9a9f934fb..86e43c73c 100644 --- a/monkey/infection_monkey/exploit/sambacry.py +++ b/monkey/infection_monkey/exploit/sambacry.py @@ -20,6 +20,7 @@ from infection_monkey.exploit import HostExploiter from infection_monkey.model import DROPPER_ARG from infection_monkey.network.smbfinger import SMB_SERVICE from infection_monkey.exploit.tools.helpers import build_monkey_commandline, get_target_monkey_by_os, get_monkey_depth +from infection_monkey.exploit.tools.helpers import get_interface_to_target from infection_monkey.pyinstaller_utils import get_binary_file_path from common.utils.attack_utils import ScanStatus from infection_monkey.telemetry.attack.t1105_telem import T1105Telem @@ -268,7 +269,10 @@ class SambaCryExploiter(HostExploiter): with monkeyfs.open(monkey_bin_64_src_path, "rb") as monkey_bin_file: smb_client.putFile(share, "\\%s" % self.SAMBACRY_MONKEY_FILENAME_64, monkey_bin_file.read) - T1105Telem(ScanStatus.USED, self.host.ip_addr[0], monkey_bin_64_src_path).send() + T1105Telem(ScanStatus.USED, + get_interface_to_target(self.host.ip_addr[0]), + self.host.ip_addr[0], + monkey_bin_64_src_path).send() smb_client.disconnectTree(tree_id) def trigger_module(self, smb_client, share): diff --git a/monkey/infection_monkey/exploit/sshexec.py b/monkey/infection_monkey/exploit/sshexec.py index 1c616c6e1..2c56471a4 100644 --- a/monkey/infection_monkey/exploit/sshexec.py +++ b/monkey/infection_monkey/exploit/sshexec.py @@ -7,6 +7,7 @@ import StringIO import infection_monkey.monkeyfs as monkeyfs from infection_monkey.exploit import HostExploiter from infection_monkey.exploit.tools.helpers import get_target_monkey, get_monkey_depth, build_monkey_commandline +from infection_monkey.exploit.tools.helpers import get_interface_to_target from infection_monkey.model import MONKEY_ARG from infection_monkey.network.tools import check_tcp_port from common.utils.exploit_enum import ExploitType @@ -163,11 +164,17 @@ class SSHExploiter(HostExploiter): ftp.putfo(file_obj, self._config.dropper_target_path_linux, file_size=monkeyfs.getsize(src_path), callback=self.log_transfer) ftp.chmod(self._config.dropper_target_path_linux, 0o777) - T1105Telem(ScanStatus.USED, self.host.ip_addr[0], src_path).send() + T1105Telem(ScanStatus.USED, + get_interface_to_target(self.host.ip_addr[0]), + self.host.ip_addr[0], + src_path).send() ftp.close() except Exception as exc: LOG.debug("Error uploading file into victim %r: (%s)", self.host, exc) - T1105Telem(ScanStatus.SCANNED, self.host.ip_addr[0], src_path).send() + T1105Telem(ScanStatus.SCANNED, + get_interface_to_target(self.host.ip_addr[0]), + self.host.ip_addr[0], + src_path).send() return False try: diff --git a/monkey/infection_monkey/exploit/tools/smb_tools.py b/monkey/infection_monkey/exploit/tools/smb_tools.py index 89e755d28..af088d9eb 100644 --- a/monkey/infection_monkey/exploit/tools/smb_tools.py +++ b/monkey/infection_monkey/exploit/tools/smb_tools.py @@ -10,6 +10,7 @@ import infection_monkey.config import infection_monkey.monkeyfs as monkeyfs from common.utils.attack_utils import ScanStatus from infection_monkey.telemetry.attack.t1105_telem import T1105Telem +from infection_monkey.exploit.tools.helpers import get_interface_to_target __author__ = 'itamar' @@ -138,7 +139,10 @@ class SmbTools(object): smb.putFile(share_name, remote_path, source_file.read) file_uploaded = True - T1105Telem(ScanStatus.USED, host.ip_addr[0], dst_path).send() + T1105Telem(ScanStatus.USED, + get_interface_to_target(host.ip_addr[0]), + host.ip_addr[0], + dst_path).send() LOG.info("Copied monkey file '%s' to remote share '%s' [%s] on victim %r", src_path, share_name, share_path, host) @@ -146,7 +150,10 @@ class SmbTools(object): except Exception as exc: LOG.debug("Error uploading monkey to share '%s' on victim %r: %s", share_name, host, exc) - T1105Telem(ScanStatus.SCANNED, host.ip_addr[0], dst_path).send() + T1105Telem(ScanStatus.SCANNED, + get_interface_to_target(host.ip_addr[0]), + host.ip_addr[0], + dst_path).send() continue finally: try: diff --git a/monkey/infection_monkey/post_breach/actions/users_custom_pba.py b/monkey/infection_monkey/post_breach/actions/users_custom_pba.py index 1a2070ac1..d923cb60e 100644 --- a/monkey/infection_monkey/post_breach/actions/users_custom_pba.py +++ b/monkey/infection_monkey/post_breach/actions/users_custom_pba.py @@ -85,10 +85,12 @@ class UsersPBA(PBA): if not pba_file_contents or not pba_file_contents.content: LOG.error("Island didn't respond with post breach file.") T1105Telem(ScanStatus.SCANNED, + WormConfiguration.current_server.split(':')[0], get_interface_to_target(WormConfiguration.current_server.split(':')[0]), filename).send() return False T1105Telem(ScanStatus.USED, + WormConfiguration.current_server.split(':')[0], get_interface_to_target(WormConfiguration.current_server.split(':')[0]), filename).send() try: diff --git a/monkey/infection_monkey/telemetry/attack/t1105_telem.py b/monkey/infection_monkey/telemetry/attack/t1105_telem.py index 171c4b963..454391da8 100644 --- a/monkey/infection_monkey/telemetry/attack/t1105_telem.py +++ b/monkey/infection_monkey/telemetry/attack/t1105_telem.py @@ -2,21 +2,24 @@ from infection_monkey.telemetry.attack.victim_host_telem import AttackTelem class T1105Telem(AttackTelem): - def __init__(self, status, host, path): + def __init__(self, status, src, dst, filename): """ T1105 telemetry. :param status: ScanStatus of technique - :param host: IP of machine which downloaded the file - :param path: Uploaded file's path + :param src: IP of machine which uploaded the file + :param dst: IP of machine which downloaded the file + :param filename: Uploaded file's name """ super(T1105Telem, self).__init__('T1105', status) - self.path = path - self.host = host + self.filename = filename + self.src = src + self.dst = dst def get_data(self): data = super(T1105Telem, self).get_data() data.update({ - 'path': self.path, - 'host': self.host + 'filename': self.filename, + 'src': self.src, + 'dst': self.dst }) return data diff --git a/monkey/infection_monkey/transport/http.py b/monkey/infection_monkey/transport/http.py index b4cb2e488..8da49f637 100644 --- a/monkey/infection_monkey/transport/http.py +++ b/monkey/infection_monkey/transport/http.py @@ -9,6 +9,7 @@ from urlparse import urlsplit import infection_monkey.monkeyfs as monkeyfs from infection_monkey.transport.base import TransportProxyBase, update_last_serve_time +from infection_monkey.exploit.tools.helpers import get_interface_to_target __author__ = 'hoffer' @@ -172,7 +173,10 @@ class HTTPServer(threading.Thread): @staticmethod def report_download(dest=None): LOG.info('File downloaded from (%s,%s)' % (dest[0], dest[1])) - TempHandler.T1105Telem(TempHandler.ScanStatus.USED, dest[0], self._filename).send() + TempHandler.T1105Telem(TempHandler.ScanStatus.USED, + get_interface_to_target(dest[0]), + dest[0], + self._filename).send() self.downloads += 1 if not self.downloads < self.max_downloads: return True @@ -222,7 +226,10 @@ class LockedHTTPServer(threading.Thread): @staticmethod def report_download(dest=None): LOG.info('File downloaded from (%s,%s)' % (dest[0], dest[1])) - TempHandler.T1105Telem(TempHandler.ScanStatus.USED, dest[0], self._filename).send() + TempHandler.T1105Telem(TempHandler.ScanStatus.USED, + get_interface_to_target(dest[0]), + dest[0], + self._filename).send() self.downloads += 1 if not self.downloads < self.max_downloads: return True diff --git a/monkey/monkey_island/cc/services/attack/attack_report.py b/monkey/monkey_island/cc/services/attack/attack_report.py index 7bec85a32..fdf57fb85 100644 --- a/monkey/monkey_island/cc/services/attack/attack_report.py +++ b/monkey/monkey_island/cc/services/attack/attack_report.py @@ -1,6 +1,6 @@ import logging 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 +from monkey_island.cc.services.attack.technique_reports import T1145, T1105 from monkey_island.cc.services.attack.attack_config import AttackConfig from monkey_island.cc.database import mongo @@ -17,7 +17,8 @@ TECHNIQUES = {'T1210': T1210.T1210, 'T1059': T1059.T1059, 'T1086': T1086.T1086, 'T1082': T1082.T1082, - 'T1145': T1145.T1145} + 'T1145': T1145.T1145, + 'T1105': T1105.T1105} 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 00d3e9536..be53a7555 100644 --- a/monkey/monkey_island/cc/services/attack/attack_schema.py +++ b/monkey/monkey_island/cc/services/attack/attack_schema.py @@ -40,6 +40,14 @@ SCHEMA = { "necessary": False, "description": "Pass the hash (PtH) is a method of authenticating as a user without " "having access to the user's cleartext password." + }, + "T1105": { + "title": "T1105 Remote file copy", + "type": "bool", + "value": True, + "necessary": True, + "description": "Files may be copied from one system to another to stage " + "adversary tools or other files over the course of an operation." } } }, diff --git a/monkey/monkey_island/cc/services/attack/technique_reports/T1105.py b/monkey/monkey_island/cc/services/attack/technique_reports/T1105.py new file mode 100644 index 000000000..176bae052 --- /dev/null +++ b/monkey/monkey_island/cc/services/attack/technique_reports/T1105.py @@ -0,0 +1,25 @@ +from monkey_island.cc.services.attack.technique_reports import AttackTechnique +from monkey_island.cc.database import mongo + +__author__ = "VakarisZ" + + +class T1105(AttackTechnique): + + tech_id = "T1105" + unscanned_msg = "Monkey didn't try to copy files to any systems." + scanned_msg = "Monkey tried to copy files, but failed." + used_msg = "Monkey successfully copied files to systems on the network." + + query = [{'$match': {'telem_category': 'attack', + 'data.technique': tech_id}}, + {'$project': {'_id': 0, + 'src': '$data.src', + 'dst': '$data.dst', + 'filename': '$data.filename'}}] + + @staticmethod + def get_report_data(): + data = T1105.get_tech_base_data() + data.update({'files': list(mongo.db.telemetry.aggregate(T1105.query))}) + 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 edd180d50..81b7dd6bf 100644 --- a/monkey/monkey_island/cc/services/attack/technique_reports/__init__.py +++ b/monkey/monkey_island/cc/services/attack/technique_reports/__init__.py @@ -52,13 +52,13 @@ class AttackTechnique(object): Gets the status of a certain attack technique. :return: ScanStatus Enum object """ - if mongo.db.attack_results.find_one({'telem_category': 'attack', - 'status': ScanStatus.USED.value, - 'technique': cls.tech_id}): + if mongo.db.telemetry.find_one({'telem_category': 'attack', + 'data.status': ScanStatus.USED.value, + 'data.technique': cls.tech_id}): return ScanStatus.USED - elif mongo.db.attack_results.find_one({'telem_category': 'attack', - 'status': ScanStatus.SCANNED.value, - 'technique': cls.tech_id}): + elif mongo.db.telemetry.find_one({'telem_category': 'attack', + 'data.status': ScanStatus.SCANNED.value, + 'data.technique': cls.tech_id}): return ScanStatus.SCANNED else: return ScanStatus.UNSCANNED diff --git a/monkey/monkey_island/cc/ui/src/components/attack/techniques/Helpers.js b/monkey/monkey_island/cc/ui/src/components/attack/techniques/Helpers.js index 9885219ad..1060f4b2d 100644 --- a/monkey/monkey_island/cc/ui/src/components/attack/techniques/Helpers.js +++ b/monkey/monkey_island/cc/ui/src/components/attack/techniques/Helpers.js @@ -11,7 +11,11 @@ export function renderMachine(val){ export function renderMachineFromSystemData(data) { let machineStr = data['hostname'] + " ( "; data['ips'].forEach(function(ipInfo){ - machineStr += ipInfo['addr'] + " "; + if(typeof ipInfo === "object"){ + machineStr += ipInfo['addr'] + " "; + } else { + machineStr += ipInfo + " "; + } }); return machineStr + ")" } 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 new file mode 100644 index 000000000..3f0438245 --- /dev/null +++ b/monkey/monkey_island/cc/ui/src/components/attack/techniques/T1105.js @@ -0,0 +1,40 @@ +import React from 'react'; +import '../../../styles/Collapse.scss' +import ReactTable from "react-table"; +import { renderMachineFromSystemData } from "./Helpers" + + +class T1105 extends React.Component { + + constructor(props) { + super(props); + } + + static getFilesColumns() { + return ([{ + Header: 'Files copied.', + columns: [ + {Header: 'Src. Machine', id: 'srcMachine', accessor: x => x.src, style: { 'whiteSpace': 'unset'}, width: 170 }, + {Header: 'Dst. Machine', id: 'dstMachine', accessor: x => x.dst, style: { 'whiteSpace': 'unset'}, width: 170}, + {Header: 'Filename', id: 'filename', accessor: x => x.filename, style: { 'whiteSpace': 'unset'}}, + ] + }])}; + + render() { + return ( +
+
{this.props.data.message}
+
+ {this.props.data.status !== 'UNSCANNED' ? + : ""} +
+ ); + } +} + +export default T1105; 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 348510175..6a9c1832c 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 @@ -14,6 +14,7 @@ import T1059 from "../attack/techniques/T1059"; import T1086 from "../attack/techniques/T1086"; import T1082 from "../attack/techniques/T1082"; import T1145 from "../attack/techniques/T1145"; +import T1105 from "../attack/techniques/T1105"; const tech_components = { 'T1210': T1210, @@ -24,7 +25,8 @@ const tech_components = { 'T1059': T1059, 'T1086': T1086, 'T1082': T1082, - 'T1145': T1145 + 'T1145': T1145, + 'T1105': T1105 }; const classNames = require('classnames');