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

18 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
       
  2. Hello, is this the correct way to make the certificate last 10 years?? (or any duration)??
    New-SelfSignedCertificate @SelfSignedHT -NotAfter (Get-Date).AddYears(10)

  3. I am getting an error at step # 4. Select this certificate in the SSL bindings
    $cert | New-Item IIS:\SslBindings\0.0.0.0!8531

    Error Details:
    Cannot find drive. A drive with the name ‘IIS’ does not exist.cert | New-Item IIS:\SslBindings\0.0.0.0!8531
    New-Item : Cannot find drive. A drive with the name ‘IIS’ does not exist.
    + $cert | New-Item IIS:\SslBindings\0.0.0.0!8531
    + $cert | New-Item IIS:\SslBindings\0.0.0.0!8531
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : ObjectNotFound: (IIS:String) [New-Item], DriveNotFoundException
    + FullyQualifiedErrorId : DriveNotFound,Microsoft.PowerShell.Commands.NewItemCommand

    Can you help?

    • If IIS: drive doesn’t exist, it probably means that the IIS powershell module is not loaded.
      You need a feature named “IIS Management Scripts and Tools” aka Web-Scripting-Tools
      Then in Powershell you load the IISAdministration module.

  4. I’m getting an error that reads

    Export-Certificate : Home location for this provider is not set. To set the home location, call “(get-psprovider ‘FileSystem’).Home = ‘path'”.
    At line:10 char:1
    + Export-Certificate -Cert $cert -Type CERT -FilePath ~/documents/cert.cer
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (:) [Export-Certificate], PSInvalidOperationException
    + FullyQualifiedErrorId : InvalidOperation,Microsoft.CertificateServices.Commands.ExportCertificateCommand

    This one is followed by one similar for importing the cert. I think it’s telling me how to remedy it but my PowerShell skills aren’t very good. Any suggestions?

    • Steps 1. to 3. is to get a certificate. In this case, it’s a self-signed certificate. You can get another certificate if you want from an internal PKI or a public CA (Certificate Authority).
      Steps 4. to 6. should be done on the WSUS server itfself.
      Steps 7. and 8. is to tell your clients to trust the cert and what’s the new https URL. In this case, it’s done with a group policy. You can leverage other tools to deploy the settings to your clients.

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.