mirror of https://github.com/avast/PurpleDome
Added plugins
parent
9fc86e9a87
commit
1c03ac4dcf
@ -0,0 +1,39 @@
|
|||||||
|
Plugin reasoning and planning. To be deleted later.
|
||||||
|
|
||||||
|
Which parts to make into plugins
|
||||||
|
================================
|
||||||
|
|
||||||
|
* Everything that could be contributed by external people
|
||||||
|
* Very specialized features
|
||||||
|
|
||||||
|
At the moment those are:
|
||||||
|
|
||||||
|
* kali attacks
|
||||||
|
* sensors
|
||||||
|
* vm_controllers
|
||||||
|
* post_processors
|
||||||
|
|
||||||
|
|
||||||
|
Parts of a plugin
|
||||||
|
=================
|
||||||
|
|
||||||
|
* Plugin specific configuration
|
||||||
|
* The plugin python code
|
||||||
|
* Additional files and tools to be used by the plugin
|
||||||
|
|
||||||
|
Therefore: We need a specific folder for every plugin
|
||||||
|
|
||||||
|
We want out own plugins plus external plugins to throw in. So we will have a default folder for plugins (ours) and additional folders with names chosen by external people. Plugins must be searched in those folders.
|
||||||
|
|
||||||
|
Picking and loading plugins
|
||||||
|
===========================
|
||||||
|
|
||||||
|
* the experiment.yaml config specifies the plugins to use
|
||||||
|
|
||||||
|
Found plugin interfaces
|
||||||
|
=======================
|
||||||
|
|
||||||
|
https://github.com/ironfroggy/straight.plugin
|
||||||
|
https://github.com/tibonihoo/yapsy ( -: not maintained anymore, sourceforge)
|
||||||
|
https://github.com/pytest-dev/pluggy/ ( -: not maintained anymore; +: used by tox and similar)
|
||||||
|
|
@ -0,0 +1 @@
|
|||||||
|
The hydra plugin remote controls the hydra tool. Hydra is able to brute force a number of protocols. Where especially ssh is relevant.
|
@ -0,0 +1,68 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# A plugin for hydra bruteforce attacks
|
||||||
|
|
||||||
|
from plugins.base.kali import KaliPlugin
|
||||||
|
|
||||||
|
|
||||||
|
class HydraPlugin(KaliPlugin):
|
||||||
|
|
||||||
|
# Boilerplate
|
||||||
|
name = "hydra"
|
||||||
|
description = "A plugin controlling the hydra brute forcing tool"
|
||||||
|
ttp = "T1110"
|
||||||
|
references = ["https://attack.mitre.org/techniques/T1110/"]
|
||||||
|
|
||||||
|
required_files = ["passwords.txt", "users.txt"] # 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__
|
||||||
|
|
||||||
|
# print("Init hydra")
|
||||||
|
|
||||||
|
def process_config(self, config):
|
||||||
|
""" process config and use defaults if stuff is missing
|
||||||
|
|
||||||
|
@param config: The config dict
|
||||||
|
"""
|
||||||
|
# TODO Create kali specific config class, send this to the plugins
|
||||||
|
self.conf["protocols"] = config.get("protocols", ["ssh"])
|
||||||
|
self.conf["userfile"] = config.get("userfile", "users.txt")
|
||||||
|
self.conf["pwdfile"] = config.get("pwdfile", "passwords.txt")
|
||||||
|
|
||||||
|
def command(self, targets, config):
|
||||||
|
""" Generate the command (having a separate step assists on debugging)
|
||||||
|
|
||||||
|
@param targets: A list of targets, ip addresses will do
|
||||||
|
@param config: dict with command specific configuration
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Set defaults if not present in config
|
||||||
|
self.process_config(config)
|
||||||
|
playground = self.machine_plugin.get_playground()
|
||||||
|
|
||||||
|
# Generate command
|
||||||
|
cmd = f"cd {playground};"
|
||||||
|
cmd += "sudo apt -y install hydra;"
|
||||||
|
for t in targets:
|
||||||
|
for p in self.conf['protocols']:
|
||||||
|
cmd += f"hydra -L {self.conf['userfile']} -P {self.conf['pwdfile']} {p}://{t};"
|
||||||
|
|
||||||
|
return cmd
|
||||||
|
|
||||||
|
def run(self, targets, config):
|
||||||
|
""" Run the command
|
||||||
|
|
||||||
|
@param targets: A list of targets, ip addresses will do
|
||||||
|
@param config: dict with command specific configuration
|
||||||
|
"""
|
||||||
|
|
||||||
|
# print("running hydra as plugin")
|
||||||
|
cmd = self.command(targets, config)
|
||||||
|
# res += str(self.run_cmd(cmd).stdout.strip())
|
||||||
|
res = self.run_cmd(cmd) or ""
|
||||||
|
|
||||||
|
# print("hydra done")
|
||||||
|
|
||||||
|
return res
|
@ -0,0 +1,8 @@
|
|||||||
|
12345
|
||||||
|
qwert
|
||||||
|
qwertz
|
||||||
|
qwerty
|
||||||
|
password
|
||||||
|
passw0rd
|
||||||
|
swordfish
|
||||||
|
test
|
@ -0,0 +1,5 @@
|
|||||||
|
test
|
||||||
|
root
|
||||||
|
password
|
||||||
|
nonexistend_user_1
|
||||||
|
nonexistend_user_2
|
@ -0,0 +1,79 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# A plugin to nmap targets
|
||||||
|
|
||||||
|
from plugins.base.kali import KaliPlugin
|
||||||
|
|
||||||
|
|
||||||
|
# TODO All scan patterns need explicit logging into the attack log !
|
||||||
|
# TODO: Add config for subnet range for ping sweeps
|
||||||
|
# TODO: Add IP exclusion --exclude ip,ip,ip to not accidentially scan non-targets
|
||||||
|
# TODO: host discovery Ping scan: -sn
|
||||||
|
# TODO: host discovery PE/PP/PM
|
||||||
|
# TODO: host discovery PS/PA/PU/PY
|
||||||
|
# TODO: host discovery reverse DNS resolution
|
||||||
|
# TODO OS identification
|
||||||
|
# TODO service discovery
|
||||||
|
# TODO stealth scans
|
||||||
|
# TODO firewall evasion
|
||||||
|
# TODO service fingerprinting
|
||||||
|
# TODO udp scans -sU
|
||||||
|
# TODO TCP SYN scan: -sS
|
||||||
|
# TODO TCP connect scan: -sT
|
||||||
|
# TODO port scan without prior ping (this is to avoid triggering firewall logic): -Pn
|
||||||
|
|
||||||
|
class NmapPlugin(KaliPlugin):
|
||||||
|
|
||||||
|
# Boilerplate
|
||||||
|
name = "nmap"
|
||||||
|
description = "NMap scan the target"
|
||||||
|
ttp = "T1595"
|
||||||
|
references = ["https://attack.mitre.org/techniques/T1595/"]
|
||||||
|
|
||||||
|
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 process_config(self, config):
|
||||||
|
""" process config and use defaults if stuff is missing
|
||||||
|
|
||||||
|
@param config: The config dict
|
||||||
|
"""
|
||||||
|
# TODO Create kali specific config class, send this to the plugins
|
||||||
|
# TODO: NMap specific config should be added. So far we only have the basic scan
|
||||||
|
|
||||||
|
def command(self, targets, config):
|
||||||
|
""" Generate the command (having a separate step assists on debugging)
|
||||||
|
|
||||||
|
@param targets: A list of targets, ip addresses will do
|
||||||
|
@param config: dict with command specific configuration
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Set defaults if not present in config
|
||||||
|
self.process_config(config)
|
||||||
|
playground = self.machine_plugin.get_playground()
|
||||||
|
|
||||||
|
# Generate command
|
||||||
|
cmd = f"cd {playground};"
|
||||||
|
# cmd += "sudo apt -y install nmap;"
|
||||||
|
for t in targets:
|
||||||
|
cmd += f"nmap {t};"
|
||||||
|
|
||||||
|
return cmd
|
||||||
|
|
||||||
|
def run(self, targets, config):
|
||||||
|
""" Run the command
|
||||||
|
|
||||||
|
@param targets: A list of targets, ip addresses will do
|
||||||
|
@param config: dict with command specific configuration
|
||||||
|
"""
|
||||||
|
|
||||||
|
res = ""
|
||||||
|
|
||||||
|
cmd = self.command(targets, config)
|
||||||
|
|
||||||
|
res += self.run_cmd(cmd) or ""
|
||||||
|
|
||||||
|
return res
|
@ -0,0 +1,44 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# Some users are created (with weak passwords) and sshd is set to allow password-based access
|
||||||
|
|
||||||
|
from plugins.base.vulnerability_plugin import VulnerabilityPlugin
|
||||||
|
|
||||||
|
|
||||||
|
class SshdVulnerability(VulnerabilityPlugin):
|
||||||
|
|
||||||
|
# Boilerplate
|
||||||
|
name = "sshd_config_vul"
|
||||||
|
description = "Allowing passwords based sshd access"
|
||||||
|
ttp = "T1110"
|
||||||
|
references = ["https://attack.mitre.org/techniques/T1110/"]
|
||||||
|
|
||||||
|
required_files = [] # Files shipped with the plugin which are needed by the machine. Will be copied to the share
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
self.plugin_path = __file__
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
|
||||||
|
# allow password access via ssh
|
||||||
|
cmd = "sudo sed -i 's/PasswordAuthentication no/PasswordAuthentication yes/g' /etc/ssh/sshd_config"
|
||||||
|
print(cmd)
|
||||||
|
self.run_cmd(cmd)
|
||||||
|
|
||||||
|
# Restart ssh
|
||||||
|
cmd = "sudo service ssh restart"
|
||||||
|
print(cmd)
|
||||||
|
self.run_cmd(cmd)
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
|
||||||
|
# Re-configure sshd to stable state
|
||||||
|
cmd = "sudo sed -i 's/PasswordAuthentication yes/PasswordAuthentication no/g' /etc/ssh/sshd_config"
|
||||||
|
print(cmd)
|
||||||
|
self.run_cmd(cmd)
|
||||||
|
|
||||||
|
# Restart ssh
|
||||||
|
cmd = "sudo service ssh restart"
|
||||||
|
print(cmd)
|
||||||
|
self.run_cmd(cmd)
|
@ -0,0 +1,93 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# Some users are created (with weak passwords) and sshd is set to allow password-based access
|
||||||
|
|
||||||
|
from plugins.base.vulnerability_plugin import VulnerabilityPlugin
|
||||||
|
|
||||||
|
|
||||||
|
class WeakPasswordVulnerabilityVulnerability(VulnerabilityPlugin):
|
||||||
|
|
||||||
|
# Boilerplate
|
||||||
|
name = "weak_user_passwords"
|
||||||
|
description = "Adding users with weak passwords"
|
||||||
|
ttp = "T1110"
|
||||||
|
references = ["https://attack.mitre.org/techniques/T1110/"]
|
||||||
|
|
||||||
|
required_files = [] # Files shipped with the plugin which are needed by the machine. Will be copied to the share
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
self.plugin_path = __file__
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
|
||||||
|
if self.machine_plugin.config.os() == "linux":
|
||||||
|
# Add vulnerable user
|
||||||
|
# mkpasswd -m sha-512 # To calc the passwd
|
||||||
|
# This is in the debian package "whois"
|
||||||
|
|
||||||
|
# user with password "test"
|
||||||
|
cmd = "useradd -m -p '$6$bc4k4Tq2.1GW$0ysyuxyfyds2JkfVEf9xHy39MhpS.hhnAo4sBLprNfIHqcpaa9GJseRJJsrq0cSOWwYlOPrdHQNHp10E1ekO81' -s /bin/bash test"
|
||||||
|
print(cmd)
|
||||||
|
self.run_cmd(cmd)
|
||||||
|
|
||||||
|
# user with password "passw0rd"
|
||||||
|
cmd = "useradd -m -p '$6$q5PAnDI5K0uv$hMGMJQleeS9F2yLOiHXs2PxZHEmV.ook8jyWILzDGDxSTJmTTZSe.QgLVrnuwiyAl5PFJVARkMsSnPICSndJR1' -s /bin/bash password"
|
||||||
|
print(cmd)
|
||||||
|
self.run_cmd(cmd)
|
||||||
|
elif self.machine_plugin.config.os() == "windows":
|
||||||
|
# net user username password /add
|
||||||
|
cmd = "net user test test /add"
|
||||||
|
print(cmd)
|
||||||
|
self.run_cmd(cmd)
|
||||||
|
|
||||||
|
cmd = "net user password passw0rd /add"
|
||||||
|
print(cmd)
|
||||||
|
self.run_cmd(cmd)
|
||||||
|
|
||||||
|
# Adding the new users to RDP (just in case we want to test RDP)
|
||||||
|
cmd = """NET LOCALGROUP "Remote Desktop Users" password /ADD"""
|
||||||
|
print(cmd)
|
||||||
|
self.run_cmd(cmd)
|
||||||
|
|
||||||
|
cmd = """NET LOCALGROUP "Remote Desktop Users" test /ADD"""
|
||||||
|
print(cmd)
|
||||||
|
self.run_cmd(cmd)
|
||||||
|
|
||||||
|
else:
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
|
||||||
|
if self.machine_plugin.config.os() == "linux":
|
||||||
|
# Remove user
|
||||||
|
cmd = "sudo userdel -r test"
|
||||||
|
print(cmd)
|
||||||
|
self.run_cmd(cmd)
|
||||||
|
|
||||||
|
# Remove user
|
||||||
|
cmd = "sudo userdel -r password"
|
||||||
|
print(cmd)
|
||||||
|
self.run_cmd(cmd)
|
||||||
|
elif self.machine_plugin.config.os() == "windows":
|
||||||
|
# net user username /delete
|
||||||
|
|
||||||
|
cmd = "net user test /delete"
|
||||||
|
print(cmd)
|
||||||
|
self.run_cmd(cmd)
|
||||||
|
|
||||||
|
cmd = "net user password /delete"
|
||||||
|
print(cmd)
|
||||||
|
self.run_cmd(cmd)
|
||||||
|
|
||||||
|
# Remove the new users to RDP (just in case we want to test RDP)
|
||||||
|
cmd = """NET LOCALGROUP "Remote Desktop Users" password /DELETE"""
|
||||||
|
print(cmd)
|
||||||
|
self.run_cmd(cmd)
|
||||||
|
|
||||||
|
cmd = """NET LOCALGROUP "Remote Desktop Users" test /DELETE"""
|
||||||
|
print(cmd)
|
||||||
|
self.run_cmd(cmd)
|
||||||
|
|
||||||
|
else:
|
||||||
|
raise NotImplementedError
|
@ -0,0 +1,45 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# Enable RDP for users
|
||||||
|
# https://pureinfotech.com/enable-remote-desktop-command-prompt-windows-10/
|
||||||
|
|
||||||
|
from plugins.base.vulnerability_plugin import VulnerabilityPlugin
|
||||||
|
|
||||||
|
|
||||||
|
class RDPVulnerability(VulnerabilityPlugin):
|
||||||
|
|
||||||
|
# Boilerplate
|
||||||
|
name = "rdp_config_vul"
|
||||||
|
description = "Allowing rdp access"
|
||||||
|
ttp = "T1110"
|
||||||
|
references = ["https://attack.mitre.org/techniques/T1110/"]
|
||||||
|
|
||||||
|
required_files = [] # Files shipped with the plugin which are needed by the machine. Will be copied to the share
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
self.plugin_path = __file__
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
|
||||||
|
# allow password access via rdp
|
||||||
|
cmd = r"""reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server" /v fDenyTSConnections /t REG_DWORD /d 0 /f"""
|
||||||
|
print(cmd)
|
||||||
|
self.run_cmd(cmd)
|
||||||
|
|
||||||
|
# Open Firewall
|
||||||
|
cmd = """netsh advfirewall firewall set rule group="remote desktop" new enable=Yes"""
|
||||||
|
print(cmd)
|
||||||
|
self.run_cmd(cmd)
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
|
||||||
|
# Re-configure sshd to stable state
|
||||||
|
cmd = r"""reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server" /v fDenyTSConnections /t REG_DWORD /d 1 /f"""
|
||||||
|
print(cmd)
|
||||||
|
self.run_cmd(cmd)
|
||||||
|
|
||||||
|
# Reset firewall
|
||||||
|
cmd = """netsh advfirewall firewall set rule group="remote desktop" new enable=No"""
|
||||||
|
print(cmd)
|
||||||
|
self.run_cmd(cmd)
|
Loading…
Reference in New Issue