Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
PowerShell script to retrieve the public SSL certificate from a remote SSL endpoint
[CmdletBinding()]
param (
[Parameter(Mandatory=$true)]
[string]
$ComputerName,
[int]
$Port = 443
)
$Certificate = $null
$TcpClient = New-Object -TypeName System.Net.Sockets.TcpClient
try {
$TcpClient.Connect($ComputerName, $Port)
$TcpStream = $TcpClient.GetStream()
$Callback = { param($sender, $cert, $chain, $errors) return $true }
$SslStream = New-Object -TypeName System.Net.Security.SslStream -ArgumentList @($TcpStream, $true, $Callback)
try {
$SslStream.AuthenticateAsClient('')
$Certificate = $SslStream.RemoteCertificate
} finally {
$SslStream.Dispose()
}
} finally {
$TcpClient.Dispose()
}
if ($Certificate) {
if ($Certificate -isnot [System.Security.Cryptography.X509Certificates.X509Certificate2]) {
$Certificate = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Certificate2 -ArgumentList $Certificate
}
Write-Output $Certificate
}
@hertus

This comment has been minimized.

Copy link

@hertus hertus commented Jan 23, 2020

thanks

@msajeesh

This comment has been minimized.

Copy link

@msajeesh msajeesh commented Sep 13, 2020

This works perfectly but we have to enter server names manually..how to find out SSL certificate installed servers in a domain ?

@holgerjay

This comment has been minimized.

Copy link

@holgerjay holgerjay commented Nov 5, 2020

great, thank you!

@euyuil

This comment has been minimized.

Copy link

@euyuil euyuil commented Jan 7, 2021

Thanks! Do this work for SNI?

@jstangroome

This comment has been minimized.

Copy link
Owner Author

@jstangroome jstangroome commented Jan 7, 2021

@euyuil if line 23 $SslStream.AuthenticateAsClient('') is modified to pass a SNI host name instead of the empty string as its argument, it should work, but I have not verified.

@sahmedz11

This comment has been minimized.

Copy link

@sahmedz11 sahmedz11 commented Feb 2, 2021

Is there a timeout value or validation of certificate?

@jstangroome

This comment has been minimized.

Copy link
Owner Author

@jstangroome jstangroome commented Feb 3, 2021

@sahmedz11 As it is currently written, the script will use default .NET timeouts. You can augment the script to set $TcpClient.ReceiveTimeout or .SendTimeout to manage timeouts during the TLS handshake. There is also $SslStream.ReadTimeout and .WriteTimeout which could be set, but I'm not sure if these apply during the AuthenticateAsClient() call.

To implement a custom TCP connection handshake timeout, significant changes would be required to replace $TcpClient.Connect(...) with $TcpClient.BeginConnect(...) instead and implement an AsyncCallback which is possible in PowerShell but not something I have tried.

The script also very explicitly does not perform any certificate validation, its purpose is to return the certificate for deeper inspection, valid or not. However you can modify the $Callback = { ... } line to capture and report any validation errors, or perform additional custom validation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment