Series · 4 partsInternal Network TriagePart 2 · You are here
- 1Kerberoasting Triage: Most Service Tickets Are a Waste of Your Time
- 2SMB Signing Is On. That Closed One Edge, Not the Graph.You are here
- 3Delegation Triage: You Were Taught the Rare One
- 4BloodHound Path Triage: The Shortest Path Is Usually the One That Expires First
NTLM relay in 60 seconds
“SMB signing is enforced across the estate” is usually where the relay conversation ends. It is a real improvement and it closes a real attack. It also gets treated as though it settled the question, and it did not, because signing is not a property of the domain. It is a property of one protocol at a time.
Relay is a graph problem. Signing removes edges. It does not remove the graph.
What signing actually protects
An NTLM relay needs two things: authentication you can capture, and a destination that will accept it without noticing it was replayed. Message signing breaks the second half — the session is bound to the original exchange, so a relayed handshake fails.
The catch is that each protocol decides this for itself, and they have not converged:
SMB has had signing for a long time. Domain controllers require it by default. Member servers and workstations historically did not, which is why relay lists were mostly other people’s laptops. Recent Windows builds have started enabling it on both client and server by default, so the classic SMB-to-SMB edge really is closing — slowly, and only as fleets turn over.
LDAP is the interesting one, because it has two separate controls that people conflate. Signing covers plain LDAP on 389. Channel binding covers LDAPS on 636. Turning on one and assuming it covered the other is common, and the gap is exactly where relayed authentication lands.
HTTP cannot sign NTLM at all. There is no signing in the scheme. An HTTP endpoint that accepts NTLM is a relay destination and always will be; the only protection is channel binding on the TLS side.
That last line is why this survives hardening programmes. The work goes into SMB, which is legible and has a GPO, and the protocol with no protection at all is the one nobody has a checkbox for.
The asymmetry worth internalising
Relay is cross-protocol. You do not have to relay SMB to SMB.
The productive direction is inbound over a protocol that cannot sign, outbound to a protocol whose signing is not enforced. Coerce authentication over HTTP, relay it to LDAP, and SMB signing is not part of the story at any point.
Which makes the WebClient service the single most underrated item on an internal assessment. It is what makes a Windows host speak WebDAV, it is off by default on servers but frequently running on workstations, and it can often be started remotely. A host with WebClient running is a host whose authentication you can obtain over HTTP — unsigned, by design.
Triage: three questions in order
The scan output everyone produces is a list of hosts without SMB signing. That is one edge of one protocol. The three questions that actually shape the finding:
1. What can I coerce, and over which protocol? Not “can I coerce” — the coercion primitives are well covered. Which transport the resulting authentication arrives on is what determines everything downstream.
2. Which destinations accept it unsigned? Per protocol, not per host. LDAP and LDAPS are separate answers.
3. What does that destination let me do? Relaying to LDAP as a workstation account is not the same as relaying as a domain controller account. The identity you capture is the ceiling on the outcome.
Enumeration for the first two is quick:
# Which hosts still permit unsigned SMB — the familiar list, and the least useful one
$ nxc smb 10.0.0.0/24 --gen-relay-list relay-targets.txt
# The question that usually gets skipped: is LDAP signing and channel binding enforced?
$ nxc ldap dc01.lab.local -u svc-audit -p '...' -M ldap-checker
LDAP-CHECKER dc01.lab.local LDAP signing NOT enforced
LDAP-CHECKER dc01.lab.local LDAPS channel binding is set to "never"
# Which hosts will speak WebDAV — i.e. hand you unsigned auth over HTTP
$ nxc smb 10.0.0.0/24 -u svc-audit -p '...' -M webdav
WEBDAV 10.0.0.51 WebClient service is running
Three lines, and the third one is the one that decides whether the first one mattered.
What that turns into
With unsigned LDAP and an HTTP coercion source, the relay does not need SMB at all:
$ ntlmrelayx.py -t ldap://dc01.lab.local --delegate-access --no-smb-server -smb2support
[*] Servers started, waiting for connections
[*] HTTPD: Received connection from 10.0.0.51
[*] Authenticating against ldap://dc01.lab.local as LAB/WS02$ SUCCEED
[*] Delegation rights modified successfully!
[*] WS02$ can now impersonate users on WS02$ via S4U2Proxy
That last line should look familiar if you have read the delegation note — the relay’s output is an RBCD write. The two findings are the same finding wearing different clothes: something that could write to a computer object, and a path to becoming that something.
Evidence matrix
| Signal | What it proves | Negative control | Defender verification |
|---|---|---|---|
| Source accepts an authentication trigger over HTTP/WebClient | A coercible credential can leave the source over a relayable transport | Disable WebClient on the lab source and confirm the HTTP edge disappears | Inventory WebClient state and authentication-capable HTTP surfaces by host role |
| LDAP target does not require signing or channel binding for the tested path | The destination will accept relayed NTLM without binding it to the original channel | Enforce the relevant LDAP control and expect relay failure | Validate domain-controller policy and capture the reject event, not only the registry value |
| Controlled relay performs a reversible RBCD or equivalent write | Source and destination edges compose into an operational chain | Restore the attribute and repeat against a hardened target | Audit directory writes and correlate source coercion, relay host, and changed object |
| SMB-to-SMB relay fails while HTTP-to-LDAP succeeds | SMB signing closed one edge but not the relay class | Test each protocol pair rather than extrapolating from SMB | Maintain a protocol-pair matrix for sources, transports, and destinations |
The pattern I keep seeing
Signing gets deployed as a project with an end date. It is scoped to SMB because SMB is where the guidance was written, it gets rolled out, the ticket closes, and the estate is recorded as remediated. LDAP signing gets deferred because it breaks legacy binds and someone has to find them first. Channel binding gets deferred for the same reason. WebClient never comes up at all, because it is not a security control and nobody inventories it.
Two years later the relay finding comes back, and it looks like a regression. It never was one. The closed edge stayed closed; the report just described one edge as though it were the whole graph.
What to hand the defenders
Report per protocol, not per estate. SMB signing enforced, LDAP signing not enforced, LDAPS channel binding off. Three states, three owners, three tickets. A single line saying “NTLM relay is possible” gets closed by pointing at the SMB rollout.
Name the coercion transport. If the path ran over HTTP, say so explicitly, because it changes which mitigation is relevant and pre-empts the “but signing is on” response before it happens.
WebClient is the cheap win. It is not needed on the overwhelming majority of workstations, disabling it removes the unsigned HTTP source entirely, and unlike LDAP hardening it does not require hunting for legacy dependencies first.
Then the durable one. Channel binding and LDAP signing enforced, and a plan to retire NTLM where it can be retired. That is slow work, which is precisely why it should be a separate finding from the things that can be done this quarter.
How current is this note?
The latest source-review, content-update, or publication date is shown.
The author completed a technical review. This does not, by itself, claim lab reproduction.
- learn.microsoft.com · smb-security-hardening ↗
- learn.microsoft.com · smb-signing-overview ↗
- msrc.microsoft.com · ADV190023 ↗
- learn.microsoft.com · ldap-session…ents-adv190023 ↗
- support.microsoft.com · kb5021989-ex…authentication ↗
- learn.microsoft.com · using-the-webdav-redirector ↗
- github.com · impacket ↗
- github.com · NetExec ↗
