Public/AzStackHci.SSLInspection.ps1
|
# /////////////////////////////////////////////////////////////////// # Test-AzStackHciSSLInspection function # Used to check for the presence of SSL Inspection on traffic sent to a specified URL # /////////////////////////////////////////////////////////////////// function Test-AzStackHciSSLInspection { <# .SYNOPSIS Function to check for the presence of SSL Inspection on traffic sent to a specified URL. .PARAMETER url The URL to test for SSL Inspection .DESCRIPTION Expects Microsoft or DigiCert certificates to be used for SSL/TLS connections to the specified URL. If a different certificate is detected, the script will report that SSL Inspection is present. Script checks for redirects and follows them to test further URLs if required. Returns $true if SSL Inspection is detected, otherwise $false. #> [CmdletBinding()] [OutputType([bool])] param ( [parameter(Mandatory=$true,HelpMessage="The URL to test for SSL Inspection",Position=0)] [System.Uri]$url, [Parameter(Mandatory=$false, HelpMessage="Optional switch to prevent console output from the function.")] [switch]$NoOutput ) begin { # Handle -NoOutput: suppress all console output if ($NoOutput.IsPresent) { $script:SilentMode = $true $VerbosePreference = 'SilentlyContinue' $DebugPreference = 'SilentlyContinue' } $ErrorActionPreference = "Stop" Write-HostAzS "`n`t///////////////////////////////////////////////" Write-HostAzS "`t Basic SSL Inspection Test for Azure Stack HCI" Write-HostAzS "`t///////////////////////////////////////////////`n" [bool]$RedirectsComplete = $false [bool]$SSLInspectionDetected = $false Write-HostAzS "Starting SSL Inspection Tests`n" Write-HostAzS "Date/Time = $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')" Write-HostAzS "Performing test from hostname: $($env:COMPUTERNAME)`n" } process { do { $Request = $null $Response = $null $Request = [System.Net.HttpWebRequest]::Create($url) $Request.Method = "GET" $Request.AllowAutoRedirect = $False $Request.Proxy = [System.Net.WebRequest]::DefaultWebProxy Write-HostAzS "Testing SSL/TLS Certificate for endpoint: '$($Request.Address.AbsoluteUri)'" try { [System.Net.HttpWebResponse]$Response = $Request.GetResponse() } catch { Write-HostAzS "Error: $($_.Exception.Message)" } # Check if the certificate subject contains "O=Microsoft" as most SSL inspection appliances will replace the certificate with their own if(($Request.ServicePoint.Certificate.Subject).Contains("O=Microsoft")){ Write-HostAzS -ForegroundColor Green "Expected Certificate Subject Found: `nSubject = $($Request.ServicePoint.Certificate.Subject)" } else { $SSLInspectionDetected = $true Write-HostAzS -ForegroundColor Red "UNKNOWN Certificate Subject Found: `nSubject = '$($Request.ServicePoint.Certificate.Subject)'" Write-HostAzS -ForegroundColor Yellow "`tNote: Expected Certificate Contains Subject = 'O=Microsoft'" } # Check if the certificate issuer contains "O=Microsoft Corporation" or "O=DigiCert Inc" as most SSL inspection appliances will replace the certificate with their own if(($Request.ServicePoint.Certificate.Issuer).Contains("O=Microsoft Corporation") -or (($Request.ServicePoint.Certificate.Issuer).Contains("O=DigiCert Inc"))){ Write-HostAzS -ForegroundColor Green "Expected Certificate Issuer Found: `nCertificate Issuer = $($Request.ServicePoint.Certificate.Issuer)" } else { $SSLInspectionDetected = $true Write-HostAzS -ForegroundColor Red "UNKNOWN Certificate Issuer Found: `nCertificate Issuer = '$($Request.ServicePoint.Certificate.Issuer)'" Write-HostAzS -ForegroundColor Yellow "`tNote: Expected Certificate Contains Issuer = 'O=Microsoft Corporation' or 'O=DigiCert Inc'" } # Root CA thumbprint validation: build the certificate chain and verify the root # against a known list of trusted Microsoft/DigiCert root CA thumbprints. # This provides a stronger check than string matching alone — a sophisticated # MITM could spoof Issuer/Subject strings but not root CA thumbprints. try { $cert2 = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($Request.ServicePoint.Certificate) $chain = New-Object System.Security.Cryptography.X509Certificates.X509Chain $null = $chain.Build($cert2) $rootCert = $chain.ChainElements[$chain.ChainElements.Count - 1].Certificate if ($script:TRUSTED_ROOT_CA_THUMBPRINTS -contains $rootCert.Thumbprint) { Write-HostAzS -ForegroundColor Green "Root CA Thumbprint Verified: $($rootCert.Thumbprint) ($($rootCert.Subject))" } else { $SSLInspectionDetected = $true Write-HostAzS -ForegroundColor Red "UNKNOWN Root CA Thumbprint: $($rootCert.Thumbprint)" Write-HostAzS -ForegroundColor Red "Root CA Subject: $($rootCert.Subject)" Write-HostAzS -ForegroundColor Yellow "`tNote: Root CA thumbprint does not match any known Microsoft/DigiCert root CAs" } } catch { Write-HostAzS -ForegroundColor Yellow "Warning: Unable to build certificate chain for root CA thumbprint validation: $($_.Exception.Message)" } # If $Response exists, check if for any redirects to further test required URLs if($Response){ if(-not([string]::IsNullOrWhiteSpace($Response.Headers["Location"]))){ Write-HostAzS "Checking Redirected URL, as 'HTTP StatusCode = $($Response.StatusCode)'" $url = $Response.Headers["Location"] } else { # No redirects found $RedirectsComplete = $true } $Response.Close() } else { # No response found, unable to determine if redirects are required $RedirectsComplete = $true } Write-HostAzS "" } while ( $RedirectsComplete -ne $true ) # End of do..while loop for redirects # Note: this test uses both string matching AND root CA thumbprint verification. # String matching checks Subject/Issuer for known Microsoft/DigiCert organizations. # Thumbprint matching validates the root certificate against known trusted root CA thumbprints # from $script:TRUSTED_ROOT_CA_THUMBPRINTS (defined in AzStackHci.Constants.ps1). Write-HostAzS -ForegroundColor Yellow "Note: This test verifies certificates by matching Subject/Issuer strings and root CA thumbprints." Write-HostAzS -ForegroundColor Yellow "It is not intended to be an exhaustive certificate validity test.`n" if($SSLInspectionDetected -eq $true){ Write-HostAzS -ForegroundColor Red "SSL Inspection Detected!`nCheck your network / proxy server configuration for SSL Inspection - https://learn.microsoft.com/en-us/azure-stack/hci/concepts/firewall-requirements`n" } else { Write-HostAzS -ForegroundColor Green "No SSL Inspection Detected :-)`n" } } # End of process block end { if ($NoOutput.IsPresent) { $script:SilentMode = $false } Write-HostAzS "SSL Inspection Tests Complete`n" # Write-Debug "Completed Test-AzStackHciSSLInspection function" return $SSLInspectionDetected } } # End of Test-AzStackHciSSLInspection function |