Who logged into this server, when, and from where? Were there failed RDP attempts overnight? Which account got locked out? Windows records all of this in the Security event log, as long as auditing is enabled. Here’s how to turn it on, which event IDs matter, and how to query them quickly with PowerShell.
1. Make sure auditing is enabled
Check the current audit policy:
auditpol /get /category:"Logon/Logoff"
auditpol /get /category:"Account Logon"
Enable success and failure auditing for logons:
auditpol /set /subcategory:"Logon" /success:enable /failure:enable
auditpol /set /subcategory:"Logoff" /success:enable
auditpol /set /subcategory:"Account Lockout" /success:enable /failure:enable
auditpol /set /subcategory:"Special Logon" /success:enable
auditpol /set /subcategory:"Credential Validation" /success:enable /failure:enable
On domain-joined servers, configure this through Group Policy (Advanced Audit Policy Configuration) instead, so local changes aren’t overwritten.
Increase the Security log size, or older events disappear quickly on busy servers:
wevtutil sl Security /ms:1073741824 # 1 GB
2. Event IDs that matter
| Event ID | Meaning |
|---|---|
| 4624 | Successful logon |
| 4625 | Failed logon |
| 4634 / 4647 | Logoff / user-initiated logoff |
| 4648 | Logon with explicit credentials (runas, mapped drives) |
| 4672 | Special privileges assigned (admin logon) |
| 4740 | Account locked out |
| 4767 | Account unlocked |
| 4778 / 4779 | RDP session reconnected / disconnected |
| 4720 / 4722 / 4728 / 4732 | User created / enabled / added to a global or local group (e.g. Administrators) |
3. Logon types (in 4624 and 4625)
| Type | Meaning |
|---|---|
| 2 | Interactive (console, including the VNC console) |
| 3 | Network (file shares, some services) |
| 4 / 5 | Batch / service |
| 7 | Unlock |
| 10 | RemoteInteractive: RDP |
| 11 | Cached credentials |
RDP logons are type 10 (or type 3 first, with NLA). Watch type 10 successes and all failures.
4. Query with PowerShell
Recent successful RDP logons:
Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4624; StartTime=(Get-Date).AddDays(-7)} |
Where-Object { $_.Properties[8].Value -eq 10 } |
Select-Object TimeCreated,
@{n='User';e={$_.Properties[5].Value}},
@{n='SourceIP';e={$_.Properties[18].Value}} |
Format-Table -AutoSize
Failed logons, grouped by source IP (brute-force check):
Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4625; StartTime=(Get-Date).AddDays(-1)} |
ForEach-Object { $_.Properties[19].Value } |
Group-Object | Sort-Object Count -Descending | Select-Object -First 15 Count, Name
Account lockouts:
Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4740} -MaxEvents 20 |
Select-Object TimeCreated, @{n='User';e={$_.Properties[0].Value}}, @{n='From';e={$_.Properties[1].Value}}
Property positions are stable for these event IDs on current Windows Server versions. Check $_.Message if a field looks wrong.
Event Viewer works too: Windows Logs → Security → Filter Current Log → Event IDs 4624,4625.
5. What to look for
- Thousands of 4625 failures from many IPs: RDP is exposed to the internet and being brute-forced. Restrict it. See RDP brute-force protection.
- Successful type 10 logons from unknown IPs: possible compromise. Investigate immediately, change passwords, and check for new users (4720) and group changes (4732).
- Logons at unusual times for an account.
- Lockouts (4740) of admin accounts: attacks, or a service using an old password.
6. Get alerts
- Task Scheduler can trigger on an event: create a task “On an event” (Log: Security, Source: Microsoft-Windows-Security-Auditing, Event ID: 4740 or 4624), with an action that runs a PowerShell script to send an email or webhook.
- Forward logs to a central system: Windows Event Forwarding, or agents for Wazuh, Graylog, Elastic or Splunk. Local logs can be cleared by an attacker (which itself logs event 1102). See Wazuh.
Reduce what you need to watch
- Don’t expose RDP to the whole internet. Allow your IPs only, or use a VPN or an RD Gateway. See RD Gateway and change the RDP port.
- Rename or disable the built-in Administrator, use strong unique passwords, and set an account lockout policy.
Quick reference
| Task | Command / ID |
|---|---|
| Enable logon auditing | auditpol /set /subcategory:"Logon" /success:enable /failure:enable |
| Successful logon | 4624 (RDP = logon type 10) |
| Failed logon | 4625 |
| Lockout | 4740 |
| RDP reconnect / disconnect | 4778 / 4779 |
| Log cleared | 1102 |
| Query | Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4625} |
Related: Windows Firewall with PowerShell and ransomware protection.