I've found several answer about how to download the certificate for a website in PowerShell using TcpClient.
function Get-RemoteCertificate {
[CmdletBinding()]
[OutputType([System.Security.Cryptography.X509Certificates.X509Certificate])]
param (
[Parameter(Mandatory, ValueFromPipeline)]
[ValidateNotNull()]
[Uri]$Uri
)
process {
try {# connecting
$TcpClient = [System.Net.Sockets.TcpClient]::new($Uri.Host, $Uri.Port)
try {# getting SSL
$SslStream = [System.Net.Security.SslStream]::new($TcpClient.GetStream())
$SslStream.AuthenticateAsClient($Uri.Host)
$SslStream.RemoteCertificate
} finally {
$SslStream.Dispose()
}# end SSL
} finally {
$TcpClient.Dispose()
}# end connect
}
}
But as the TLS handshake will fail when the certificate isn't trusted, I can't download self signed certificates and I will get the error
Exception calling ".ctor" with "2" argument(s): "A connection attempt failed because the connected party did not
properly respond after a period of time, or established connection failed because connected host has failed to
respond
Is there a way to download self signed certificates without using OpenSSL?
CodePudding user response:
Without using your sample, you can achieve this simple task based on this answer
$ub = new-object System.UriBuilder -argumentlist 'https', '1.1.1.1', 443
$uri = $ub.Uri
# Disable the verification:
[Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
$req = [Net.HttpWebRequest]::Create($Uri.AbsoluteUri)
try {
$req.GetResponse() | Out-Null
# Export the file, or return it if you want to keep a function
$req.ServicePoint.Certificate.Export("Cert") | Set-Content -Path "C:\temp\test.crt" -Encoding Byte
} catch {
Write-Host Exception while checking URL $url`: $_ -f Red
}
CodePudding user response:
NOTE: This is considered dangerous and you should think about the possible negative side effects of using this technique.
You can use a different overload when instantiating [System.Net.Security.SslStream]
that ignores cert errors as shown here.
function Get-RemoteCertificate {
[CmdletBinding()]
[OutputType([System.Security.Cryptography.X509Certificates.X509Certificate])]
param (
[Parameter(Mandatory,ValueFromPipeline)]
[ValidateNotNull()]
[Uri]$Uri
)
process {
try {
$TcpClient = [System.Net.Sockets.TcpClient]::new($Uri.Host, $Uri.Port)
try {
$SslStream = [System.Net.Security.SslStream]::new(
$TcpClient.GetStream(),
$True,
[System.Net.Security.RemoteCertificateValidationCallback]{$true}
)
$SslStream.AuthenticateAsClient($Uri.Host)
$SslStream.RemoteCertificate
} finally {
$SslStream.Dispose()
}
} finally {
$TcpClient.Dispose()
}
}
}