Windows Server Security Hardening: Comprehensive Protection Guide
Introduction
Security hardening is essential for protecting Windows Server infrastructure from threats. This guide covers implementing security baselines, configuring Windows Defender Advanced Threat Protection, firewall hardening, BitLocker encryption, Secure Boot, Credential Guard, AppLocker policies, auditing, and automated patch management.
Security Baselines
Microsoft Security Compliance Toolkit
# Download Security Compliance Toolkit from Microsoft
# https://www.microsoft.com/en-us/download/details.aspx?id=55319
# Extract baseline GPOs
$baselinePath = "C:\SecurityBaselines\Windows-Server-2022"
# Import baseline GPO
Import-GPO -BackupGpoName "MSFT Windows Server 2022 - Domain Security" `
-Path $baselinePath `
-TargetName "WS2022-Security-Baseline" `
-CreateIfNeeded
# Link to OU
New-GPLink -Name "WS2022-Security-Baseline" `
-Target "OU=Servers,DC=contoso,DC=com" `
-LinkEnabled Yes `
-Order 1
CIS Benchmarks
# Install CIS-CAT Lite (assessment tool)
# https://www.cisecurity.org/cybersecurity-tools/cis-cat-lite/
# Run CIS assessment
& "C:\CIS-CAT\Assessor-CLI.bat" `
-b "C:\CIS-CAT\benchmarks\CIS_Microsoft_Windows_Server_2022_Benchmark_v1.0.0-xccdf.xml" `
-D "C:\CIS-Reports\"
# Review HTML report for compliance gaps
Custom Security GPO
# Create custom security GPO
New-GPO -Name "Custom-Server-Hardening" -Comment "Custom security policies"
# Configure password policy
Set-GPRegistryValue -Name "Custom-Server-Hardening" `
-Key "HKLM\SYSTEM\CurrentControlSet\Control\Lsa" `
-ValueName "NoLMHash" `
-Type DWord `
-Value 1
# Disable SMBv1
Set-GPRegistryValue -Name "Custom-Server-Hardening" `
-Key "HKLM\SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters" `
-ValueName "SMB1" `
-Type DWord `
-Value 0
# Enable credential guard
Set-GPRegistryValue -Name "Custom-Server-Hardening" `
-Key "HKLM\SOFTWARE\Policies\Microsoft\Windows\DeviceGuard" `
-ValueName "EnableVirtualizationBasedSecurity" `
-Type DWord `
-Value 1
Set-GPRegistryValue -Name "Custom-Server-Hardening" `
-Key "HKLM\SOFTWARE\Policies\Microsoft\Windows\DeviceGuard" `
-ValueName "RequirePlatformSecurityFeatures" `
-Type DWord `
-Value 3 # Secure Boot and DMA Protection
Windows Defender Advanced Threat Protection
Installing and Configuring Defender ATP
# Check Windows Defender status
Get-MpComputerStatus
# Update definitions
Update-MpSignature
# Configure real-time protection
Set-MpPreference -DisableRealtimeMonitoring $false
Set-MpPreference -DisableBehaviorMonitoring $false
Set-MpPreference -DisableIOAVProtection $false
Set-MpPreference -DisableScriptScanning $false
# Enable cloud-delivered protection
Set-MpPreference -MAPSReporting Advanced
Set-MpPreference -SubmitSamplesConsent SendAllSamples
# Configure scanning
Set-MpPreference -ScanScheduleDay Everyday
Set-MpPreference -ScanScheduleTime 02:00
Set-MpPreference -SignatureScheduleDay Everyday
Set-MpPreference -SignatureScheduleTime 01:00
# Onboard to Microsoft Defender for Endpoint (requires subscription)
# Download onboarding package from Microsoft 365 Defender portal
# Run onboarding script
& "C:\Onboarding\WindowsDefenderATPOnboardingScript.cmd"
Defender Exclusions (Use Sparingly)
# Add exclusions for known safe applications
Add-MpPreference -ExclusionPath "C:\Program Files\Microsoft SQL Server\MSSQL15.MSSQLSERVER\MSSQL\DATA"
Add-MpPreference -ExclusionProcess "sqlservr.exe"
Add-MpPreference -ExclusionExtension ".bak"
# View current exclusions
Get-MpPreference | Select-Object -ExpandProperty ExclusionPath
Get-MpPreference | Select-Object -ExpandProperty ExclusionProcess
Threat Detection and Response
# View threat history
Get-MpThreatDetection
# View recent scans
Get-MpThreat
# Manual scan
Start-MpScan -ScanType QuickScan
# Full scan
Start-MpScan -ScanType FullScan
# Scan specific path
Start-MpScan -ScanType CustomScan -ScanPath "C:\Users"
# Remove detected threats
Remove-MpThreat
# Restore quarantined items (if false positive)
Restore-MpPreference -ThreatID <ThreatID>
Windows Firewall Hardening
Advanced Firewall Configuration
# Enable firewall for all profiles
Set-NetFirewallProfile -Profile Domain,Public,Private -Enabled True
# Block all inbound by default
Set-NetFirewallProfile -DefaultInboundAction Block -DefaultOutboundAction Allow
# Enable logging
Set-NetFirewallProfile -LogFileName "%SystemRoot%\System32\LogFiles\Firewall\pfirewall.log" `
-LogMaxSizeKilobytes 16384 `
-LogAllowed True `
-LogBlocked True
# Allow RDP (restrict by source)
New-NetFirewallRule -DisplayName "Allow RDP from Management Network" `
-Direction Inbound `
-Protocol TCP `
-LocalPort 3389 `
-RemoteAddress 10.0.1.0/24 `
-Action Allow `
-Profile Domain
# Allow WinRM (for remote management)
New-NetFirewallRule -DisplayName "Allow WinRM HTTPS" `
-Direction Inbound `
-Protocol TCP `
-LocalPort 5986 `
-Action Allow `
-Profile Domain
# Block SMBv1
New-NetFirewallRule -DisplayName "Block SMBv1" `
-Direction Inbound `
-Protocol TCP `
-LocalPort 445 `
-Action Block `
-Enabled True
IPSec Configuration
# Create IPSec policy for server-to-server communication
New-NetIPsecRule -DisplayName "Server Authentication" `
-InboundSecurity Require `
-OutboundSecurity Request `
-Protocol TCP `
-LocalPort 1433 ` # SQL Server
-Authentication Required `
-Encryption Dynamic
# Configure authentication method
Set-NetIPsecRule -DisplayName "Server Authentication" `
-Auth1 ComputerKerb `
-Auth2 UserKerb
BitLocker Drive Encryption
Enabling BitLocker on Data Volumes
# Check BitLocker capability
Get-BitLockerVolume
# Enable BitLocker on data volume
Enable-BitLocker -MountPoint "E:" `
-EncryptionMethod Aes256 `
-UsedSpaceOnly `
-RecoveryPasswordProtector
# Backup recovery key to AD
Backup-BitLockerKeyProtector -MountPoint "E:" `
-KeyProtectorId (Get-BitLockerVolume -MountPoint "E:").KeyProtector[0].KeyProtectorId
# Add TPM protector (for OS volume)
Add-BitLockerKeyProtector -MountPoint "C:" -TpmProtector
Enable-BitLocker -MountPoint "C:" -EncryptionMethod Aes256 -SkipHardwareTest
# View BitLocker status
Get-BitLockerVolume | Select-Object MountPoint, VolumeStatus, EncryptionPercentage, ProtectionStatus
BitLocker Management
# Suspend BitLocker (for firmware updates)
Suspend-BitLocker -MountPoint "C:" -RebootCount 1
# Resume BitLocker
Resume-BitLocker -MountPoint "C:"
# Decrypt volume (if needed)
Disable-BitLocker -MountPoint "E:"
# Rotate recovery password
Add-BitLockerKeyProtector -MountPoint "E:" -RecoveryPasswordProtector
Remove-BitLockerKeyProtector -MountPoint "E:" -KeyProtectorId $oldKeyProtectorId
BitLocker GPO Configuration
# Configure BitLocker via GPO
# Computer Configuration → Policies → Administrative Templates → Windows Components → BitLocker Drive Encryption
# Operating System Drives
Set-GPRegistryValue -Name "BitLocker-Policy" `
-Key "HKLM\SOFTWARE\Policies\Microsoft\FVE" `
-ValueName "OSEncryptionType" `
-Type DWord `
-Value 1 # Full encryption
# Data Drives
Set-GPRegistryValue -Name "BitLocker-Policy" `
-Key "HKLM\SOFTWARE\Policies\Microsoft\FVE" `
-ValueName "FDVEncryptionType" `
-Type DWord `
-Value 1
Credential Guard
Enabling Credential Guard
# Prerequisites: Windows Server 2016+ with Hyper-V capability
# Enable Virtualization-Based Security
Enable-WindowsOptionalFeature -Online -FeatureName VirtualMachinePlatform -NoRestart
# Enable Credential Guard via GPO or Registry
New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa" `
-Name "LsaCfgFlags" `
-Value 1 `
-PropertyType DWord `
-Force
# Enable Secure Boot (UEFI firmware setting required)
# Confirm-SecureBootUEFI should return True
# Restart computer
Restart-Computer -Force
Verifying Credential Guard
# Check if Credential Guard is running
Get-CimInstance -ClassName Win32_DeviceGuard -Namespace root\Microsoft\Windows\DeviceGuard
# Expected output:
# SecurityServicesRunning: {1, 2} # 1 = Credential Guard, 2 = HVCI
# Alternative check via System Information
msinfo32.exe
# Look for "Credential Guard" under "System Summary"
AppLocker Application Control
Configuring AppLocker Rules
# Enable AppLocker service
Set-Service -Name AppIDSvc -StartupType Automatic
Start-Service -Name AppIDSvc
# Create default rules (allow built-in apps)
$rules = @"
<AppLockerPolicy Version="1">
<RuleCollection Type="Exe" EnforcementMode="Enabled">
<FilePathRule Id="921cc481-6e17-4653-8f75-050b80acca20" Name="(Default Rule) All files located in the Windows folder" Description="Allows members of the Everyone group to run applications that are located in the Windows folder." UserOrGroupSid="S-1-1-0" Action="Allow">
<Conditions>
<FilePathCondition Path="%WINDIR%\*"/>
</Conditions>
</FilePathRule>
<FilePathRule Id="a61c8b2c-a319-4cd0-9690-d2177cad7b51" Name="(Default Rule) All files located in the Program Files folder" Description="Allows members of the Everyone group to run applications that are located in the Program Files folder." UserOrGroupSid="S-1-1-0" Action="Allow">
<Conditions>
<FilePathCondition Path="%PROGRAMFILES%\*"/>
</Conditions>
</FilePathRule>
</RuleCollection>
<RuleCollection Type="Script" EnforcementMode="Enabled">
<FilePathRule Id="06dce67b-934c-454f-a263-2515c8796a5d" Name="(Default Rule) All scripts located in the Program Files folder" Description="Allows members of the Everyone group to run scripts that are located in the Program Files folder." UserOrGroupSid="S-1-1-0" Action="Allow">
<Conditions>
<FilePathCondition Path="%PROGRAMFILES%\*"/>
</Conditions>
</FilePathRule>
<FilePathRule Id="9428c672-5fc3-47f4-808a-a0011f36dd2c" Name="(Default Rule) All scripts located in the Windows folder" Description="Allows members of the Everyone group to run scripts that are located in the Windows folder." UserOrGroupSid="S-1-1-0" Action="Allow">
<Conditions>
<FilePathCondition Path="%WINDIR%\*"/>
</Conditions>
</FilePathRule>
</RuleCollection>
</AppLockerPolicy>
"@
$rules | Set-AppLockerPolicy -Merge
# Set enforcement mode
Set-AppLockerPolicy -XmlPolicy $rules -Merge
Publisher Rules (Recommended)
# Create publisher rule for signed applications
New-AppLockerPolicy -FileInformation (Get-AppLockerFileInformation -Path "C:\Program Files\Application\app.exe") `
-RuleType Publisher `
-User Everyone `
-RuleNamePrefix "Contoso-App-" |
Set-AppLockerPolicy -Merge
# Test AppLocker policy before enforcement
Test-AppLockerPolicy -XmlPolicy C:\AppLockerPolicy.xml -Path "C:\Users\TestApp.exe"
Security Auditing
Configuring Advanced Audit Policies
# Enable advanced audit policies
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:"Security Group Management" /success:enable /failure:enable
auditpol /set /subcategory:"User Account Management" /success:enable /failure:enable
auditpol /set /subcategory:"Process Creation" /success:enable
auditpol /set /subcategory:"File Share" /success:enable /failure:enable
auditpol /set /subcategory:"Sensitive Privilege Use" /success:enable /failure:enable
# View current audit settings
auditpol /get /category:*
# Export audit policy
auditpol /backup /file:C:\AuditPolicy.csv
# Import audit policy
auditpol /restore /file:C:\AuditPolicy.csv
Security Event Monitoring
# Monitor failed logon attempts (Event ID 4625)
Get-WinEvent -FilterHashtable @{
LogName = 'Security'
ID = 4625
StartTime = (Get-Date).AddDays(-1)
} | Select-Object TimeCreated, Message | Format-Table -AutoSize
# Monitor account lockouts (Event ID 4740)
Get-WinEvent -FilterHashtable @{
LogName = 'Security'
ID = 4740
StartTime = (Get-Date).AddDays(-1)
}
# Monitor privilege escalation (Event ID 4672)
Get-WinEvent -FilterHashtable @{
LogName = 'Security'
ID = 4672
StartTime = (Get-Date).AddHours(-8)
}
# Create scheduled task for daily security report
$action = New-ScheduledTaskAction -Execute 'PowerShell.exe' `
-Argument '-File C:\Scripts\SecurityReport.ps1'
$trigger = New-ScheduledTaskTrigger -Daily -At 8am
Register-ScheduledTask -TaskName "Daily Security Report" `
-Action $action `
-Trigger $trigger `
-User "SYSTEM"
Patch Management
Windows Update Configuration
# Install PSWindowsUpdate module
Install-Module -Name PSWindowsUpdate -Force
# Check for updates
Get-WindowsUpdate
# Install all updates
Install-WindowsUpdate -AcceptAll -AutoReboot
# Install security updates only
Install-WindowsUpdate -MicrosoftUpdate -Category "Security Updates" -AcceptAll
# Hide specific update
Hide-WindowsUpdate -KBArticleID "KB5012345"
# View update history
Get-WindowsUpdateLog
Get-WUHistory
WSUS Configuration
# Configure client to use WSUS
Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" `
-Name "UseWUServer" `
-Value 1
Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate" `
-Name "WUServer" `
-Value "http://wsus.contoso.com:8530"
Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate" `
-Name "WUStatusServer" `
-Value "http://wsus.contoso.com:8530"
# Restart Windows Update service
Restart-Service wuauserv
# Force detection
wuauclt /detectnow
Automated Patching Schedule
# Create maintenance window
$maintenanceScript = @"
`$updates = Get-WindowsUpdate -MicrosoftUpdate -Category 'Security Updates','Critical Updates'
if (`$updates.Count -gt 0) {
Install-WindowsUpdate -MicrosoftUpdate -Category 'Security Updates','Critical Updates' -AcceptAll -IgnoreReboot
# Send notification
Send-MailMessage -To 'admin@contoso.com' ``
-From 'server@contoso.com' ``
-Subject 'Server Patching Completed' ``
-Body "`$(`$updates.Count) updates installed on `$env:COMPUTERNAME" ``
-SmtpServer 'smtp.contoso.com'
# Schedule reboot
shutdown /r /t 300 /c "Server will reboot in 5 minutes for updates"
}
"@
$maintenanceScript | Out-File C:\Scripts\WeeklyPatching.ps1
# Schedule weekly patching (Tuesday 2 AM)
$action = New-ScheduledTaskAction -Execute 'PowerShell.exe' `
-Argument '-ExecutionPolicy Bypass -File C:\Scripts\WeeklyPatching.ps1'
$trigger = New-ScheduledTaskTrigger -Weekly -DaysOfWeek Tuesday -At 2am
Register-ScheduledTask -TaskName "Weekly Patching" `
-Action $action `
-Trigger $trigger `
-User "SYSTEM" `
-RunLevel Highest
Security Compliance Scanning
PowerShell Security Assessment
# Security assessment script
$report = @()
# Check if Windows Firewall is enabled
$firewallStatus = Get-NetFirewallProfile | Select-Object Name, Enabled
$report += [PSCustomObject]@{
Check = "Windows Firewall"
Status = if ($firewallStatus.Enabled -contains $false) { "FAIL" } else { "PASS" }
Details = $firewallStatus
}
# Check if BitLocker is enabled
$bitlockerStatus = Get-BitLockerVolume | Select-Object MountPoint, ProtectionStatus
$report += [PSCustomObject]@{
Check = "BitLocker Encryption"
Status = if ($bitlockerStatus.ProtectionStatus -contains "Off") { "FAIL" } else { "PASS" }
Details = $bitlockerStatus
}
# Check if Windows Defender is enabled
$defenderStatus = Get-MpComputerStatus | Select-Object RealTimeProtectionEnabled, AntivirusEnabled
$report += [PSCustomObject]@{
Check = "Windows Defender"
Status = if (-not $defenderStatus.RealTimeProtectionEnabled) { "FAIL" } else { "PASS" }
Details = $defenderStatus
}
# Check for pending updates
$pendingUpdates = Get-WindowsUpdate
$report += [PSCustomObject]@{
Check = "Pending Updates"
Status = if ($pendingUpdates.Count -gt 0) { "WARN" } else { "PASS" }
Details = "$($pendingUpdates.Count) updates pending"
}
# Export report
$report | Export-Csv C:\Reports\SecurityAssessment_$(Get-Date -Format 'yyyyMMdd').csv -NoTypeInformation
$report | Format-Table -AutoSize
Key Takeaways
- Apply Microsoft Security Baselines for foundational hardening
- Enable Windows Defender ATP for advanced threat protection
- Configure Windows Firewall with restrictive default-deny rules
- Implement BitLocker encryption on all data volumes
- Enable Credential Guard to protect domain credentials
- Use AppLocker to control application execution
- Configure comprehensive security auditing
- Automate patch management with scheduled tasks
- Regular security assessments validate compliance
- Document exclusions and exceptions with business justification
Next Steps
- Deploy security baselines to all servers
- Enable BitLocker on unencrypted volumes
- Configure centralized logging with SIEM
- Implement automated security scanning
- Schedule regular vulnerability assessments
- Train staff on security best practices
Additional Resources
- Windows Security Baselines
- Microsoft Defender for Endpoint
- BitLocker Drive Encryption
- Credential Guard
- AppLocker
Harden. Protect. Monitor. Secure.