Home > Enterprise >  How do I download the certificate from a web server that is self signed using PowerShell?
How do I download the certificate from a web server that is self signed using PowerShell?

Time:08-31

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()
        }
    }
}
  • Related