RDP hardening with Group Policy means deciding exactly who may open a Remote Desktop session and what their token can do once they are inside. Most privilege escalation on a Windows server does not come from a missing patch — it comes from a standard user sitting in a group they should not be in, or holding a user right such as SeDebugPrivilege that lets them take over another process. This guide walks through auditing the current rights, tightening them with Local Group Policy or a domain GPO, and verifying the result without locking yourself out.
Before you start
You need:
- A Windows VPS or Admin RDP running Windows Server 2019, 2022 or 2025, reachable on RDP port 3389 (
203.0.113.10:3389). - An account in the local Administrators group, plus a second, non-admin account you can test with.
- A browser console session open in your VPS provider's control panel before you touch logon rights. If a policy change locks RDP out, the console is your way back in.
- If the server is domain-joined, edit the settings in a GPO linked to the OU holding the computer object. On a standalone server, use
gpedit.msc. The paths are the same; the local editor only affects one machine.
Warning: Changing Allow log on through Remote Desktop Services or Deny log on through Remote Desktop Services can end your own session on the next logon. Keep the console open and test with a second account before you sign out.
Audit the current logon rights and group membership
Start by recording what you have, so you can compare later.
net localgroup Administrators
net localgroup "Remote Desktop Users"
Get-LocalGroupMember -Group Administrators | Format-Table Name, PrincipalSourceThen look at the rights that matter for escalation:
whoami /priv
secedit /export /cfg C:\Temp\secpol-before.infOpen secpol-before.inf and note the lines starting with SeRemoteInteractiveLogonRight, SeDenyRemoteInteractiveLogonRight, SeDebugPrivilege, SeImpersonatePrivilege and SeTcbPrivilege. That file is your rollback reference.
Tip: whoami /priv shows only the privileges in your current token. Run it once as your admin account and once as the standard test account — the difference is the attack surface you are about to close.
Restrict who can log on through RDP
This is the single most effective RDP hardening step. By default, any member of Remote Desktop Users or Administrators can connect.
- Open
gpedit.msc(or the Group Policy Management Editor for a domain GPO). - Go to Computer Configuration > Windows Settings > Security Settings > Local Policies > User Rights Assignment.
- Open Allow log on through Remote Desktop Services (older builds call it Allow log on through Terminal Services).
- Remove Remote Desktop Users and Administrators if you want a dedicated group instead. Add a purpose-built group such as
RDP-Users, and keep a separateRDP-Adminsgroup for administrative sessions. - Open Deny log on through Remote Desktop Services and add
Guests, plus any service or backup accounts that should never open an interactive session.
Warning: If you remove Administrators from the allow list, administrators can no longer connect over RDP — only through the console. That is a valid jump-host design, but confirm you can still reach the server before you apply it.
Create the groups first so the policy has something to reference:
New-LocalGroup -Name "RDP-Users" -Description "Interactive RDP access"
New-LocalGroup -Name "RDP-Admins" -Description "Administrative RDP access"
Add-LocalGroupMember -Group "RDP-Users" -Member "deploy"Remove escalation paths from user rights
A standard user with the wrong user right can become SYSTEM. Review these in the same User Rights Assignment node:
- Debug programs (
SeDebugPrivilege) — should contain Administrators only. Any other entry lets a user attach a debugger to a privileged process and read its token. - Impersonate a client after authentication — Administrators and Service only.
- Replace a process level token — Administrators and Local Service only.
- Create a token object — Administrators only.
- Act as part of the operating system — Administrators only, and ideally empty.
- Take ownership of files or other objects — Administrators only.
- Load and unload device drivers — Administrators only.
Also tighten the local logon side, because a user who can log on at the console can often bypass RDP restrictions:
- Allow log on locally — Administrators and a small operations group.
- Deny log on locally — service accounts and any account used only for RDP.
- Allow log on through Remote Desktop Services — as configured above.
- Deny access to this computer from the network — Guests and any anonymous-capable account.
Note: SeImpersonatePrivilege is granted to service accounts by default and is required by IIS and SQL Server. Removing it from those accounts breaks them. Restrict it to the accounts that genuinely need it rather than clearing the list.
Harden UAC so standard users cannot elevate
Under Computer Configuration > Windows Settings > Security Settings > Local Policies > Security Options, set:
- User Account Control: Run all administrators in Admin Approval Mode — Enabled.
- User Account Control: Behavior of the elevation prompt for standard users — Automatically deny elevation requests. A standard RDP user then sees a refusal instead of a credential box.
- User Account Control: Behavior of the elevation prompt for administrators in Admin Approval Mode — Prompt for credentials on the secure desktop.
- User Account Control: Only elevate executables that are signed and validated — Enabled if your software is signed.
- Interactive logon: Do not display last user name — Enabled, so a session does not leak account names.
These settings stop the classic "borrow an admin password" escalation inside a session. Pair them with an account lockout policy against RDP password guessing so brute force cannot undo the work.
Lock down the Administrators group
Membership drift is how escalation happens six months later. Use Restricted Groups (under Security Settings > Restricted Groups) to declare the exact membership of Administrators and Remote Desktop Users. The policy removes anyone you did not list on the next refresh.
Warning: Restricted Groups is authoritative. If you list a group and forget a legitimate admin account, that account is removed at the next policy refresh. Test on one server first.
If you manage more than a couple of servers, move these settings into a proper domain GPO — see Advanced Windows Server: Implementing Group Policy Objects (GPO) for security.
Apply the policy
Force a refresh and confirm the settings landed:
gpupdate /force
gpresult /h C:\Temp\gpo-report.html
secedit /export /cfg C:\Temp\secpol-after.infOpen the HTML report and check that your settings appear under Computer Configuration > Windows Settings > Security Settings. Compare secpol-before.inf and secpol-after.inf to see exactly which rights changed.
Check it works
- Open a second RDP session as the standard test account (
deploy) to203.0.113.10:3389. - Run
whoami /privand confirm the dangerous privileges are gone. - Try to start an elevated process, for example
cmd.exewith Run as administrator. You should get an immediate refusal, not a credential prompt. - Run
net localgroup Administratorsand confirm only the accounts you listed are present. - Sign out and back in as your admin account to prove you still have access.
If the standard user can still elevate, the policy is not applying — check gpresult for a conflicting GPO with a higher precedence.
Troubleshooting
- You are locked out of RDP after applying the policy — you removed your own group from Allow log on through Remote Desktop Services. Reconnect through the browser console in your VPS provider's control panel, re-add the group, run
gpupdate /force. - A service or application stopped working — you stripped
SeImpersonatePrivilegeorSeServiceLogonRightfrom its service account. Restore the right for that account only. - Standard users still see a UAC credential prompt — the elevation prompt setting was applied to the wrong node, or a domain GPO overrides it. Check precedence in
gpresult /h. - Accounts you removed from Administrators reappear — a Restricted Groups policy or a startup script is re-adding them. Check both, and review scheduled tasks running as SYSTEM.
gpupdatereports success but nothing changed — the machine is in the wrong OU, or the GPO is not linked. Verify the link and rungpresult /rto see which GPOs applied.
Next steps
- Review the wider baseline in Securing Windows Server: Hardening the Registry and Services.
- Start with the basics if you are new to the editor: Local Group Policy Editor basics for a standalone server.
- Limit exposure at the network edge with Restrict RDP port 3389 to your own IP addresses.
