Using NTLM Reflection to Own Active Directory (CVE-2025-33073)

Overview

Like many other pentesters and offensive security professionals out there, we’ve been getting a ton of mileage out of CVE-2025-33073. Microsoft describes this vulnerability as “Improper access control in Windows SMB allows an authorized attacker to elevate privileges over a network.” Additionally, the original blog post from SYNACKTIV provides an outstanding breakdown of the core issues responsible for creating the vulnerability in the first place.

While it may seem like ~7 months later that most everyone would have this issue patched, we’ve found that this is not remotely close to being true. Whether its enterprise domain controllers, tier-zero servers, or random workstations, we are consistently finding hosts still affected by this issue on nearly every engagement we have with our clients. Which, in turn, has provided us with trivial paths to compromising their environments.

The goal I’d like to achieve with this blog is to inform attackers and defenders alike that this issue is far more serious than it was given credit for, and the exploitation primitives are not as restrictive as was initially believed. Numerous techniques and bypasses for relaying to a myriad of different protocols from SMB are possible when dealing with NTLM reflection vulnerabilities. Some of these are specific to reflection issues.

Back to Table of Contents

How It Works

Since I stand zero chance of explaining it better, here’s an excerpt from the aforementioned blog post:

“NTLM local authentication is a special case of NTLM authentication in which the server informs the client (in the NTLM_CHALLENGE message) that there is no need to compute the challenge response in the NTLM_AUTHENTICATE message. Instead, the server sets the “Negotiate Local Call” in the challenge message, creates a server context, adds it to a global context list and inserts the context ID in the Reserved field. When the client receives the NTLM_CHALLENGE message, it understands that local NTLM authentication must occur. It then adds its token into the server context which was passed via the ID in the Reserved field. As the client and the server are on the same machine, everything happens inside the same lsass.exe process. Eventually, the client sends back an NTLM_AUTHENTICATE message which is nearly empty and the server uses the token added to its context to perform further operations (via SMB in our case).

The last question is: why are we privileged on the machine? Well, PetitPotam coerces lsass.exe into authenticating to our server and lsass.exe runs as SYSTEM. When the client (lsass.exe) receives the NTLM_CHALLENGE message indicating that local NTLM authentication must be performed, it copies its SYSTEM token into the server context. When the server receives the NTLM_AUTHENTICATE message, it retrieves the token from the context object and impersonates it to perform further actions via SMB (in our case, use the Remote Registry service to dump the SAM hive and compromise the machine).”

Back to Table of Contents

Prerequisites Needed for Attackers

So, you’re likely wondering how we forcefully trick the server into believing that it’s handling a local authentication request, versus a remote one? Simple – we abuse the way that LsapCheckMarshalledTargetInfo handles authentication. Two requirements are necessary.

  1. We can register a DNS record in an Active Directory DNS zone (possible for all “Authenticated Users” by default in AD!) OR are within the same broadcast domain as the target host(s) we’re attempting to exploit, we can advertise a DNS record that looks something like “localhost1UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAwbEAYBAAAA” and have that record point back to an attacker-controlled host.
  2. We can coerce machine account authentication via numerous coercion techniques such as PetitPotam, DFSCoerce, Printerbug, and many more. All authenticated users, irrespective of privilege, can satisfy this requirement in Active Directory.

These are not difficult prerequisites to satisfy in the overwhelming majority of environments. Many the organizations have not taken steps to ensure all “Authenticated Users” cannot add arbitrary DNS records into their AD DNS zones. In cases where that’s been fixed, you could go the poisoning/MiTM vector. This is particularly effective on very flat networks with large broadcast domains (such as a /16 – yes, we see it all the time). GitHub repositories exist already that handle this out of the box for attackers.

Back to Table of Contents

Classic Exploitation of CVE-2025-33073

When targeting a host that lacks SMB signing and is also vulnerable to CVE-2025-33073, successful exploitation will look something like this within ntlmrelayx.py:

Figure 1: Successful SMB->SMB Relay With CVE-2025-33073
Figure 1: Successful SMB->SMB Relay With CVE-2025-33073

This allows an attacker to instantly compromise the affected host via numerous techniques to execute code via SMB. Most of us already know you can execute code over SMB under the context of a privileged session, which is no big surprise. In fact, the SYNACKTIV blog states as much:

Figure 2: SYNACKTIV Blog Post Conclusion
Figure 2: SYNACKTIV Blog Post Conclusion

At this point, you’re probably laughing or saying something along the lines of:

“Hah! Imagine NOT having SMB signing universally enforced throughout your environment! What is this, 2013?”

Okay, fair. It’s certainly a factual statement that many more clients are enforcing SMB signing across the board in their environments. For us, it’s becoming increasingly rare to see an entire organization just fail to enforce SMB signing whatsoever. The more common scenario is that specific straggler hosts lack it, or non-domain joined hosts don’t receive a GPO to have the policy enforced. These hosts, for attackers and pentesters, are generally of very little interest due to their lack of privileged credential material (or any domain credentials at all) stored on them.

Well, it’s that simple then, right? Just enable SMB signing everywhere and ignore having to install security patches specific to NTLM reflection issues.

Wrong.

Back to Table of Contents

The Harsh Reality of NTLM Reflection Vulnerabilities in 2026

When CVE-2025-33073 was first introduced to the public writ-large, I was immediately interested in discovering the issue on our clients as it seemed like it would be something that would probably be an issue for quite some time, considering the cadence of most patching schedules in corporate environments. This intuition was indeed correct, but I was running into numerous situations where SMB signing was enabled, and it didn’t seem like there was a whole lot I could do with it other than just mark it as a failure to install security patches and move on.

That was, until in September 2025, a X/Twitter post by Alex Neff (@al3x_n3ff) that contained the following came to my attention:

Figure 3: X Post by Alex Neff
Figure 3: X Post by Alex Neff

The thread went on to state additional info:

Figure 4: X Post by Alex Neff (thread cont.)
Figure 4: X Post by Alex Neff (thread cont.)

This was a game-changer in many ways. Learning that we could relay cross-protocol to ADCS enrollment services, MSSQL databases, and WinRMS was very intriguing. Some astute readers might look at this information and make the following, generally correct assumption of:

“These environments must still be allowing Net-NTLMv1 authentication to occur! Net-NTLMv1 doesn’t allow for the inclusion of a MIC (Message Integrity Code), which always allows for cross-protocol relay to other services that enforce channel binding & signing!”

Kinda. In the following GitHub issue thread, multiple hackers troubleshoot extensively and prove that you can in fact perform cross-protocol relays from SMB to certain other protocols, some with channel binding enforced, some without, with pretty much no one really understanding why this was successful. It just worked, for whatever reason.

Figure 5: GitHub Issue Thread Excerpt
Figure 5: GitHub Issue Thread Excerpt

This doesn’t even consider the reality of Kerberos Reflection attacks, which are a whole different ballgame and simply outside the scope of this article entirely. Numerous configurations are vulnerable to Kerberos reflection attacks although signing and channel binding are still imperative to ensure you stand a chance at preventing it.

Okay, at this point, you’re probably thinking again:

“Okay, so enforce channel binding AND signing on all protocols, and I’m completely in the clear.”

Not quite (if you’re not installing security updates).

Back to Table of Contents

Extending NTLM Reflection Attacks to LDAP/LDAPS & (Possibly) RPC Services

While working on a new tool I plan on releasing a separate blog post for (related to relaying, coming very soon) – I came across the absolutely outstanding blog post by Italy-native security researcher Andrea Pierini – “Decoder” (@decoder-it).

https://decoder.cloud/2025/11/24/reflecting-your-authentication-when-windows-ends-up-talking-to-itself/

Decoder goes on to explain that Kerberos Reflection issues can also abuse the CredMarshalTargetInfo trick by registering a DNS record with a special, serialized base64-like structure called Credential Target Information. They also explain that, much like we already know, NTLM and Kerberos reflection attacks against SMB services result in SYSTEM privileges against vulnerable hosts.

Figure 6: Decoder’s Kerberos/NTLM Reflection Example
Figure 6: Decoder’s Kerberos/NTLM Reflection Example

They go on to state some special features and quirks about “NTLM Local Authentication” in Windows:

Figure 7: Special NTLM Local Authentication Attributes
Figure 7: Special NTLM Local Authentication Attributes
Figure 8: Special NTLM Local Authentication Attributes (cont.)
Figure 8: Special NTLM Local Authentication Attributes (cont.)

This was an interesting piece of information. However, something even more interesting caught my attention while reading through the blog. See below:

Figure 9: Explaining NTLM Reflection Against Domain Controllers
Figure 9: Explaining NTLM Reflection Against Domain Controllers

Woah. Nowhere had I seen that this was a thing. In fact, if I were to take basically every other blog post, technical writeup, and X thread I’d seen up to this point as gospel, my default assumption was “this is impossible and not feasible”. Decoder goes on to write:

Figure 10: SMB->LDAPS Reflection via CVE-2025-33073
Figure 10: SMB->LDAPS Reflection via CVE-2025-33073

At this point, I took this as a challenge to get this working in my own custom Impacket fork. After all, this was a massive attack vector that would make domain compromise trivial in a lot of environments. Decoder’s “partial MIC removal” code wasn’t public when I first began researching this on 01/06/2026. So, I went and built my own.

Back to Table of Contents

Implementing “SIGN + SEAL” NTLMSSP Header Stripping for NTLM Reflection

While Decoder’s Impacket fork wasn’t public, they gave us enough hints to run with. We know we need to strip NTLMSSP flags related to SIGN and SEAL attributes. But we need to preserve the MIC. Time to bust out the packet capture.

First, I ran a tcpdump command to capture authentication packets generated by exploitation of CVE-2025-33073. A basic filter on port 445 TCP is sufficient for the task. That resulted in the following packet being generated:

Figure 11: NTLM Reflection Packet NTLMSSP Attributes
Figure 11: NTLM Reflection Packet NTLMSSP Attributes

Aha! As the highlighted portions show, there’s three flags:

Negotiate Always Sign: Set

Negotiate Seal: Set

Negotiate Sign: Set

This has to be exactly what Decoder was referring to. So, I modified “ldaprelayclient.py” for Impacket’s ntlmrelayx.py to strip these flags. I started with just the “sign” flags to see the behavior, implemented the “–remove-mic-partial” flag in my own fork, and pushed it to my testing appliance. I just happened to have the perfect environment where a domain controller was vulnerable to CVE-2025-33073 and channel binding+signing were enforced to test the issue on.

My patch:

Figure 12: “Partial MIC Removal” Patch To “ldaprelayclient.py”
Figure 12: “Partial MIC Removal” Patch To “ldaprelayclient.py”

Without implementing the patch to ntlmrelayx.py, this was the behavior:

Figure 13: Reflection Fails to Authenticate to LDAPS
Figure 13: Reflection Fails to Authenticate to LDAPS

This was expected unless you had been lucky enough to receive Net-NTLMv1 authentication from the vulnerable host. However, add the partial MIC removal flag and…

Figure 14: Successful SMB->LDAPS Reflection
Figure 14: Successful SMB->LDAPS Reflection

Wow! That easy, huh? At this point, I already had a low-privilege computer account and simply added the account into the built-in “Administrators” group, DCSync’d, and collected the win! Very, very cool.

This really left me wondering though, is there any way to do this against other protocols?

Back to Table of Contents

Attempting SMB -> RPC Relay to Execute Privileged Commands (And SMB->SMB With Signing!)

To save the reader (you), some time reading paragraphs upon paragraphs of technical information, troubleshooting, and failures just to achieve a nothingburger – this is the abbreviated version.

What I found was that it is in fact possible to get SMB->RPC “relays” (using this loosely) with NTLM reflection via stripping similar authentication headers in the NTLMSSP response after coercion. My goal was to use TSCH via RPC as the “NT AUTHORITY\SYSTEM” account to create a service, have it execute an arbitrary command (such as adding a new local user account and making it an administrator), and then closing gracefully.

When I first managed to get the authentication to work successfully (instead of just throwing “Not implemented!”), I got excited:

Figure 15: Successful SMB->RPC Reflection Authentication
Figure 15: Successful SMB->RPC Reflection Authentication

However, this is where it gets less fun. No matter what I did, which authentication level I negotiated, however many flags within NTLMSSP I stripped, modified, or mangled, no matter how many different arguments I gave ntlmrelayx.py, I couldn’t get anything else other than:

Figure 16: DCERPC – rpc_s_access_denied
Figure 16: DCERPC – rpc_s_access_denied

This was a real bummer. I wanted it to work very badly, but what I found was that there was no real way to get past the sheer reality of either RPC requiring you to encrypt subsequent session packet data with the NTLM session key. This is similar to (exactly) how SMB signing works. In fact, I can get the same behavior from SMB, even with SMB signing enabled:

Figure 17: “Successful” (Not) SMB->SMB Relay with Signing
Figure 17: “Successful” (Not) SMB->SMB Relay with Signing

But, attempting to conduct any sort of action over the SOCKS relay would result in STATUS_ACCESS_DENIED, since we’re not honoring the session signing with the negotiated credentials. This is plainly obvious if you have any idea how SMB signing works, but I was curious to see if NTLM reflection issues had any effect on it.

I looked quite a bit to see if there’s a way to, for example, forcefully set “Negotiate LAN Manager Key”, “Request Non-NT Session Key”, “Negotiate 56”, and several other flags that would enable a DES-based session key that possibly, I could crack using rainbow tables or brute-force and authenticate as the SYSTEM account to these services. I also mangled the target hostname attribute within the NTLMSSP handshake (localhost, the computer’s actual hostname, FQDN, null) to no avail either. And numerous combinations of the above.

In my testing, this wasn’t fruitful and resulted in practically nothing of value occurring. I do think it could be possible with Net-NTLMv1 authentication perhaps, but that’s a whole different set of research.

Back to Table of Contents

Conclusions and Caveats

First, I want to thank all the previous researchers for putting most of the legwork in to discover much of this behavior. Funnily enough, as I neared finishing this blog post for our website, I checked @decoder-it’s GitHub page and saw this:

Figure 18: Decoder’s Now Public “partial-remove-mic” Impacket Fork
Figure 18: Decoder’s Now Public “partial-remove-mic” Impacket Fork

Pretty immediate facepalm, followed by laughter, as I had spent a few hours performing packet dumps, modifying ntlmrelayx.py, and testing, only to discover the code I needed was about to get posted anyways. For kicks, let’s look at Decoder’s implementation:

Figure 19: Decoder’s Partial MIC Removal Source
Figure 19: Decoder’s Partial MIC Removal Source

Mine, once again, for reference (version without removal of NTLMSSP_NEGOTIATE_SEAL):

Figure 20: Self-Rolled “Partial MIC Removal” Patch
Figure 20: Self-Rolled “Partial MIC Removal” Patch

Ours ended up pretty much identical to one another. They both worked. This commit was the specific, minimal modification working code that implemented the partial MIC removal behavior successfully against LDAPS.

Overall, I’m glad I went through the exercise of learning more about how NTLMSSP works under the hood. It’s not extraordinarily complex, and I think there exists further flaws and reflection primitives possible. In fact, I know there are, because once again, decoder-it has hinted:

Figure 21: Additional NTLM Reflection Issues Incoming
Figure 21: Additional NTLM Reflection Issues Incoming

What to really take away from this? Patch your systems, enable channel binding & signing on all protocols, universally. Make it a significant priority. NTLM reflection vulnerabilities can enable cross-protocol vulnerabilities that sometimes circumvent controls like signing and channel binding. CVE-2025-33073 is NOT a SYSTEM code execution vulnerability on hosts only lacking SMB signing – it is a high-impact, easily exploitable vulnerability with numerous abuse primitives that have zero mitigating controls in some cases.

Back to Table of Contents

Recommendations

Recommendations? Install the June 2025 Windows security updates if you want to be protected against this specific relay abuse. And, of course, enable signing and channel binding across all protocols. Rapidly patch exploits that allow NTLM reflection issues. Reconfigure your AD DNS domain ACLs to prevent all low-privilege AD users from creating new DNS records. This advice has always been universal but it’s especially important for NTLM reflection vulnerabilities of this class.
My next upcoming blog will be around a tool that will make it trivial for pentesters/security professionals to enumerate not only every instance of CVE-2025-33073 in a domain environment, but many other NTLM relay attack primitives.

Back to Table of Contents