Skip to content

Commit 900fa08

Browse files
committed
new module ntlm reflexion
1 parent 04a695f commit 900fa08

2 files changed

Lines changed: 97 additions & 0 deletions

File tree

nxc/modules/CVE-2025-33073.py

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
import time
2+
from impacket.dcerpc.v5 import transport, rrp
3+
from impacket.dcerpc.v5.rpcrt import RPC_C_AUTHN_GSS_NEGOTIATE
4+
from impacket.smbconnection import SessionError
5+
6+
7+
class NXCModule:
8+
# https://www.synacktiv.com/en/publications/ntlm-reflection-is-dead-long-live-ntlm-reflection-an-in-depth-analysis-of-cve-2025
9+
name = "CVE-2025-33073"
10+
description = "Attempt to check if the OS is vulnerable to CVE-2025-33073"
11+
supported_protocols = ["smb"]
12+
opsec_safe = True
13+
multiple_hosts = True
14+
15+
# Reference table from MSRC report
16+
# https://msrc.microsoft.com/update-guide/fr-FRS/vulnerability/CVE-2025-33073
17+
18+
MSRC_PATCHES = { # key = (major, minor, build), value = minimum patched UBR
19+
(6, 3, 9600): 22620, # Windows Server 2012 R2
20+
(6, 2, 9200): 25522, # Windows Server 2012
21+
(6, 1, 7601): 27769, # Windows Server 2008 R2 SP1
22+
(6, 0, 6003): 23351, # Windows Server 2008 SP2
23+
(10, 0, 14393): 8148, # Windows Server 2016
24+
(10, 0, 17763): 7434, # Windows Server 2019 / Win10 1809
25+
(10, 0, 20348): 3807, # Windows Server 2022
26+
(10, 0, 19044): 5965, # Windows 10 21H2
27+
(10, 0, 22621): 5472, # Windows 11 22H2
28+
}
29+
30+
def __init__(self, context=None, module_options=None):
31+
self.context = context
32+
self.module_options = module_options
33+
34+
def options(self, context, module_options):
35+
"""No options"""
36+
37+
def is_vulnerable(self, major, minor, build, ubr):
38+
key = (major, minor, build)
39+
min_patched_ubr = self.MSRC_PATCHES.get(key)
40+
if min_patched_ubr is None:
41+
return None # Unknown product
42+
if ubr is None:
43+
return None
44+
return ubr < min_patched_ubr
45+
46+
def on_login(self, context, connection):
47+
self.context = context
48+
self.connection = connection
49+
if not connection.conn.isSigningRequired(): # Not vulnerable if SMB signing is enabled
50+
self.trigger_winreg(connection.conn, context)
51+
rpc = transport.DCERPCTransportFactory(r"ncacn_np:445[\pipe\winreg]")
52+
rpc.set_smb_connection(connection.conn)
53+
if connection.kerberos:
54+
rpc.set_kerberos(connection.kerberos, kdcHost=connection.kdcHost)
55+
dce = rpc.get_dce_rpc()
56+
if connection.kerberos:
57+
dce.set_auth_type(RPC_C_AUTHN_GSS_NEGOTIATE)
58+
try:
59+
dce.connect()
60+
dce.bind(rrp.MSRPC_UUID_RRP)
61+
# Reading UBR from registry
62+
hRootKey = rrp.hOpenLocalMachine(dce)["phKey"]
63+
hKey = rrp.hBaseRegOpenKey(dce, hRootKey, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion")["phkResult"]
64+
ubr = rrp.hBaseRegQueryValue(dce, hKey, "UBR")[1]
65+
version_str = f"{connection.server_os_major}.{connection.server_os_minor}.{connection.server_os_build}.{ubr}" if ubr else None
66+
dce.disconnect()
67+
if not version_str:
68+
self.context.log.info("Could not determine OS version from registry")
69+
return
70+
vuln = self.is_vulnerable(connection.server_os_major, connection.server_os_minor, connection.server_os_build, ubr)
71+
if vuln:
72+
context.log.highlight(f"VULNERABLE to {self.name}! {connection.server_os} ({version_str})")
73+
except SessionError as e:
74+
if "STATUS_OBJECT_NAME_NOT_FOUND" in str(e):
75+
self.context.log.info(f"RemoteRegistry is probably deactivated: {e}")
76+
else:
77+
self.context.log.debug(f"Unexpected error: {e}")
78+
79+
def trigger_winreg(self, connection, context):
80+
# Original idea from https://twitter.com/splinter_code/status/1715876413474025704
81+
# Basically triggers the RemoteRegistry to start without admin privs
82+
tid = connection.connectTree("IPC$")
83+
try:
84+
connection.openFile(
85+
tid,
86+
r"\winreg",
87+
0x12019F,
88+
creationOption=0x40,
89+
fileAttributes=0x80,
90+
)
91+
except SessionError as e:
92+
# STATUS_PIPE_NOT_AVAILABLE error is expected
93+
context.log.debug(str(e))
94+
# Give remote registry time to start
95+
time.sleep(1)
96+

tests/e2e_commands.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ netexec smb TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS -M webdav -
131131
netexec smb TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS -M wifi
132132
netexec smb TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS -M winscp
133133
netexec smb TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS -M zerologon
134+
netexec smb TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS -M CVE-2025-33073
134135
# test for multiple modules at once
135136
netexec smb TARGET_HOST -u LOGIN_USERNAME -p LOGIN_PASSWORD KERBEROS -M spooler -M petitpotam -M zerologon -M nopac -M dfscoerce -M enum_av -M enum_dns -M gpp_autologin -M gpp_password -M lsassy -M impersonate -M install_elevated -M ioxidresolver -M ms17-010 -M ntlmv1 -M runasppl -M shadowcoerce -M uac -M webdav -M wifi
136137
##### SMB Anonymous Auth

0 commit comments

Comments
 (0)