15

We have a Windows 10 Pro machine at our office which has an open port to the internet for incoming remote desktop connections (a ‘host’). It is well protected by complex password and limited number of permitted attempts and only TLS 1.1 or higher, but it doesn't present an externally-verified SSL certificate, only the self-generated self-signed one that Remote Desktop Services provides, and this gives us two problems:

  1. We cannot be fully confident when connecting remotely we really are connecting to this machine and not some hijacked connection.
  2. Our site fails PCI-DSS 3.1 compliance check (required because we use there a point-of-sale debit/credit card machine that connects via internet). The check reports fatal errors on this internet-facing remote desktop port: 'SSL Self-Signed Certificate' and 'SSL Certificate with Wrong Hostname'.

How do I get a Windows 10 Pro (or Windows 7 / 8 / 8.1 Pro) machine acting as server/host to present a proper SSL certificate for Remote Desktop verification?

  • 1
    You can either place the self-signed certificate into the certificate store, of each machine which will connect to this machine, that way only that self-signed certificate is trusted. You can also get the certificate signed by a CA and by default, because the CA is trusted, the certificate the host wants to use will be trusted. You won't be able to solve your PCI-DSS 3.1 compliance issues unless you get a certificate signed by CA. You should do that. – Ramhound Jun 24 '16 at 17:43
  • Thanks @Ramhound, you are quite right, I need a CA-signed certificate - I now have one. – gogoud Jun 25 '16 at 13:24
  • Related --> serverfault.com/questions/444286/… – FreeSoftwareServers Aug 15 '19 at 11:14
16

You can set this host machine to use and present your (existing, purchased) externally-verified SSL certificate thus (instructions probably also work for Windows 8 & 8.1, may or may not work for Windows 7) (parts of this based on a Microsoft KB 2001849):

First, you need to have purchased a genuine verified ssl certificate.

If you have this certificate in pkcs12 format file (e.g. pfx extension) you can view SHA1 fingerprint using Linux or Cygwin thus (you will need it below):

openssl pkcs12 -in mysite.pfx -nodes|openssl x509 -noout -fingerprint

Alternatively if you have the individual certificate files in your Linux server at /etc/ssl (/etc/ssl/certs/mysite.crt, /etc/ssl/mysite.ca-bundle and /etc/ssl/private/mysite.key) you can create pfx file and obtain SHA1 fingerprint thus:

  1. Create pfx file for your certificate, if you don’t already have one (here: mysite.pfx) – set a good password when requested:

    sudo openssl pkcs12  -export -out mysite.pfx -inkey /etc/ssl/private/mysite.pem -in /etc/ssl/certs/mysite.crt -certfile /etc/ssl/mysite.ca-bundle
    
  2. Move or copy this pfx file as required so that it is accessible by your Windows host machine.

  3. View SHA1 fingerprint of the key (you will need this below):

openssl x509 -in /etc/ssl/certs/mysite.crt -noout -fingerprint

Import pkcs12 format (e.g. pfx) file into Windows host machine’s personal certificates store:

  1. Start > Run > mmc
  2. File > Add Remove Snap-in > Certficates > Add > Computer Account > Local Computer > OK
  3. In the left-hand window right-click on Certificates (Local Computer)Personal, choose All Tasks/Import…
  4. Locate the pfx file and import it, I suggest that for security reasons you don’t make it exportable.
  5. Expanding your Personal/Certificates you should now see 3 certificates, one of which is your site certificate (e.g. mysite.com). Right-click on this site certificate and right-click, choose All Tasks / Manage Private Keys…
  6. Add user ‘NETWORK SERVICE’ with Read permission only (not Full Control), then Apply
  7. Close mmc

Use regedit to add a new Binary Value called SSLCertificateSHA1Hash at HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp. The value it needs is the SHA1 fingerprint of the certificate obtained above: right-click on the new value, choose Modify and then type in the hex codes sequentially (without colons or spaces or commas, letters are not case-sensitive) – there are 20 hex pairs in all (40 characters).

You may need to reboot the host machine, or restart Remote Desktop Services (from Services.msc) before it will work.

Now, after making a remote desktop connection to this host using the correct site name (e.g. mysite.com) you should see a locked padlock on the left-hand side of the top connection bar: clicking on this shows that the identity of the remote computer was verified. A port that is open from the internet through to this host should now pass PCI-DSS 3.1 hostname testing.

| improve this answer | |
  • I'd like to upvote you a few thousands times. It works 100% – Shockwaver Jan 1 at 14:04
9

Here are the basic steps I use:

Get a valid certificate that for the host, (it doesn't have to come from an external CA, but all your machines have to trust it). Make sure it has the correct hostname, I had problems with wildcard certs.

Install the cert on the host, like:

certutil.exe -p myPassword -importPFX c:\mycert.pfx noExport

find the thumbprint for the cert, either in the UI or in PowerShell:

$tp = (ls Cert:\LocalMachine\my | WHERE {$_.Subject -match "something unique in your certs subject field" } | Select -First 1).Thumbprint

now tell Remote Desktop to use that certificate:

& wmic /namespace:\\root\CIMV2\TerminalServices PATH Win32_TSGeneralSetting Set SSLCertificateSHA1Hash="$tp" 

no reboot required

| improve this answer | |
  • My wildcard SSL Cert worked fine, but I still had to open MMC and Add Network Service Permission or it wouldn't work. – FreeSoftwareServers Aug 16 '19 at 7:00
  • I was able to import wildcard certs on "Windows 10" as well as "Windows Server 2016" with a catch that Windows Server do not have certutil.exe. That’s not a big deal since you can manually import the mycert.pfx into cert store. I did not have to open MMC and did not Add Network Service Permission. – TMT Mar 31 at 3:29
1

My cert comes with 2 files needed, domain.crt & domain.ca-bundle & then I have my domain.key from generating the request.

Here is how I set it up using a Linux VM to combine the certs and generate the fingerprint and windows CMD to setup the host. This allows full scripting of setup.

The biggest differences between mine and @gogoud answer are:

  • I don't edit the registry. I tried that and it didn't work, I use wmic /namespace: via CMD prompt.
  • I tailored the "Fingerprint" line on the Linux VM to strip all unnecessary parts of the thumbprint and put it in the format Windows wants. (IE: No colons, no words, just the Fingerprint w/ lower case letters).
  • I also scripted adding NETWORK SERVICE permissions.

Make a directory to work in and move the 3 files into it:

domain.ca-bundle  domain.crt  domain.key 

Create pfx format key:

sudo openssl pkcs12  -export -out domain.pfx -inkey *.key -in *.crt -certfile *.ca-bundle

Export SSLCertificateSHA1Hash/FingerPrint to TXT File:

sudo openssl x509 -in *.crt -noout -fingerprint | sed -e 's/SHA1 Fingerprint=//g' | sed -e 's/://g' | tr '[:upper:]' '[:lower:]' > SSLCertificateSHA1Hash.txt

Import Cert to Windows (Open Elevated CMD Prompt):

  • This can be further scripted via the switch "-p MyPassword"

    certutil.exe -importpfx C:\domain.pfx
    

Now add SSLCertificateSHA1Hash to to RDP-Tcp via CMD (Elevated CMD Prompt):

set /p FingerPrint=<C:\SSLCertificateSHA1Hash.txt
wmic /namespace:\\root\CIMV2\TerminalServices PATH Win32_TSGeneralSetting Set SSLCertificateSHA1Hash="%FingerPrint%"

You will need to add the user "Network Service" w/ "Read Only" permissions now:

icacls.exe "C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys\*" /grant "NETWORK SERVICE":R

Reboot Host:

 shutdown /r /t 5
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.