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
You’ve successfully mitigated the threat reported at BH2015 š
Note that the certificate is valid for 1 year.
No available!
Thanks!
Do you need to re-run this script after the cert expires in one year? Thanks!
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.
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).
In your case, you’ve got more than 1.
You can see these:
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:
Hello, is this the correct way to make the certificate last 10 years?? (or any duration)??
New-SelfSignedCertificate @SelfSignedHT -NotAfter (Get-Date).AddYears(10)
Yes, according to the documentation on this page:
https://docs.microsoft.com/en-us/powershell/module/pkiclient/new-selfsignedcertificate?view=win10-ps
That was a fast reply!! Thank you!! š Also thank you for writing the script. š
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.
Ah thanks! I didn’t think about that!
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?
See https://p0w3rsh3ll.wordpress.com/2014/12/23/tilde-issue/
Thanks for the quick response, the answer was staring me in the face but I didn’t know what to do with it.
Also thanks for the script.
Do we do all seven steps on the WSUS server? Does the last step update itself to use SSL?
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.
I solved the above error and now I have the following:
New-Item : Cannot create a file when that file already exists
At line:16 char:9
+ $cert | New-Item IIS:\SslBindings\0.0.0.0!8531
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [New-Item], Win32Exception
+ FullyQualifiedErrorId : System.ComponentModel.Win32Exception,Microsoft.PowerShell.Commands.NewItemCommand
============
As I view the IIS bindings for the WSUS Admin site there is none for HTTPS there. Should I be looking elsewhere? While waiting for a response I will try adding it myself.
When I already have a previous certificate, I do
You’re the best! Thanks a lot for this!
Hey, please help me!
I have 1 Upstream WSUS, 40 downstream WSUS (internal) & 1 downstream WSUS (external-internet facing server), every server have their own hostname of course. I want to make all client connect to wsus.contoso.com (I set this with DNS and routing), so wherever the user is (in internal network or external network), they can connect to wsus.contoso.com.
My question :
1. what server that should generate self-signed certificate?
2. lets say I generate the self-signed cert. in Upstream WSUS server, so what should I do next with the downstream servers?
Hello,
I’d generate only 1 certificate wsus.contoso.com and install it on every wsus server. Then you just need to distribute its public key to client computers in their root CA store.
You can also generate 41 certificates and distribute 41 public keys to clients computers. I suppose it will also work and that first the tumbprint of the certificate and then its name is in use when the TLS session is established by the client.
When a client is sent to https://wsus.contoso.com, you’re right, there’s first a dns request, then the client tries to initiate the tls session with the IIS wsus website (should be installed as wsus.contoso.com and not hostname.contoso.com).
Please, let me know what you do and what works.
Cheers
Thanks for your fast respond! I will try it, and will update it in this forum.
hello, you said that “Iād generate only 1 certificate wsus.contoso.com and install it on every wsus server.”
1. Is it self signed certificate?
2. Did you mean I should create self signed certificate on master WSUS server? The how can I install the same certificate on the other replica WSUS server?
Please help me
1. Yes, it can be. It can be self-signed or from a PKI.
2. Yes, the server name and location in the hierarchy doesn’t matter. The certificate will appear to be the same for the clients. Clients will check the name wsus.contoso.com.
Each WSUS server should have the certificate (private key in Personal computer store and public key in the Trusted Root CA computer store). Clients only need the public key of the certificate and to trust it (add it to the Trusted Root CA computer store). It also means that you need to be able to export the certificate including its private key so that you can import it on other WSUS servers in their Personal computer store.
The official guide about SSL is : https://docs.microsoft.com/en-us/windows-server/administration/windows-server-update-services/deploy/2-configure-wsus#23-secure-wsus-with-the-secure-sockets-layer-protocol
Here’s the guide about the hierarchy
https://docs.microsoft.com/en-us/windows-server/administration/windows-server-update-services/plan/plan-your-wsus-deployment#12-choose-a-wsus-deployment-scenario
Here’s someone who wrote about configuring ssl between upstream and downstream:
https://techdirectarchive.com/2018/03/10/configuring-ssl-between-wsus-servers-upstream-and-downstream-servers/
Here’s how to use the New-SelfSignedCertificate cmdlet and mark the private key as exportable
https://p0w3rsh3ll.wordpress.com/2016/04/17/bye-bye-makecert-exe/
(Yes, you even create the certificate on a Windows 10 computer)
Here’s what I do to renew the WSUS certificate every year:
https://p0w3rsh3ll.wordpress.com/2019/02/28/quick-tip-renew-a-certificate-used-by-wsus/
Hello, I’m still failed, Here’s my steps :
1. on WSUS upstream named “WSUS-UP”, create self sign certificate (the certificate issued to wsus-up of course), set WSUS with SSL, and no problem at all.
2. export that certificate into .pfx format, export the public key too, then copy to my downstream named “WSUS-down”
3. on “WSUS-down” import the .pfx certificate (private key) into IIS, then import the public key to Trust CA.
4. Then, when I set WSUS with SSL on “WSUS-down” server, it cannot load the WSUS!
Maybe you can help me?
I think it is because the certificate is issued to “wsus-up”, when in my downstream the wsus name is “wsus-down”