Skip to Main Content
February 03, 2022

I’m bringing relaying back: A comprehensive guide on relaying anno 2022

Written by Jean-Francois Maes

For years now, Internal Penetration Testing teams have been successful in obtaining a foothold or even compromising entire domains through a technique called NTLM relaying. The earliest, most descriptive relaying blog post I could find dates all the way back to 2017 written by Marcello, better known as byt3bl33d3r:
https://byt3bl33d3r.github.io/practical-guide-to-ntlm-relaying-in-2017-aka-getting-a-foothold-in-under-5-minutes.html

At the time of writing this blog post in 2022, (un)surprisingly, relaying is still very much alive. This blog post aims to be a comprehensive resource that will walk through the attack primitives that continue to work today. While most will be well known techniques, some techniques involving Active Directory Certificate Services might be lesser known.

The Lab Setup

For this blogpost, I have created a mini lab in Snap Labs, which will be available alongside this blog post for anyone with an account.  Unfortunately, AWS does some weird magic in their backend which prevents multicast traffic from hitting Responder. As a results, I was forced to create the lab offline.eq

The lab architecture looks as follows:

Our lab contains three (3) servers in one (1) domain (bravoteam.local) :

  • The domain controller - A server 2019 instance with Active Directory Domain Services (needed to become a domain controller) and Active Directory Certificate Services installed (for AD CS abuse avenues in this blog post)
  • Server 1 - A Windows Server 2019 out of the box, no special configurations have been made
  • Server 2 - Also a Windows Server 2019 without any special configuration

Our domain has four (4) users:

  • Bravoteam\blackburn - Enterprise admin
  • Bravoteam\hayes - Domain admin
  • Bravoteam\spenser - A regular domain user that has local admin privileges on server 1
  • Bravoteam\perry - A regular domain user with no special privileges at all

All these users have the same password of Qwerty123, as this is a lab environment, and they have not had their properties modified in any special way.

The Attacker Machine

We will also need an attacker-controlled machine in the form of a Linux system. In this blog post, we will be using a Kali machine. Regardless of what your distro of choice is, the following tools will be required to follow along this blog post:

Attack 0: No Attack at all, be Quiet and Just Listen

In order to assess the effectiveness of relaying attacks, we will need to learn more about our network environment. In order to succeed with 'classic' relaying attacks, some prerequisites must be met:

  1. There must be broadcast traffic in the environment. Classic examples of this are DNS replacement protocols like Link Local Multicast Name Resolution (LLMNR) and NetBIOS Name Resolution (NBT-NS).
  2. We must have suitable targets (servers with SMB signing not enforced).

Later in this blog post, we will also take a look at some other attacks, but let's focus on the basics first.

In order to check if prerequisite number one is met, we can use Responder in analyze mode as follows.

Figure 1 - Responder in Analyze Mode

The A flag makes sure we are just listening in, but we are not actually poisoning anything. If there is broadcast traffic present, it should not take too long before you will get some noise in your console window.

Figure 2 - Broadcast tTraffic

We see some NBT-NS traffic flying in, which is good news for adversaries but less so for organizations.

The next step is to verify whether we have servers present with SMB Signing disabled. This will usually be the case, as SMB Signing is only enforced on domain controllers by default and is usually not turned on by organizations due to it affecting performance.

In order to verify whether our assumption is correct, we can utilize CrackMapExec’s SMB module with the –gen-relay-list flag to compile a list of all servers that have SMB Signing disabled.

Note: This is a lab environment with three (3) machines—in a real-life organization, this list would be significantly longer.

Figure 3- Domain Controller With SMB Signing Enabled

As expected, the domain controller has SMB Signing on, but the other two (2) servers in the domain have SMB signing off, which makes them prime relay targets. Now that we did our recon, let’s take a look at all the shenanigans we can pull here. But before we do, I wanted to point out some interesting behavior about Responder in analyze mode.

While it is true that Responder in analyze mode does not poison anything, it will still capture the hash (provided the SMB or any other server-like HTTP that could receive connections is turned on).

This is useful for when you are on an engagement and your client has some kind of network spider or software that does patch management, as you will be able to capture the hash of that account without having to poison anything.

Figure 4 - Juicy NTLM Hash

Keep in mind that NetNTLMv1 and NetNTLMv2 hashes are not the actual NTLM hashes that can be used for pass-the-hash type attacks. NetNTLM hashes are the result of a challenge and response protocol. NetNTLM hashes can only be utilized for relaying attacks or for potential brute-forcing using Hashcat, for example.

Another pro tip is that NTLMv2 hashes are harder to crack than their NTLMv1 counterpart but not impossible for user accounts! Computer accounts, on the other hand, are not worth your computing power as you won’t crack them in the NetNTLMv2 format. (Note: This is important for later.)

Attack 1: The Classic SAM Dump SMB to SMB Relay Using Responder and NTLM Relay

Probably the best-known attack scenario is to use Responder and NTLM relay together. This approach relies on broadcast protocols in the network such as LLMNR or NBT-NS. In order for Responder and NTLM relay to work nicely together, we have to modify the Responder.conf file and disable the HTTP and SMB servers (as NTLM relay will be our SMB and HTTP server).

Figure 5 - Turning the SMB and HTTP Server off in Responder.conf

If an attacker is able to relay authentication of a user to a system that has SMB Signing turned off (default) and that user happens to be a local admin on that system, the default behavior of NTLM relay is to dump the security account manager database and reveal the password hashes of local accounts.

In order to perform the attack, we will relay using the NTLM relay script from the Impacket suite. We can easily set up the relay using our generated target file from earlier as follows.

Figure 6 - Setting up NTLM Relay

The way I like to run Responder is using either -rdwF or -rdP (which is easy to remember thanks to the RDP, lol). Nowadays, the rdP flags will probably be more successful than the wF counterpart, as explained by Laurent Gaffié in this blogpost: https://g-laurent.blogspot.com/2021/08/responders-dhcp-poisoner.html

Why -P and not -F? Nowadays, WPAD NTLM authentication is unlikely successful, therefore forcing NTLM authentication on wpad.dat retrieval is not recommended. The concept is to serve the wpad.dat file with no user authentication, and as soon the client starts using our proxy, we force authentication with the Proxy-Auth module :)

Update:In the newer versions of Responder, the -r and -f flags have disappeared. Additionally, the -d flag has now been changed from “Enable answers for NETBIOS domain suffix queries. Answering to domain suffixes will likely break stuff on the network. Default: False” to “Enable answers for DHCP broadcast requests. This option will inject a WPAD server in the DHCP response. Default: False”. It should also be noted that -d as it is now CAN have an impact on your client's network, as you are effectively poisoning the WPAD file over DHCP, which does not always revert back immediately once you stop the attack. It will likely require a reboot.

Figure 7- Responder in rdP Mode (Careful With the New d Flag Though!)

Now we see something strange.

We get a successful authentication for Spenser, but it seems like we cannot relay to the server where Spenser is a local admin—why is that?

Figure 8 - Failed Authentication
Figure 9 - Spenser is Admin on this Server

This is because a computer cannot relay toward itself, and Microsoft fixed that issue a long time ago. Let’s try it again, but this time we will trigger the relay from srv01 toward srv02 as Spenser:

Figure 10 - Much Better! We get a Dumped SAM

This time our SAM dump worked because the originating request came from another IP address (srv01) than the one that we relayed to (srv02).

Attack 1B:Proxy Chaining the SMB Connection Using Responder and NTLM Relay

A twist to this approach is to utilize the SOCKS option in NTLM relay.

This is by far my favorite approach as it will give you a nice overview of successfully relayed attempts even if the user was not a local admin to the relayed machine. This gives you a much cleaner view of your operation than trying to sift through the NTLM relay logs as they happen, because even though I love NTLM relay, the logging is super-duper noisy.

Figure 11 - Everything is Better With SOCKS

This time, I modified my GPO on the domain controller so Spenser is allowed to log in. This way, you can see the full effect of the SOCKS proxy as now authentication as Spenser will succeed on both srv01 and srv02.

Figure 12 - We got Some Sessions!

As you can see, the SOCKS command will give a nice overview of which relays were successful, and the SOCKS option will keep the SMB connection open indefinitely for you. In this example, we can see that Spenser has admin rights on srv02 (10.10.10.55) but not on srv01 (10.10.10.69).

You can now use secretsdump.py to dump the SAM database or even use lsassy or another tool to start dumping LSASS.

Do not forget to change your SOCKS proxy configuration before going all bananas.

Figure 13 - Edit our SOCKS Configuration
Figure 14 - The Default SOCKS Config for ntlmrelayx.py is on Port 1080

After setting the proxy chains to the NTLM relay SOCKS proxy, we can now proxychain whichever tool we want and it will ignore the password value and use the relay credential instead.

Figure 15 - Dumping Hashes Over SOCKS

I should stress here that even if you are not local admin on the system, there could still be confidential files within your grasp if you have time to hunt for them. In this example, Spenser does not have local admin rights on srv01 but is able to access the finance share with confidential client data.

Figure 16 - We can Also Access File Shares!

Attack 2: Enumerating Over LDAP

This attack set up is very similarly to what we already used in prior attacks.

Figure 17- Setting up ntlmrelayx.py for LDAP This Time

However, domain controllers have SMB Signing enabled by default, so you can guess what happens next…

Figure 18 - Signature Please?

As we expected, we get a nice verbose error saying that the client requests signing, so it is not possible to invoke a relay like that. Does that mean we are stuck? Well, no 😊

We have two (2) options here:

  • WebDAV shenanigans
  • Mitm6

Attack 2A: WebDAV Shenanigans

SMB to LDAP is not an option because we have SMB signing problems, but what would happen if we use another protocol such as HTTP? In order for this attack to work, we will need to figure out if the webclient service is running in the environment.

By using hackanddo’s webclientservicescanner (needs valid domain credentials), we can figure out if this is the case. The webclientservicescanner is very easy to use—you basically provide the tool with valid credentials and it will reach out to all the computers in the domain over RPC to look for the \pipe\DAV RPC SERVICE.

Unfortunately, this service is usually not enabled by default.

Figure 19 - No Luck on the webclient Front

Enumerating this is nice but not really necessary. We can brute-force webclient connections if needed, as we will see soon.

Starting the webclient Service

These techniques only work if the webclient service is actually installed on the systems—they will not magically be installed by running the mentioned programs or browsing to the special files.

Thanks to James Foreshaw, we have a way to enable the webclient automatically through some low-level ETW shenanigans (this was later also ported to a C# version by Alessandro Magnosi).

There is also another approach we can take, which is playing with special files such as the Documents.searchConnector-ms file, as described by several researchers at MDSec.

The content of such a document looks as follows:

<?xml version="1.0" encoding="UTF-8"?> <searchConnectorDescription xmlns="http://schemas.microsoft.com/windows/2009/searchConnector"> <iconReference>imageres.dll,-1002</iconReference> <description>Microsoft Outlook</description> <isSearchOnlyItem>false</isSearchOnlyItem> <includeInStartMenuScope>true</includeInStartMenuScope> <iconReference>https://<strong><em>10.10.10.137</em></strong>/0001.ico</iconReference> <templateInfo> <folderType>{91475FE5-586B-4EBA-8D75-D17434B8CDF6}</folderType> </templateInfo> <simpleLocation> <url>https://<strong><em>www.trustedsec.com</em></strong>/</url> </simpleLocation> </searchConnectorDescription>

If we can drop this file somewhere and call it Documents.searchConnector-ms, we can forcefully start a webclient connection.
That finance share we were able to access from an unprivileged perspective starts to look pretty good now, doesn’t it? 😉

Let’s drop the file on the finance share and browse to it on our server. Look what it does to the webclient service in particular.

Figure 20 - Dropping the searchconnector in our Unprivileged Share
Figure 21 - srv02's webclient Suddenly Kicked off When Browsing to the Share

Magic! The webclient service has started on our server (srv02).

For our next step, how can we force an authentication over HTTP?

Something About a Hippopotamus and Printers

Lee Christensen published a way to coerce authentication over MS-RPRN RPC all the way back in 2018. This was later dubbed spoolsample or printerbug, as this relies on the spooler service to be running on the system.

In 2021, Lionel Gilles found a similar coerced authentication method, this time over the MS-EFSRPC (file encryption protocol), and this attack was dubbed PetitPotam.

The crazy thing about PetitPotam is that it worked from an unauthenticated perspective. This has since been patched, but it is not uncommon to come across the unpatched vulnerability every now and then.

Using these coercion methods, it is possible to trigger an authentication over HTTP to our attacker-controlled machine using our hostname@80/something as the target.

Figure 22 - Using the printerbug to Force Authentication
Figure 23 - Using PetitPotam to Force Authentication

For illustration purposes, I killed NTLM relay for a minute and enabled Responder's HTTP server again so we can clearly see what is happening.

Figure 24 - Drowning in Hashes

We see the hashes flying in! This means we can probably relay to LDAP, so let’s give it a go, shall we?

Figure 25 - Enumerating the Domain Thanks to Dirk-jan Mollema

We were successful in enumerating the domain information! However, since printerbug and PetitPotam both needed authentication to work, we could have just used a tool like ldapdomaindump to directly bind to LDAP ourselves and dump the data directly.
Is there a easier way to achieve the same result, preferably unauthenticated? Let’s find out…

Attack 2B: mitm6

2018 was a very nice year for the offensive community, as Dirk-jan Mollema published research about IPv6-based MitM attacks.
In modern Windows operating systems, IPv6 is enabled by default. This means that systems periodically poll for an IPv6 lease, as IPv6 is a newer protocol than IPv4, and Microsoft decided it was a good idea to give IPv6 precedence over IPv4.

However, in the vast majority of organizations, IPv6 is left unused, which means that an adversary could hijack the DHCP requests for IPv6 addresses and force authentication attempts to the attacker-controlled system. We do that by setting our system as the primary DNS server.

https://dirkjanm.io/worst-of-both-worlds-ntlm-relaying-and-kerberos-delegation/

First, we launch mitm6 and spoof any requests for internal resources.

Figure 26 - Let's do Some IPv6 Shenanigans

When a user attempts to browse to an internal resource, they will be presented with login prompt.

Figure 27 - Just an Innocent Login Prompt

If the user fills in their credentials, pat yourself on the back and grab a beer because you successfully relayed to LDAP from an unauthenticated standpoint.

Figure 28 - From Unauthenticated to Authenticated Domain Enumeration

Attack 3: Fun With LDAP’s 'Secure' Counterpart, LDAPS!

In last attack scenario, we used the LDAP protocol to dump the Active Directory objects, but we still do not have a real foothold, do we? Let's change that by relaying to LDAPS instead.

Using LDAP’s 'secure' twin, we are able to add a new computer account by abusing the fact that, by default, users are allowed to domain-join up to 10 new computer objects. This can be changed but often is not the case

Let’s set up NTLM relay to target LDAPS and see if we can find someone helpful enough to add our trustedcomputer01 to the domain for us.

Note: When possible, use the FQDN instead of the IP address. The IP address works most of the time, but FQDN looks cleaner and avoids SNI certificate conflicts.

Figure 29 - LDAP was Fun, but LDAPS is Cooler

As with the previous attack, use mitm6 or PetitPotam/printerbug targeting a system that has the webclient service running. Or, if you are bold enough, just spray and pray PetitPotam/printerbug to all domain computers.

After some time letting mitm6 run, we get a successful relay

Figure 30 - New Computer Added

We get a new computer added, thanks to our dear friend srv02 😊!
Now we can use this computer to do authenticated stuff in the domain, like using PetitPotam/printerbug or even BloodHound/kerberoasting…

Attack 4:Resource Based Constrained Delegation anyone?

For those of you who are unaware of what resource-based constrained delegation is, I recommend reading the excellent blog post from SpecterOps here:

https://posts.specterops.io/kerberosity-killed-the-domain-an-offensive-kerberos-overview-eb04b1402c61

It basically boils down to configuring certain systems in Active Directory to be allowed to request Kerberos tickets on behalf of other users. By setting the msDS-AllowedToActOnBehalfOfOtherIdentity attribute, we are indicating that we trust any authentication that originates from the value in the attribute. For example, if SRV02 has msDS-AllowedToActOnBehalfOfOtherIdentity set to srv01, this means that srv02 trusts authentications coming from srv01. What you might find interesting is that a computer account is able to set this property on itself.

Essentially, this means if we are able to get an NTLM relay working from a computer account and delegate it to LDAPS, we can set the msDS-AllowedToActOnBehalfOfOtherIdentity attribute to any arbitrary value. If we set it to a value of a computer that we created, we can set our newly created computer up for regular constrained delegation. This will make our new computer able to request service tickets for itself on behalf of any user in the domain (S4U2Self) and then forward it to the relayed computer (S4U2Proxy) because the relayed computer explicitly trusts our new computer due to the msDS-AllowedToActOnBehalfOfOtherIdentity attribute.

TL;DR If we can relay a computer account to LDAPS that is allowed to add additional computers to the domain, we can compromise the relayed computer by impersonating a domain admin on the relayed computer.

Let’s see this in action.

We are going to set up ntlmrelayx.py to LDAPS, but this time we are going to use the –delegate-access flag.

Figure 31 - Resource-Based Constrained Delegation With a Touch of Relaying

This time, we will use PetitPotam with our previously created computer account just for fun.

Figure 32 - Another PetitPotam Authentication

And if we now look to NTLM relay we can see that we added a new computer and granted it delegation rights towards SRV01$

Figure 33 - What a Killchain! Resource-Based Constrained Delegation Success!

We can now use getST.py to get a service ticket for the CIFS service for SRV01$, which will allow us to use the ticket in combination with secretsdump to dump SAM.

Figure 34 - Compromising the Server With Resource-Based Constrained Delegation

Attack 5: LDAP is Fun, Especially With Shadow Credentials

So far, this blog post has covered pretty well-known attack avenues. Let’s dive into the more novel stuff as a reward for reading through this massive post

This is an attack avenue that is relatively novel, as I have not seen many people discuss this attack vector before. Quite recently, Impacket received a pull request (https://github.com/ShutdownRepo/impacket/tree/shadowcredentials) from shutdownrepo and nodauf, who figured out that we can use NTLM relay for shadow credentials, allowing us to compromise the computer or user.. If you are unfamiliar with what shadow credentials are, I highly recommend reading the blog post of Elad Shamir, as he is the discoverer of this beautiful 'feature':

https://posts.specterops.io/shadow-credentials-abusing-key-trust-account-mapping-for-takeover-8ee1a53566ab

From the post above:

Tl;dr
It is possible to add “Key Credentials” to the attribute msDS-KeyCredentialLink of the target user/computer object and then perform Kerberos authentication as that account using PKINIT.

What do we need for this attack?

  • The functional level of the domain needs to be Server 2016 or above (I hope this is the case for the vast majority of your clients, otherwise they probably have bigger issues).
  • Active Directory Certificate Services (ADCS) need to be enabled in the domain, and the domain controller needs to have a digital certificate for service authentication installed.

We can enumerate if there is a certificate authority using Certipy:

Figure 35 - Enumerating Templates

We can see that there is a certificate authority present in the domain, and it is in fact our domain controller. We also know that the domain controller is up to date thanks to our CrackMapExec reconnaissance earlier. This means chances are pretty good that our shadow credential attack will work fine.

Now it's time to test the shadow credential relaying attack. I recommend setting up a virtualenv and installing the patched Impacket in the venv instead of overriding the production Impacket.

Figure 36 - Relaying With Shadow Credentials Thanks to nodauf

Let’s go wild and trigger an authentication from our dear server with webclient enabled.

Figure 37 - We Like PetitPotam, but mitm6 and spoolsample Also Work

Note: We can also use mitm6 or any other coerced authentication mechanism that triggers an HTTP connection.

Let’s check our NTLM relay.

Figure 38 - compromising the server through shdadow credentials

We can now use PKINIT tools as instructed to obtain a TGT for the server, and we could even go further and UnPAC-the-hash to retrieve the NTLM password.

Figure 39 - Some Dirk-jan Mollema Magic to Reveal the NT Hash

Attack 6: ESC8 for the Win

When there is a certificate authority in the domain that has the web enrollment feature enabled, it is possible to perform NTLM relaying to the HTTP endpoint to obtain a certificate.

Since we already know there is a certificate authority present, let’s try to relay to it.

Figure 40 - Time for Certificate Abuse

The fun part about the certificate authority being available over plain HTTP is that it does not matter which protocol is being used to relay, it will always work. SMB or HTTP does not matter at this point.

This time I relayed just with Responder, but printerbug, PetitPotam, or mitm6 will all do nicely

Figure 41 - If You See This Massive base64 Blob, it is Time to Party, as we can compromise the user/computer

After we have obtained the certificate, we can use it to get a TGT and even the NT hash via UnPAC-the-hash using pkinittools from Dirk-jan Mollema:

Figure 42 - Getting a TGT With the Certificate
Figure 43 - Extracting the NT Hash From the TGT Using the AS-REP Key

Conclusions

The moral of the story is broadcast protocols and coerced authentication can lead to disastrous consequences. If possible, please, please disable them in your environment and make sure to keep your tier 0 (or any other tier for that matter) up to date with the latest patches.

I hope this blog post has opened the eyes of  both offensive and defensive security practitioners worldwide so they can realize that NTLM relaying has much, much more to offer than just simply relaying to dump the SAM database.

Shoutouts

To close off this blogpost, I want to give some shoutouts to the excellent researchers that have contributed towards the tooling that make these attack primitives easy for us to execute:

Special shoutout to Justin Bollinger for reviewing this massive document!

And probably countless others that I forgot to mention.

This concludes the (somewhat lengthy) NTLM relay blog post, I hope this information will be useful to you! 😊

References

https://gist.github.com/gladiatx0r/1ffe59031d42c08603a3bde0ff678feb

https://www.tiraniddo.dev/2015/03/starting-webclient-service.html

https://twitter.com/tifkin_/status/1419806476353298442?s=20

https://gist.github.com/klezVirus/af004842a73779e1d03d47e041115797

https://www.tiraniddo.dev/2015/03/starting-webclient-service.html