1

In order to fix an issue with our website test PowerShell script, we added the following code prior to Invoke-WebRequest call (per this and this:

add-type @"
using System.Net;
using System.Security.Cryptography.X509Certificates;
public class TrustAllCertsPolicy : ICertificatePolicy {
    public bool CheckValidationResult(
        ServicePoint srvPoint, X509Certificate certificate,
        WebRequest request, int certificateProblem) {
            return true;
        }
 }
"@
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy

$login = Invoke-WebRequest "https://...."

And then to add valid TLS policies we recently added:

[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]'Tls12'

My question is simple. How does this code affect the Invoke-webrequest? As far as I can see, it is not linked to the call in direct way. There's nothing applied to a session variable (in an obvious way).
I saw one reference to a callback function, but I still don't see how CheckValidationResult gets passed as a callback. And yet it works.

uSlackr
  • 743
  • 5
  • 19
  • 1
    `Invoke-WebRequest` runs in a .NET AppDomain (powershell). The `ServicePointManager` affects all connections in that domain. It sounds like you have a certificate issue requiring these workarounds or your computer is on Windows 7 where TLS 1.2 was not shipped in the SCHANNEL SSP by default. – Maximilian Burszley Oct 23 '18 at 19:01
  • Exactly what I was looking for. Care to add this as an answer? – uSlackr Oct 23 '18 at 20:21

2 Answers2

2

PowerShell is a .NET application. .NET applications have an AppDomain (only one; this is why you need to re-launch powershell.exe to clear the session). As a part of this, you have a System.Net.ServicePointManager class to manage HTTP connections (I strongly recommend reading this article for fuller understanding).


The reason for your first bit of code with the TrustAllCertsPolicy object is due to the untrusted nature of self-signed certificates which tells me either

  1. Your service is using a self-signed cert
  2. Your service has some company-specific cert that your workstation does not have imported

So all it does is let Invoke-WebRequest accept any certificate (which is dangerous if you don't know what you're connecting to).


The reason for your second bit with the SecurityProtocol is due to Win7/W2K8 not supporting TLS1.2 as a default. This is normally handled using the SCHANNEL registry keys (some additional reading), but they don't exist on those platforms by default (I may be mis-remembering this piece) so your AppDomain is defaulting to SSL3.0/TLS1.0. I'd recommend using -bor when setting the SecurityProtocol so you don't break any backwards- or forwards-compability:

[System.Net.ServicePointManager]::SecurityProtocol =
    [System.Net.ServicePointManager]::SecurityProtocol -bor [System.Net.SecurityProtocolType]::Tls12
Maximilian Burszley
  • 18,243
  • 4
  • 34
  • 63
  • Great. Thanks. The link is good too. My comment to @guillaumeCR explains our use case for the cert name issue. – uSlackr Oct 23 '18 at 22:06
-1

First of all, let's make it clear that this powershell effectively disables TLS and makes all your https requests insecure as absolutely no certificate verification is performed (it returns true all the time).

How this works is as such:

  1. You create the new cert validator class that blindly says "yes" whenever you ask "is this secure?"
  2. You assign the policy on the static ServicePointManager of your session.
  3. You create a new web request, which internally refers to the static ServicePointManager to instantiate a cert policy and blindly say "yes" to any cert verification.

I'm not sure what problem you are trying to fix with this approach, but I would not recommend this approach.

Guillaume CR
  • 3,006
  • 1
  • 19
  • 31
  • Thanks for the note. We aren't "blindly" doing this. We're running a specific test against a specific web server we own & operate. The server is part of a load balanced pair and the virtual name has the cert on it. This is low risk in this situation and easier to implement than a SAN cert. I know what we are doing, just unclear how the mechanism works. – uSlackr Oct 23 '18 at 20:25
  • 1
    It does not turn off TLS, it only limits it to use TLS1.2 – Maximilian Burszley Oct 23 '18 at 21:43
  • @TheIncorrigible1 TLS depends on certificate trust. By trusting all certificates you are effectively turning off TLS. – Guillaume CR Oct 25 '18 at 14:05