When Get-WebRequest Fails You, (Thu, May 12th)

This post was originally published on this site

In my last story (https://isc.sans.edu/forums/diary/Finding+the+Real+Last+Patched+Day+Interim+Version/28610/) , I talked about pulling patch descriptions from the MS portal using Get-WebRequest.  This worked great on my test machine (said every developer ever), but the next day when I tried it on a different client's domain, I got this error for every call of Get-WebRequest:

Invoke-WebRequest : The underlying connection was closed: An unexpected error occurred on a send.
At line:3 char:21
+ … $postdata = Invoke-WebRequest -Uri $lnk
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand

This is a classic "something is wrong on the internet" error message – there really is nothing in the message that steers us towards a solution, other than telling me that the get-webrequest command failed.  I turns out that this client had simply killed TLS 1.0, 1.1 and several ciphers in 1.2 in their domain using a Group Policy (an excellent choice), and the MS Portal doesn't support TLS 1.3 (oops).

A quick nmap scan of the target site confirms that the MS update catalogue site is 1.2 only, with support for only 4 ciphers:

nmap -Pn -sT -p443 -sV www.catalog.update.microsoft.com –script ssl-enum-ciphers
Starting Nmap 7.92 ( https://nmap.org ) at 2022-05-06 08:18 Eastern Daylight Time
Nmap scan report for www.catalog.update.microsoft.com (
Host is up (0.038s latency).

443/tcp open  ssl/https
|_http-server-header: Microsoft-IIS/10.0
| ssl-enum-ciphers:
|   TLSv1.2:
|     ciphers:
|       TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (secp384r1) – A
|       TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (ecdh_x25519) – A
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (secp384r1) – A
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (ecdh_x25519) – A

|     compressors:
|       NULL
|     cipher preference: server
|_  least strength: A

Note, in this case nmap might be a bit misleading, ssllabs.com finds that two of these four should not get an "A" grade:

TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (0xc028)   ECDH secp384r1 (eq. 7680 bits RSA)   FS   WEAK     256
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (0xc027)   ECDH x25519 (eq. 3072 bits RSA)      FS   WEAK     128

Anyway, since I can't fix the MS Catalogue site, my solution was to temporarily fix the current instance of PowerShell and permit other TLS versions and ciphers.  I added this to the start of the script to expand the SSL/TLS options available to my script:

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::TLS -bor [Net.SecurityProtocolType]::TLS11 -bor [Net.SecurityProtocolType]::TLS12

This uses a call to dotnet to expand this script's support for TLS.  This fixes the situation for Invoke-WebRequest, Invoke-RestMethod and any other operation you may need that uses TLS.  Note that for this particular case I've enabled all of TLS 1.0, 1.1 and 1.2 when for this job, only some ciphers in TLS12 were needed – but for me, if I'm going to keep a hammer like this laying around, I want it to WORK the next time (and every time) too :-).  Enabling all of the options isn't the most elegant or most perfect solution, but it's a solution I won't have to come back and fix again later.  Plus it's only enabled for the process that called it – in this case my script.

My take-aways from this:

  • PowerShell REALLY needs some help in writing better error messages.  The fact that the whole language is a shim that allows you go make calls to other bits and pieces of the OS is what makes it so powerful, but it also makes collecting error information from all those sources and presenting it back in the PS interface very difficult.
  • Microsoft is as bad as everyone else in following security guidance, their patch portal for goodness sake needs remediation for TLS support.  Their perimeter assessment report likely did not have a "weak ciphers" finding, but likely did have a "does not conform to Microsoft TLS standards" finding (with references).  And because there wasn't a security risk (just an internal spanking if they got caught) the manager and PM likely decided to assume that risk and fix it later.  Because an hour to fix TLS was too much work.  Or alternatively, maybe the report did have a "weak ciphers" finding, and the site was then restricted so far that only the 4 ciphers we see are allowed.  Either way, I needed a workaround to use the site at all.

Have you needed to dive into different dotnet functions to make a script work or to call a function that isn't in PowerShell yet?  Please, share in our comment section, enquiring minds want to know!

Rob VandenBrink
rob <at> coherentsecurity.com

(c) SANS Internet Storm Center. https://isc.sans.edu Creative Commons Attribution-Noncommercial 3.0 United States License.

Leave a Reply

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