Get-CipherSuite.ps1
|
<#PSScriptInfo
.VERSION 1.0.2 .GUID 3f8b2a1c-7d4e-4f9a-b5c6-8e2d1a0f3b7c .AUTHOR Petar Ivanov .COMPANYNAME .COPYRIGHT (c) 2025 Petar Ivanov. All rights reserved. .TAGS TLS SSL Cipher Security Network Certificate HTTPS .LICENSEURI .PROJECTURI .ICONURI .EXTERNALMODULEDEPENDENCIES .REQUIREDSCRIPTS .EXTERNALSCRIPTDEPENDENCIES .RELEASENOTES Initial release - Analyzes TLS/SSL cipher suites on remote endpoints. Features: - Reports SSL/TLS protocol version, cipher algorithm, hash algorithm, and encryption details - Validates if the negotiated cipher suite is in the approved security list - Supports testing multiple endpoints simultaneously - Option to test all TLS/SSL versions (SSL3, TLS 1.0, 1.1, 1.2, 1.3) Examples: Get-CipherSuite.ps1 -Endpoints "gbl.his.arc.azure.com" Get-CipherSuite.ps1 -Endpoints "gbl.his.arc.azure.com" -TestAllVersions .PRIVATEDATA #> <# .SYNOPSIS TLS Cipher Suite Analyzer - Tests SSL/TLS cipher suites on remote endpoints. .DESCRIPTION This script connects to specified endpoints and analyzes the negotiated TLS/SSL cipher suites. It reports the protocol version, cipher algorithm, hash algorithm, and key exchange details. It also validates if the cipher suite is in the approved list. .PARAMETER Endpoints One or more hostnames or URLs to test. .PARAMETER Port The port to connect to. Default is 443. .PARAMETER TestAllVersions If specified, tests all TLS/SSL protocol versions (SSL3, TLS 1.0, 1.1, 1.2, 1.3). .EXAMPLE .\Get-CipherSuite.ps1 -Endpoints "gbl.his.arc.azure.com" .EXAMPLE .\Get-CipherSuite.ps1 -Endpoints "gbl.his.arc.azure.com", "agentserviceapi.guestconfiguration.azure.com", "westeurope-gas.guestconfiguration.azure.com" .EXAMPLE .\Get-CipherSuite.ps1 -Endpoints "myserver.com" -Port 8443 .EXAMPLE .\Get-CipherSuite.ps1 -Endpoints "gbl.his.arc.azure.com" -TestAllVersions .NOTES Author: Petar Ivanov Date: November 27, 2025 Version: 1.0.1 #> param( [Parameter(Mandatory=$true, Position=0)] [string[]]$Endpoints, [Parameter(Mandatory=$false)] [int]$Port = 443, [Parameter(Mandatory=$false)] [switch]$TestAllVersions ) function Get-EndpointCipherSuite { param( [string]$Endpoint, [int]$Port, [object]$SpecificProtocol = $null ) $cleanEndpoint = $Endpoint -replace '^https?://', '' -replace '/$', '' if ($null -eq $SpecificProtocol) { Write-Host "`nTesting: $cleanEndpoint`:$Port (Default/Best Available)" -ForegroundColor Cyan } else { Write-Host "`nTesting: $cleanEndpoint`:$Port ($SpecificProtocol)" -ForegroundColor Cyan } Write-Host ("-" * 60) try { $tcpClient = New-Object System.Net.Sockets.TcpClient $tcpClient.Connect($cleanEndpoint, $Port) if ($null -eq $SpecificProtocol) { $sslStream = New-Object System.Net.Security.SslStream($tcpClient.GetStream(), $false) $sslStream.AuthenticateAsClient($cleanEndpoint) } else { $sslStream = New-Object System.Net.Security.SslStream($tcpClient.GetStream(), $false, { param($sender, $certificate, $chain, $sslPolicyErrors) return $true }) $sslStream.AuthenticateAsClient($cleanEndpoint, $null, $SpecificProtocol, $false) } $sslProtocol = $sslStream.SslProtocol $cipherAlgorithm = $sslStream.CipherAlgorithm $cipherStrength = $sslStream.CipherStrength $hashAlgorithm = $sslStream.HashAlgorithm $keyExchangeAlgorithm = $sslStream.KeyExchangeAlgorithm $keyExchangeStrength = $sslStream.KeyExchangeStrength # Map key exchange enum to readable name $keyExchangeName = switch ($keyExchangeAlgorithm) { ([System.Security.Authentication.ExchangeAlgorithmType]::None) { "None" } ([System.Security.Authentication.ExchangeAlgorithmType]::RsaSign) { "RSA" } ([System.Security.Authentication.ExchangeAlgorithmType]::RsaKeyX) { "RSA" } ([System.Security.Authentication.ExchangeAlgorithmType]::DiffieHellman) { "DH" } 44550 { "ECDHE" } # ECDH Ephemeral default { $keyExchangeAlgorithm.ToString() } } Write-Host "SSL/TLS Protocol: $sslProtocol" -ForegroundColor Green Write-Host "Cipher Algorithm: $cipherAlgorithm ($cipherStrength bits)" -ForegroundColor Green Write-Host "Hash Algorithm: $hashAlgorithm" -ForegroundColor Green Write-Host "Key Exchange: $keyExchangeName ($keyExchangeStrength bits)" -ForegroundColor Green # Check if this is an approved cipher suite based on the components $isAllowed = $false if ($sslProtocol -eq 'Tls13') { # TLS 1.3 - check based on cipher and hash if (($cipherAlgorithm -like "*Aes256*" -and $hashAlgorithm -eq "Sha384") -or ($cipherAlgorithm -like "*Aes128*" -and $hashAlgorithm -eq "Sha256")) { $isAllowed = $true $cipherSuiteName = if ($cipherAlgorithm -like "*Aes256*") { "TLS_AES_256_GCM_SHA384" } else { "TLS_AES_128_GCM_SHA256" } } else { $cipherSuiteName = "TLS_1.3 (${cipherAlgorithm}_${hashAlgorithm})" } Write-Host "Cipher Suite: $cipherSuiteName" -ForegroundColor $(if ($isAllowed) { "Green" } else { "Yellow" }) } else { # TLS 1.2 - check based on key exchange, cipher, and hash # Approved: ECDHE + (AES256 or AES128) + (SHA384 or SHA256) if ($keyExchangeName -eq "ECDHE") { if (($cipherAlgorithm -like "*Aes256*" -and $hashAlgorithm -eq "Sha384") -or ($cipherAlgorithm -like "*Aes128*" -and $hashAlgorithm -eq "Sha256")) { $isAllowed = $true } } # Construct standard cipher suite name if ($keyExchangeName -eq "ECDHE" -and $cipherAlgorithm -like "*Aes256*" -and $hashAlgorithm -eq "Sha384") { $cipherSuiteName = "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384" } elseif ($keyExchangeName -eq "ECDHE" -and $cipherAlgorithm -like "*Aes128*" -and $hashAlgorithm -eq "Sha256") { $cipherSuiteName = "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" } else { $cipherSuiteName = "TLS_${keyExchangeName}_WITH_${cipherAlgorithm}_${hashAlgorithm}" } Write-Host "Cipher Suite (approx): $cipherSuiteName" -ForegroundColor $(if ($isAllowed) { "Green" } else { "Yellow" }) } $sslStream.Close() $tcpClient.Close() Write-Host "Status: $(if ($isAllowed) { 'ENABLED [OK] (APPROVED)' } else { 'ENABLED [WARNING] (NON-APPROVED)' })" -ForegroundColor $(if ($isAllowed) { "Green" } else { "DarkYellow" }) Write-Host "Cipher Suite Security: $(if ($isAllowed) { 'APPROVED [OK]' } else { 'NOT IN APPROVED LIST [X]' })" -ForegroundColor $(if ($isAllowed) { "Green" } else { "Red" }) return @{Connected = $true; Approved = $isAllowed} } catch { Write-Host "Status: DISABLED [X]" -ForegroundColor Red return @{Connected = $false; Approved = $false} } } Write-Host "`n========================================" -ForegroundColor Magenta Write-Host " TLS Cipher Suite Analyzer" -ForegroundColor Magenta Write-Host "========================================" -ForegroundColor Magenta foreach ($endpoint in $Endpoints) { if ($TestAllVersions) { Write-Host "`n$('=' * 60)" -ForegroundColor White Write-Host "ENDPOINT: $endpoint`:$Port - Testing All TLS Versions" -ForegroundColor White Write-Host "$('=' * 60)" -ForegroundColor White $protocols = @( @{Name = "SSL 3.0"; Value = [System.Security.Authentication.SslProtocols]::Ssl3}, @{Name = "TLS 1.0"; Value = [System.Security.Authentication.SslProtocols]::Tls}, @{Name = "TLS 1.1"; Value = [System.Security.Authentication.SslProtocols]::Tls11}, @{Name = "TLS 1.2"; Value = [System.Security.Authentication.SslProtocols]::Tls12}, @{Name = "TLS 1.3"; Value = [System.Security.Authentication.SslProtocols]::Tls13} ) $results = @() foreach ($protocol in $protocols) { $result = Get-EndpointCipherSuite -Endpoint $endpoint -Port $Port -SpecificProtocol $protocol.Value $results += [PSCustomObject]@{ Protocol = $protocol.Name Status = if ($result.Connected) { "ENABLED [OK]" } else { "DISABLED [X]" } Color = if ($result.Connected) { "Green" } else { "Red" } } } Write-Host "`n$('-' * 60)" -ForegroundColor White Write-Host "SUMMARY - Supported TLS Versions on $endpoint`:$Port" -ForegroundColor White Write-Host "$('-' * 60)" -ForegroundColor White foreach ($result in $results) { Write-Host "$($result.Protocol.PadRight(15)): " -NoNewline -ForegroundColor Yellow Write-Host $result.Status -ForegroundColor $result.Color } } else { Get-EndpointCipherSuite -Endpoint $endpoint -Port $Port } } Write-Host "`n========================================" -ForegroundColor Magenta Write-Host "Testing Complete!" -ForegroundColor Magenta Write-Host "========================================`n" -ForegroundColor Magenta |