Audit your RDP logins with one line of PowerShell

If you run an RDS/terminal server (or even just a workstation with RDP enabled) that’s exposed to the internet through default port 3389, there’s a good chance it’s been visited by a port-scanning, bruteforcing bot at some stage. Hopefully all of your users had strong passwords and withstood the attack, or perhaps not. One way to quickly check all IPs that have successfully logged on to the box is to run this PowerShell command:

Get-WinEvent 'Microsoft-Windows-TerminalServices-LocalSessionManager/Operational' | Select -ExpandProperty Properties | Where-Object {$_.Value -like '*.*.*.*'} | Sort-Object -Property Value -Unique

Since you probably haven’t memorised all legitimate IPs that should be logging in, copying and pasting the results into a bulk IP-to-country tool like this one can quickly reveal any red flags. If you see any IPs from foreign countries—and you’re not expecting foreign countries to be logging in—this could be an indication you’ve been owned. Take a closer look through Event Viewer to see which users were compromised. If you look in their user folder chances are you’ll find something untoward such as a mass mailer. BrowsingHistoryView is also a useful tool to figure out the intentions of your attacker. I’ve even seen a hacked RDS servers used to register AWS accounts.

How can you prevent future breaches?

  • Needless to say, immediately change the password of the compromised user(s).
  • Enforce strong passwords through Group Policy: 8-10 characters minimum length and enable the option Password must meet complexity requirements. Note that this doesn’t guarantee good quality passwords. Users should be educated on examples of good and bad passwords.
  • Turn on Network Level Authentication. This is the “more secure” option in remote settings. Why? In some cases, an attacker could find usernames to bruteforce by connecting to your server with a non-NLA RDP client and getting an image of your logon screen with all users currently logged on.
  • If viable, firewall RDP connections off only to IPs or countries that need to connect.
  • Consider changing your RDP port to something non-standard such as 23389. Bots are a lot less likely to discover a server with an exotic port number. Yes, this is security through obscurity but automated attacks will be drastically reduced.
  • Make users connect via a VPN rather than port forwarding RDP.

Changing Windows RDP port the right way

If your router doesn’t allow you to specify different internal and external ports when setting up port forwarding for remote desktop, you may need to change the listening port. You can do this the old-fashioned way by modifying the registry, adding a firewall exception and restarting the appropriate services like so:

reg add "HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp" /v PortNumber /t REG_DWORD /d 3390 /f
netsh advfirewall firewall add rule name="Remote Desktop (TCP 3390)" protocol=tcp dir=in localport=3390 action=allow
net stop termservice /y && net start termservice

Or you could do it the simpler, less-likely-to-break-things way:

netsh interface portproxy add v4tov4 listenport=3390 connectport=3389 connectaddress=192.168.1.100
netsh advfirewall firewall add rule name="Remote Desktop (TCP 3390)" protocol=tcp dir=in localport=3390 action=allow

Where 192.168.1.100 is the computer’s actual IP address and 3390 is your desired port. connectaddress can also be the name of the computer, but not localhost or 127.0.0.1. And yes, this setting will persist across reboots.

This is a much more graceful solution than modifying the service’s listening port because RDP is now available on both the standard port 3389 and 3390, and will allow computers on the network to continue connecting using just the computer name or IP without having to specify your new exotic port number.