Switch WSUS to https

The following was presented at Black Hat 2015 USA during the summer.

The whitepaper is available at http://ctx.is/WSUSpect
The slides are available at http://www.contextis.com/documents/162/WSUSpect_Presentation.pdf
The code is available at https://github.com/ctxis/wsuspect-proxy

The only mitigation identified was an HTTPS-enabled WSUS. In this post, I’d like to show how to switch your HTTP based WSUS to HTTPS.

I’ll assume that:

  • your server is running Windows 2012 R2, has already an http based WSUS
  • your server may not be connected directly to the Internet
  • you don’t want to buy a certificate from a public certiticate authority
  • you don’t have PKI in your infrastructure

This official documentation is available on Technet on this page

But let’s do this with PowerShell 🙂


# 1. Create a self-signed certificate
$SelfSignedHT = @{
 DnsName = "$($env:COMPUTERNAME).$($env:USERDNSDOMAIN)".ToLower()
 CertStoreLocation = "Cert:\LocalMachine\My"
}
New-SelfSignedCertificate @SelfSignedHT
$cert = Get-ChildItem -Path Cert:\LocalMachine\My -SSLServerAuthentication

# 2. Export its public key
Export-Certificate -Cert $cert -Type CERT -FilePath ~/documents/cert.cer

# 3. Import the public key in the Trusted Root Certificate Authorities store
Import-Certificate -FilePath ~/documents/cert.cer -CertStoreLocation Cert:\LocalMachine\Root

# 4. Select this certificate in the SSL bindings
$cert | New-Item IIS:\SslBindings\0.0.0.0!8531

# 5. Require SSL for the following virtual roots only:
'SimpleAuthWebService','DSSAuthWebService',
'ServerSyncWebService','APIRemoting30',
'ClientWebService' | ForEach-Object {
 Set-WebConfigurationProperty -Filter 'system.webserver/security/access' -Location "WSUS Administration/$($_)" -Name sslFlags -Value 8
}

# 6. Switch WSUS to SSL
& 'C:\Program Files\Update Services\Tools\WsusUtil.exe' configuressl $("$($env:COMPUTERNAME).$($env:USERDNSDOMAIN)".ToLower())

# 7. Change your GPO to point to the new URL
$key = 'HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate'
$uri = 'https://{0}:8531' -f $("$($env:COMPUTERNAME).$($env:USERDNSDOMAIN)".ToLower())
Get-GPO -All | Foreach-Object { 
 if ($_ | Get-GPRegistryValue -Key $key -ValueName WUServer -EA 0) {
  $_ | Set-GPRegistryValue -Key $key -ValueName WUServer       -Value $uri -Type String
  $_ | Set-GPRegistryValue -Key $key -ValueName WUStatusServer -Value $uri -Type String
 }
}

You’re almost done.
The last step consists in distributing the public key of your self-signed certificate to your clients so that they trust your self-signed certificate.
To achieve this, you’ll need to edit your GPO that targets clients and import your ~/documents/cert.cer file into ‘Computer Configuration / Policies / Windows Settings / Security Settings / Public Key Policies / Trusted Root Certificate Authrorities
Import-PK-into-Root

You’ve successfully mitigated the threat reported at BH2015 😎
Note that the certificate is valid for 1 year.

Advertisements

7 thoughts on “Switch WSUS to https

    • Good question!
      You need to run 1 to 4. That will change the cert on the server.
      5 to 7 are already done and needed to be run only once.
      Then you need to distribute the updated cert in the GPO that targets client computers.

  1. Keep getting an error on step two: Export-Certificate : Cannot convert ‘System.Object[]’ to the type ‘Microsoft.CertificateServices.Commands.Certificate’ required by parameter
    ‘Cert’. Specified method is not supported.
    At line:11 char:26 (the $cert parameter). Any ideas?

    • Yes,
      The following line will store your ssl certificate(s).

      $cert = Get-ChildItem -Path Cert:\LocalMachine\My -SSLServerAuthentication
      

      In your case, you’ve got more than 1.

      You can see these:

      dir Cert:\LocalMachine\My -SSLServerAuthentication | 
      Where { $_.NotAfter -gt (Get-date) }
      

      After that, you can choose to either delete certificates not in use or you can further filter the above line to get only 1 certificate (the one to be used by IIS and WSUS).

      Here’s what will work for you at step 1:

      # 1. Create a self-signed certificate
      $SelfSignedHT = @{
       DnsName = "$($env:COMPUTERNAME).$($env:USERDNSDOMAIN)".ToLower()
       CertStoreLocation = "Cert:\LocalMachine\My"
      }
      $cert = New-SelfSignedCertificate @SelfSignedHT
      # $cert = Get-ChildItem -Path Cert:\LocalMachine\My -SSLServerAuthentication
       

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.