This Series

As a reminder, this is a two part blog post where I will be covering pass the hash attacks and different ways they can be used during a penetration test. Because this is such a big topic, I want to narrow it down a bit:

  • I primarily want to focus on what works now, on patched systems, in primarily the default state (no Windows 7, no special firewall rules, etc.), but will make one exception to that which I’ll point out
  • I want to focus on practical uses. These will be uses that I’ve applied in a penetration test before, not something that just looks flashy
  • At first I will be covering the basics, but I also want to share a specific technique that took me a while to discover and I hope speeds up that process for someone else

Part 1 - The first blog post was about what pass the hash is and techniques that are commonly used during penetration tests

Part 2 - This post will focus on what I would consider to be an intermediate level technique that I’ve found useful during my penetration tests as well as some of the limitations I’ve encountered

As always, I’m writing beginners here, so I won’t be diving too deep into the concepts covered here. The idea is to talk about techniques that are used today and show how they work. I hope you’re able to get some value from this series. As always, I’d love to discuss it with you on Discord or Twitter!

Pass The Hash To Remote Desktop?

This is one of the tricks that inspired me to make this blog post. I have seen some guides out there, but they didn’t surface as readily as blogs about passing the hash with CrackMapExec or secretsdump. I think this technique can be just as useful though, depending on the situation.

If you want to use Remote Desktop with a pass the hash attack, you can use xfreerdp, which I’ll cover shortly, but you may run into the issue I did when I first started penetration testing. At first I thought this was just a dead end, but I was able to find a way around it by reading research from other penetration testers and I wanted to share that here in the hopes of helping someone else like me.

Using XFreeRDP

If you want to connect to a host using pass the hash, you can do that using xfreerdp and the NT portion of the hash. Unlike the the Impacket tools or CrackMapExec, xfreerdp does not want the colon between the LM and NT hash or the LM hash itself. When you connect to a host for the first time, you’ll need to accept the certificate as well.

xfreerdp /pth:[NT HASH] /v:[TARGET IP/HOSTNAME] /u:[USERNAME]

In our lab this looks like below. screenshot

However, if you’re running a default install of Windows, you’ll get the following error on the screen: Account restrictions are preventing this user from signing in. For example: blank passwords aren’t allowed, sign-in times are limited, or a policy restriction has been enforced.

The look of this screen varies by OS version, but this is how it appears on Windows 11. screenshot

As I mentioned previously, I had originally thought this was a dead end, but one day I dug into it a lot deeper and I was able to find out that there is a method that allows me to connect via RDP using a pass the hash attack. Funny enough, the route to configure the device to allow pass the hash for remote desktop is… a pass the hash attack.

Modifying The Registry

The protection we’re running into here is called RestrictedAdmin mode and is applied using either the policy or registry. The key point here is that the registry overrides the policy configuration, and we can modify that using a pass the hash attack to allow a pass the hash attack regardless of what is set via the policy or registry. The key is located in HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Lsa under the name DisableRestrictedAdmin.

We can query that value using Impacket’s Reg tool, which basically works the same as the reg command in Windows Command Prompt. If you query this on a default host that’s been joined to a basic Active Directory domain with little to no configuration, you’ll note that there is no entry in the registry for this value. When I’m doing penetration tests, it’s important for me to know the current configuration to be able to put it back when I’m done and not leave the customer in a less secure state. If the value is already set, we can just override it and put it back to the old value when we’re done rather than delete the entry.

impacket-reg [USERNAME]@[TARGET IP/HOSTNAME] -hashes [NTLM HASH] query -keyName HKLM\\SYSTEM\\CurrentControlSet\\Control\\LSA -v DisableRestrictedAdmin

Here’s how that looks in the lab. Notice how on this host there was no entry found. So here we know our previously attempted connection was prevented by policy, but we know we can override that. screenshot

The command below can be used to make the new registry entry we need.

impacket-reg [USERNAME]@[TARGET IP/HOSTNAME] -hashes [NTLM HASH] add -keyName HKLM\\SYSTEM\\CurrentControlSet\\Control\\LSA -v DisableRestrictedAdmin -vt REG_DWORD -vd 0

Here’s that addition in the lab. screenshot

I will always validate this change took place successfully by querying the value again. The output has changed since the last time we tried it, because the key now exists. screenshot

We’re now ready to try a remote desktop connection again, but this time, we’ve used a pass the hash attack to circumvent the protections Microsoft put in place to prevent a pass the hash attack to remote desktop. Once again, we never have to know the user’s password to get to this point, which I think adds a ton of power and really shows that a strong password (although important) can’t be the only security measure in place.

Back to XFreeRDP

Now when we use xfreerdp we get to the desktop as we’d expect! We’re already in a local administrative session, so we could plant a beacon or perform a session takeover for a logged in domain user that has permissions we’re interested in, the possibilities are much greater than our previous access, which makes this a powerful technique to use in the field. screenshot

Limitations

As with any attack, there are limitations you can run into when trying this in the real world. Unlike many other attacks, as long as you’re not executing commands directly on the host, it’s fairly hard to get caught by standard AV when doing a pass the hash attack. However, one of the big limitations I run into in the real world is UAC token filtering. This blog post isn’t focused on the details of Windows and how it protects itself, so in summary: UAC token filtering can be used to restrict the privileges of the remote session, effectively removing the administrative access token from the session’s access token. This means that any actions performed by the remote session will be limited to the permissions granted to the standard user account, rather than the full administrative privileges of the local administrator. Essentially, when you make a connection to a remote host with local administrative permissions, if the UAC token filtering is enabled and that user is not excluded from the protection, you will only be allowed to perform non-administrative actions.

If you want to read more about it, you can check out Microsoft’s documentation.

I want to show what that looks like in the real world. So let’s imagine a slightly different scenario. Let’s say that we have obtained a SAM dump from a host, maybe by using something like NTLMRelayX (which I won’t go into here), which provides us with the local user’s and their password hashes.

If the default administrator account is present and enabled, we can use that for any actions without worrying about UAC token filtering because it is not applied to this user by default. However, any non-default account does have this protection applied. If the default administrator account is disabled and the user created locally administrative accounts have not been made exempt from UAC token filtering, then we won’t be able to execute administrative commands with that user. We could still try to crack the password, but it severely decreases the value of the hash itself.

Let’s take a look at an example to show what I mean. Here we see a SAM dump and I will be focusing on two users:

  • Administrator - This is the built-in administrator account. Even if it was renamed, we could identify it by the RID of 500.
  • localadmin - This is a user created account, evident by the fact that it’s RID is above 999. This is a locally administrative user, but has UAC token filtering applied by default. screenshot Please ignore the fact that the hashes are the same for those users. All of my lab users have the same password to make things easy, but in the real world, these users would likely have different passwords.

Let’s imagine that the administrator account has been disabled by an organization to better harden their systems. Let’s try to use the localadmin users.

First, because this is a lab and we have visibility into everything, let’s confirm that localadmin is part of the administrators group. screenshot

Now that we’ve confirmed they are administrative, let’s try to use their permissions. CrackMapExec is a great way to check user permissions, so we’ll use that. We’d expect to see [+] if the user credentials are valid and (Pwn3d!) if the user is administrative over this host, just like we saw in the output earlier using CrackMapExec when we obtained the SAM or LSASS contents. But here, we see we only get a [+]. This is due to UAC token filtering. screenshot

There are ways to disable UAC token filtering, but they require having access to the host, which we don’t in this scenario. We only have a hash and don’t have the ability to use the administrative permissions. Like the RestrictedAdmin protections, there may be a workaround out there, but currently I’m not aware of any. It might be that someone has figured this out already, and if so, I’d love to find out and edit this blog post to point to the answer. Please feel free to message me on Twitter or Discord to let me know!

Conclusion

There are other ways to use a pass the hash attack, and I’ve barely touched on the subject, but (apart from NetNTLMv2 which I’ll get to another time) these are the primary methods I find successful during penetration tests. There are a lot of edge cases that can work as well, but it’s important to start basic and make adjustments as you learn more about the environment.

I hope this was useful to my readers and look forward to sharing other techniques I use on penetration tests in my next posts. I’m sure that I’ll be learning new pass the hash techniques as well, there’s always so much out there, and I’ll be sure to post about it here to share my learning journey. As always, if you have any questions or corrections you can message me on Twitter or Discord!