Every production Windows Server running IIS should follow a standardized hardening process. Manual configuration through the GUI inevitably leads to inconsistencies, missed patches, and settings that drift over time as team members make ad-hoc changes. By using PowerShell to configure IIS, administrators can create reusable scripts that enforce security baselines, integrate with configuration management tools like Ansible or SCCM, and ensure every .NET hosting environment starts from the same secure foundation. This approach is particularly valuable for hosting providers managing multiple servers or virtual machines for customers running ASP.NET Core applications.
In this guide, we examine key areas where PowerShell delivers immediate value for system administrators: application pool management with isolated identities, protocol hardening for TLS, request filtering to block malicious traffic, HTTP security response headers, and Windows Authentication integrated with Active Directory. The examples are written for Windows Server 2022 with IIS 10, but the patterns work on Windows Server 2019 and future releases. Each section includes ready-to-use code snippets tested in production environments. Following these patterns reduces your attack surface and makes compliance audits significantly easier.
#Server Preparation and Required Modules
The WebAdministration module is the primary tool for managing IIS from PowerShell. It is installed as part of the IIS Management Scripts and Tools feature. For a complete setup suitable for hosting .NET applications, install the Web Server role along with ASP.NET support and the management tools. If you plan to use Active Directory-based authentication or authorization, the server must be joined to your domain and the executing account should have rights to read group memberships.
Import-Module ServerManager
Install-WindowsFeature -Name Web-Server, Web-Asp-Net45, Web-Mgmt-Console, Web-Mgmt-Tools -IncludeManagementTools
Import-Module WebAdministration
#Hardening Application Pools
Application pools are the foundation of IIS process isolation. Each pool should operate under a dedicated low-privilege account to contain potential breaches. For domain environments, create a gMSA (group Managed Service Account) if possible, or a standard domain account with no interactive rights. The script below creates a pool, configures a specific identity, sets resource limits to prevent denial-of-service from a single application, and enables regular recycling. These settings are essential in shared hosting scenarios to maintain fair resource allocation across customers.
$poolName = "SecureHostingPool"
New-WebAppPool -Name $poolName
$pool = Get-Item "IIS:\AppPools\$poolName"
$pool.processModel.identityType = 3 # SpecificUser
$pool.processModel.userName = "DOMAIN\WebAppSvc"
$pool.processModel.password = "P@ssw0rd123!"
$pool.processModel.loadUserProfile = $true
$pool.queueLength = 500
$pool.cpu.limit = 30000 # 30% CPU
$pool.cpu.action = "KillW3wp"
$pool.recycling.periodicRestart.time = "1.00:00:00"
$pool | Set-Item
#Enforcing Modern TLS Configurations
Weak cryptographic protocols remain one of the top findings in vulnerability scans of web servers. Use PowerShell to modify the Schannel registry settings to disable outdated protocols and prioritize secure cipher suites. After applying these changes a server reboot is required. The configuration below disables everything before TLS 1.2, enables TLS 1.3, and orders cipher suites to prefer AES-GCM with ECDHE. This ensures your hosted applications achieve an A+ rating on SSL Labs tests and protects customer data in transit.
# Disable insecure protocols
$keyPath = 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols'
@('SSL 2.0', 'SSL 3.0', 'TLS 1.0', 'TLS 1.1') | ForEach-Object {
New-Item -Path "$keyPath\$_\Server" -Force | Out-Null
New-ItemProperty -Path "$keyPath\$_\Server" -Name 'Enabled' -Value 0 -Type DWord
New-ItemProperty -Path "$keyPath\$_\Server" -Name 'DisabledByDefault' -Value 1 -Type DWord
}
# Additional TLS 1.2/1.3 enablement and cipher suite ordering can be added similarly
#Active Directory Authentication Setup
When hosting internal applications, leveraging Active Directory for authentication eliminates the need to manage separate credentials. With the server joined to the domain, configure the site to require Windows Authentication. This uses Kerberos for ticket-based auth which integrates cleanly with AD groups for authorization rules. The PowerShell cmdlets modify the authentication providers at the site level. You can then use URL authorization to allow only specific AD security groups to access certain paths.
Import-Module WebAdministration
$site = 'IIS:\Sites\InternalApp'
Set-WebConfigurationProperty -Filter '/system.webServer/security/authentication/anonymousAuthentication' -Name 'enabled' -Value 'false' -PSPath $site
Set-WebConfigurationProperty -Filter '/system.webServer/security/authentication/windowsAuthentication' -Name 'enabled' -Value 'true' -PSPath $site
Set-WebConfigurationProperty -Filter '/system.webServer/security/authentication/windowsAuthentication' -Name 'useAppPoolCredentials' -Value 'false' -PSPath $site
#Security Headers and Request Filtering
Security headers instruct browsers on how to handle your content and can prevent entire classes of attacks. Request filtering protects the server by rejecting malformed or dangerous requests before they reach your application code. Both can be managed through PowerShell by editing the configuration sections. The example adds important headers like HSTS and CSP placeholders, while tightening the request limits. These should be tailored to your specific applications but having a baseline script ensures nothing is overlooked during initial setup.
# Add security headers
$headersPath = 'IIS:\Sites\Default Web Site\system.webServer/httpProtocol/customHeaders'
@(
@{name='X-Content-Type-Options'; value='nosniff'},
@{name='X-Frame-Options'; value='DENY'},
@{name='Strict-Transport-Security'; value='max-age=31536000; includeSubDomains; preload'}
) | ForEach-Object {
Add-WebConfigurationProperty -PSPath 'IIS:\Sites\Default Web Site' -Filter 'system.webServer/httpProtocol/customHeaders' -Name '.' -Value $_
}
# Configure request filtering limits
Set-WebConfigurationProperty -PSPath 'IIS:\' -Filter 'system.webServer/security/requestFiltering/requestLimits' -Name 'maxUrl' -Value 2048
Take these scripts, test them thoroughly against your application requirements, and incorporate them into an automated server build process. Whether you are provisioning new hosts weekly or enforcing compliance on existing ones, PowerShell gives you the precision and repeatability that manual processes cannot match. The combination of isolated app pools, strong TLS, AD-backed authentication, and proper headers creates a robust platform for hosting .NET applications. Review and update your scripts whenever Microsoft releases new security guidance or IIS updates to stay ahead of emerging threats.
Comments
No comments yet