A freshly installed Windows Server 2022 is not secure by default. Before connecting it to your network and deploying workloads, you need to configure networking, apply patches, harden the operating system, and enable proper auditing. Skipping these steps leaves your server vulnerable to lateral movement, privilege escalation, and data exfiltration. This guide walks you through the complete initial setup and security hardening process, following CIS Benchmark recommendations and Microsoft best practices.
Prerequisites
Before you begin, make sure you have:
- Windows Server 2022 installed (Standard or Datacenter edition)
- Administrator access to the server (local or via RDP)
- Network information: static IP address, subnet mask, default gateway, and DNS server addresses
- Internet connectivity for downloading updates and Defender definitions
- A backup plan — take a snapshot or checkpoint before making system-level changes
Tip: Prefer Server Core installation for production servers. It has a smaller attack surface, fewer updates, and less resource consumption compared to Desktop Experience.
Step 1: Configure Networking and Hostname
The first task on any new server is setting a proper hostname and static network configuration.
Rename the Server
# Check current name
hostname
# Rename and schedule a reboot
Rename-Computer -NewName "SRV-PROD-01" -Restart
Configure Static IP Address
# List network adapters
Get-NetAdapter
# Remove existing DHCP configuration
Remove-NetIPAddress -InterfaceAlias "Ethernet0" -Confirm:$false
Remove-NetRoute -InterfaceAlias "Ethernet0" -Confirm:$false
# Set static IP
New-NetIPAddress -InterfaceAlias "Ethernet0" `
-IPAddress "10.0.1.20" `
-PrefixLength 24 `
-DefaultGateway "10.0.1.1"
# Set DNS servers
Set-DnsClientServerAddress -InterfaceAlias "Ethernet0" `
-ServerAddresses "10.0.1.5", "10.0.1.6"
Configure the Time Zone
# List available time zones
Get-TimeZone -ListAvailable | Where-Object { $_.Id -like "*Eastern*" }
# Set time zone
Set-TimeZone -Id "Eastern Standard Time"
# Configure NTP source
w32tm /config /manualpeerlist:"time.windows.com" /syncfromflags:manual /reliable:YES /update
Restart-Service w32time
w32tm /resync /force
Step 2: Configure Windows Update
Keeping the server patched is the single most effective security measure you can take.
Install the PSWindowsUpdate Module
# Install NuGet provider if needed
Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force
# Install PSWindowsUpdate module
Install-Module -Name PSWindowsUpdate -Force -Confirm:$false
# Import the module
Import-Module PSWindowsUpdate
Check and Install Updates
# List available updates
Get-WindowsUpdate
# Install all available updates
Install-WindowsUpdate -AcceptAll -AutoReboot
# Check update history
Get-WUHistory | Select-Object -First 20 | Format-Table Date, Title, Result
Configure Automatic Updates via Registry
# Configure Windows Update for auto-download, notify before install
$WUPath = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU"
New-Item -Path $WUPath -Force | Out-Null
Set-ItemProperty -Path $WUPath -Name "NoAutoUpdate" -Value 0
Set-ItemProperty -Path $WUPath -Name "AUOptions" -Value 3 # Auto download, notify install
Set-ItemProperty -Path $WUPath -Name "ScheduledInstallDay" -Value 1 # Every Sunday
Set-ItemProperty -Path $WUPath -Name "ScheduledInstallTime" -Value 3 # 3 AM
Step 3: Enable and Configure Windows Defender
Windows Server 2022 includes Windows Defender Antivirus. On Server Core, it runs without a GUI but is fully functional via PowerShell.
Verify Defender Status
# Check Defender status
Get-MpComputerStatus | Select-Object AntivirusEnabled, RealTimeProtectionEnabled,
IoavProtectionEnabled, AntispywareEnabled, AntivirusSignatureLastUpdated
# Update definitions
Update-MpSignature
Configure Real-Time Protection
# Enable all protection features
Set-MpPreference -DisableRealtimeMonitoring $false
Set-MpPreference -MAPSReporting Advanced
Set-MpPreference -SubmitSamplesConsent SendAllSamples
Set-MpPreference -DisableBlockAtFirstSeen $false
# Enable network protection
Set-MpPreference -EnableNetworkProtection Enabled
# Enable controlled folder access (ransomware protection)
Set-MpPreference -EnableControlledFolderAccess Enabled
Configure Exclusions for Application Paths
# Add exclusions for known application paths (adjust for your environment)
Add-MpPreference -ExclusionPath "D:\SQLData"
Add-MpPreference -ExclusionPath "D:\SQLLogs"
Add-MpPreference -ExclusionProcess "sqlservr.exe"
# Verify exclusions
Get-MpPreference | Select-Object -ExpandProperty ExclusionPath
Warning: Only add exclusions for trusted application paths. Each exclusion creates a blind spot for the antivirus engine. Never exclude temp directories or user-writable paths.
Step 4: Configure Windows Firewall
The Windows Firewall should be enabled on all profiles. The principle is simple: block everything inbound by default, then allow only the ports your services require.
Enable All Firewall Profiles
# Enable firewall on all profiles
Set-NetFirewallProfile -Profile Domain,Public,Private -Enabled True
# Set default actions: block inbound, allow outbound
Set-NetFirewallProfile -Profile Domain,Public,Private `
-DefaultInboundAction Block `
-DefaultOutboundAction Allow
# Enable firewall logging
Set-NetFirewallProfile -Profile Domain,Public,Private `
-LogAllowed True `
-LogBlocked True `
-LogFileName "%systemroot%\system32\LogFiles\Firewall\pfirewall.log" `
-LogMaxSizeKilobytes 16384
Create Specific Allow Rules
# Allow RDP only from management subnet
New-NetFirewallRule -DisplayName "RDP - Management Only" `
-Direction Inbound -Protocol TCP -LocalPort 3389 `
-RemoteAddress "10.0.100.0/24" -Action Allow
# Allow WinRM (for remote management)
New-NetFirewallRule -DisplayName "WinRM HTTPS" `
-Direction Inbound -Protocol TCP -LocalPort 5986 `
-RemoteAddress "10.0.100.0/24" -Action Allow
# Allow ICMP (ping) from internal network
New-NetFirewallRule -DisplayName "ICMP Allow Internal" `
-Direction Inbound -Protocol ICMPv4 `
-RemoteAddress "10.0.0.0/8" -Action Allow
Review and Clean Up Default Rules
# List all enabled inbound rules
Get-NetFirewallRule -Direction Inbound -Enabled True |
Format-Table DisplayName, Profile, Action
# Disable rules you don't need (example: disable built-in file sharing)
Disable-NetFirewallRule -DisplayGroup "File and Printer Sharing"
Step 5: Disable Legacy Protocols and Enforce TLS 1.3
Windows Server 2022 is the first Windows Server release with native TLS 1.3 support. You should disable all older protocol versions.
Disable SSL 2.0, SSL 3.0, TLS 1.0, and TLS 1.1
# Function to disable a protocol
function Disable-Protocol {
param([string]$Protocol)
$basePath = "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\$Protocol"
foreach ($side in @("Server", "Client")) {
$path = "$basePath\$side"
New-Item -Path $path -Force | Out-Null
Set-ItemProperty -Path $path -Name "Enabled" -Value 0 -Type DWord
Set-ItemProperty -Path $path -Name "DisabledByDefault" -Value 1 -Type DWord
}
Write-Host "Disabled $Protocol" -ForegroundColor Yellow
}
# Disable legacy protocols
Disable-Protocol -Protocol "SSL 2.0"
Disable-Protocol -Protocol "SSL 3.0"
Disable-Protocol -Protocol "TLS 1.0"
Disable-Protocol -Protocol "TLS 1.1"
Verify TLS 1.3 Is Enabled
# Check TLS 1.3 registry (enabled by default on Server 2022)
$tls13Path = "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.3\Server"
if (Test-Path $tls13Path) {
Get-ItemProperty -Path $tls13Path
} else {
Write-Host "TLS 1.3 is using default settings (enabled)" -ForegroundColor Green
}
Disable Weak Cipher Suites
# Disable weak ciphers
$weakCiphers = @("RC4 128/128", "RC4 64/128", "RC4 56/128", "DES 56/56", "Triple DES 168")
foreach ($cipher in $weakCiphers) {
$path = "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Ciphers\$cipher"
New-Item -Path $path -Force | Out-Null
Set-ItemProperty -Path $path -Name "Enabled" -Value 0 -Type DWord
}
# Set strong cipher suite order
$cipherOrder = @(
"TLS_AES_256_GCM_SHA384",
"TLS_AES_128_GCM_SHA256",
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"
) -join ","
Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Cryptography\Configuration\SSL\00010002" `
-Name "Functions" -Value $cipherOrder
Step 6: Account Security and Password Policies
Rename the Built-in Administrator Account
# Rename the default Administrator account (CIS recommendation)
Rename-LocalUser -Name "Administrator" -NewName "SrvLocalAdmin"
# Disable the Guest account
Disable-LocalUser -Name "Guest"
Configure Password and Lockout Policies
# Set password policy via net accounts
net accounts /minpwlen:14 /maxpwage:60 /minpwage:1 /uniquepw:24
# Set account lockout policy
net accounts /lockoutthreshold:5 /lockoutduration:30 /lockoutwindow:30
Restrict Remote Desktop Access
# Only allow specific group for RDP access
$rdpGroup = "Remote Desktop Users"
Remove-LocalGroupMember -Group $rdpGroup -Member "Everyone" -ErrorAction SilentlyContinue
# Add only authorized users
Add-LocalGroupMember -Group $rdpGroup -Member "DOMAIN\RDP-Admins"
# Enable NLA (Network Level Authentication) for RDP
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp" `
-Name "UserAuthentication" -Value 1
Step 7: Configure Audit Policies and Logging
Proper auditing is essential for detecting intrusions and satisfying compliance requirements.
Enable Advanced Audit Policies
# Account Logon events
auditpol /set /subcategory:"Credential Validation" /success:enable /failure:enable
auditpol /set /subcategory:"Kerberos Authentication Service" /success:enable /failure:enable
# Logon/Logoff events
auditpol /set /subcategory:"Logon" /success:enable /failure:enable
auditpol /set /subcategory:"Logoff" /success:enable
auditpol /set /subcategory:"Special Logon" /success:enable
# Object Access
auditpol /set /subcategory:"File System" /success:enable /failure:enable
auditpol /set /subcategory:"Registry" /success:enable /failure:enable
# Policy Changes
auditpol /set /subcategory:"Audit Policy Change" /success:enable /failure:enable
auditpol /set /subcategory:"Authentication Policy Change" /success:enable
# Privilege Use
auditpol /set /subcategory:"Sensitive Privilege Use" /success:enable /failure:enable
# System events
auditpol /set /subcategory:"Security State Change" /success:enable /failure:enable
auditpol /set /subcategory:"Security System Extension" /success:enable /failure:enable
Configure Event Log Sizes
# Increase Security log to 1 GB
wevtutil sl Security /ms:1073741824
# Increase System log to 256 MB
wevtutil sl System /ms:268435456
# Increase Application log to 256 MB
wevtutil sl Application /ms:268435456
# Set retention to auto-archive
wevtutil sl Security /rt:false /ab:true
Verify Audit Configuration
# Display all audit policies
auditpol /get /category:*
# Check recent security events
Get-WinEvent -LogName Security -MaxEvents 10 |
Format-Table TimeCreated, Id, Message -Wrap
Step 8: Disable Unnecessary Services
Reducing the number of running services shrinks the attack surface.
# Services commonly disabled on hardened servers
$servicesToDisable = @(
"XblAuthManager", # Xbox Live Auth Manager
"XblGameSave", # Xbox Live Game Save
"WSearch", # Windows Search (unless needed)
"MapsBroker", # Downloaded Maps Manager
"lfsvc", # Geolocation Service
"SharedAccess", # Internet Connection Sharing
"WMPNetworkSvc", # Windows Media Player Network Sharing
"Browser" # Computer Browser
)
foreach ($svc in $servicesToDisable) {
$service = Get-Service -Name $svc -ErrorAction SilentlyContinue
if ($service) {
Stop-Service -Name $svc -Force -ErrorAction SilentlyContinue
Set-Service -Name $svc -StartupType Disabled
Write-Host "Disabled: $svc" -ForegroundColor Yellow
}
}
Step 9: Additional CIS Benchmark Hardening
Disable SMBv1
# Disable SMBv1 (critical — used by WannaCry and similar malware)
Disable-WindowsOptionalFeature -Online -FeatureName SMB1Protocol -NoRestart
Set-SmbServerConfiguration -EnableSMB1Protocol $false -Force
Enable Credential Guard
# Enable Virtualization-Based Security and Credential Guard
$regPath = "HKLM:\SYSTEM\CurrentControlSet\Control\DeviceGuard"
Set-ItemProperty -Path $regPath -Name "EnableVirtualizationBasedSecurity" -Value 1
Set-ItemProperty -Path $regPath -Name "RequirePlatformSecurityFeatures" -Value 3
$credGuardPath = "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa"
Set-ItemProperty -Path $credGuardPath -Name "LsaCfgFlags" -Value 1
Restrict PowerShell Execution
# Enable PowerShell script block logging
$psLogPath = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging"
New-Item -Path $psLogPath -Force | Out-Null
Set-ItemProperty -Path $psLogPath -Name "EnableScriptBlockLogging" -Value 1
# Enable PowerShell module logging
$psModLogPath = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ModuleLogging"
New-Item -Path $psModLogPath -Force | Out-Null
Set-ItemProperty -Path $psModLogPath -Name "EnableModuleLogging" -Value 1
# Set execution policy to RemoteSigned
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope LocalMachine -Force
Disable Anonymous Access
# Restrict anonymous enumeration of SAM accounts and shares
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa" `
-Name "RestrictAnonymousSAM" -Value 1
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa" `
-Name "RestrictAnonymous" -Value 1
# Disable null session pipes
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters" `
-Name "NullSessionPipes" -Value @() -Type MultiString
Troubleshooting
Common Issues After Hardening
Locked out after renaming Administrator: If you lose access after renaming the built-in Administrator account, boot into Safe Mode or use a Windows Recovery Environment. The renamed account still has the same SID and permissions.
RDP stops working after firewall changes: Always create your RDP allow rule before setting the default inbound action to Block. If locked out, use the server console (iLO, iDRAC, VMware Console) to fix the firewall:
# Emergency: temporarily disable firewall via console
Set-NetFirewallProfile -Profile Domain,Public,Private -Enabled False
# Fix your rules, then re-enable
Applications break after TLS hardening: Some legacy applications require TLS 1.0/1.1. Test thoroughly in a staging environment before deploying. If needed, you can selectively re-enable a protocol for a specific application rather than system-wide.
Event log flooding after enabling audits: If your Security event log fills up quickly, review which subcategories generate the most events. File System auditing on busy file servers can generate enormous volumes. Consider using a SIEM to collect logs remotely with appropriate filtering.
Verification Checklist
Run this script to verify your hardening configuration:
Write-Host "=== Security Hardening Verification ===" -ForegroundColor Cyan
# Check hostname
Write-Host "`nHostname: $(hostname)"
# Check firewall status
Get-NetFirewallProfile | Format-Table Name, Enabled, DefaultInboundAction
# Check Defender status
$defender = Get-MpComputerStatus
Write-Host "Defender Real-Time Protection: $($defender.RealTimeProtectionEnabled)"
Write-Host "Defender Signatures Updated: $($defender.AntivirusSignatureLastUpdated)"
# Check SMBv1
$smb1 = Get-SmbServerConfiguration | Select-Object -ExpandProperty EnableSMB1Protocol
Write-Host "SMBv1 Disabled: $(-not $smb1)"
# Check audit policies
Write-Host "`nAudit Policies:"
auditpol /get /category:"Logon/Logoff"
# Check disabled legacy protocols
$protocols = @("SSL 2.0", "SSL 3.0", "TLS 1.0", "TLS 1.1")
foreach ($proto in $protocols) {
$path = "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\$proto\Server"
if (Test-Path $path) {
$enabled = (Get-ItemProperty -Path $path).Enabled
Write-Host "$proto Disabled: $($enabled -eq 0)"
}
}
Summary
Hardening Windows Server 2022 is not a one-time activity but a foundational practice that must happen before deploying any workload. In this guide, you configured static networking, applied Windows Updates, enabled and tuned Windows Defender, locked down the firewall to allow only necessary traffic, disabled legacy TLS/SSL protocols in favor of TLS 1.3, hardened account policies, and enabled comprehensive auditing. These steps align with CIS Benchmark Level 1 recommendations and significantly reduce your server’s attack surface. From here, continue with role-specific hardening (IIS, SQL Server, Active Directory) and integrate your event logs into a centralized SIEM for ongoing monitoring.