在Invoke-WebRequest调用中信任自签名证书

时间:2019-05-22 13:02:06

标签: powershell https ssl-certificate powershell-core

问题

有没有一种我可以调用#!/bin/bash for portNumber in {57201..57206}; do destinationDirectory="destination/$portNumber" mkdir "$destinationDirectory" thePparameter="tcp port $portNumber" pcapsplitter -f 'file.pcapng' -o "$destinationDirectory" -m bpf-filter -p "$thePparameter" done 的方式,例如,期望证书的给定公钥来验证我是否信任连接?

如果没有,是否还有另一种方法可以调用webrequest并仅信任网页而不信任发行者或忽略证书检查?

问题

我想用Invoke-WebRequest加载网页。我尝试通过https连接到网页,并且服务器提供了自签名证书。

由于我的证书存储区Invoke-WebRequest中没有颁发者证书,将引发错误:

  
    

Invoke-WebRequest:根据验证过程,远程证书无效。

  

已知的解决方法

  1. 使用在Powershell v6.0.0 ref中添加的Invoke-WebRequest-Switch
  2. 添加新的证书策略以信任所有证书ref
  3. 信任发行人证书

我尝试过但没有解决的问题

  1. 在不信任颁发者证书的情况下将网页证书添加到证书存储中
  2. 将网页证书添加到证书存储,并使用-SkipCertificateCheck的{​​{1}}-参数指定此证书

PS:由于此问题同时出现在Powershell <5和Powershell Core中,因此我将它们都标记了出来。

2 个答案:

答案 0 :(得分:2)

我需要与我的Icinga2服务器建立可信连接,并找到了一种比较单个证书的方法。

这是存储[X509Certificate2]证书以进行比较并设置回调函数以验证证书的主要代码。

function set-SSLCertificate {
    param(
        $Cert
    )

    if (-not("validateCert" -as [type])) {
        add-type -TypeDefinition @"
            using System.Net.Security;
            using System.Security.Cryptography.X509Certificates;

            public static class ValidateCert {
                static X509Certificate2 MyCert;

                public static bool Validate(object sender,
                    X509Certificate cert,
                    X509Chain chain,
                    SslPolicyErrors sslPolicyErrors) {
                        if (MyCert.Equals(cert)) {
                            return true;
                        } else {
                            return false;
                        }
                }

                public static RemoteCertificateValidationCallback GetDelegate(X509Certificate2 Cert) {
                    MyCert = Cert;
                    return new RemoteCertificateValidationCallback(ValidateCert.Validate);
                }
            }
"@
    }
    [System.Net.ServicePointManager]::ServerCertificateValidationCallback = [validateCert]::GetDelegate($Cert)
}

您需要证书[X509Certificate2]。

我使用此功能来转换Base64格式的证书,该证书易于存储在变量中。

function get-x509 {
    param(
        [string]
            $Cert64
    )

    $CertBin=[System.Convert]::FromBase64String(($Cert64.Trim(" ") -replace "-.*-",""))

    [System.Security.Cryptography.X509Certificates.X509Certificate2]$CertBin
}

连接SSL服务器的整个过程:

[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]'Ssl3,Tls,Tls11,Tls12'

$SecPass = ConvertTo-SecureString $Pass -AsPlainText -Force
$Cred = New-Object System.Management.Automation.PSCredential($User, $SecPass)

$Cert = get-x509 $Cert64
set-SSLCertificate $Cert

Invoke-RestMethod -Uri $URL -Credential $Cred

要获取旧的行为,请执行以下操作:

[System.Net.ServicePointManager]::ServerCertificateValidationCallback = $null

答案 1 :(得分:1)

简短的回答,不,您无法解决它,当涉及到证书时,甚至不要尝试。客户端将首先查看证书以及整个证书链,以查看其是否受信任。如果该链的任何部分(例如发行者)不可信,那么它就是不可信的。如果这个基本事实没有发生,那么将没有办法撤销证书。

对于自签名证书,由于它们是不可信的,所以您是对的,实际上,客户端只有两种选择:

  1. 忽略证书来源,并使用-SkipCertificateCheck开关盲目连接。
  2. 接受颁发者和完整链可以被信任并导入证书

您无法绕开这个基本事实。我喜欢使用示例:自签名证书就像将炸弹状的对象交付给客户端,并在其上贴有“不是炸弹-相信我,我是@Paxz”的贴纸。证书链就像拿着炸弹状的物体一样,您看着交付驱动程序,它们看起来非常阴暗,同时看起来完全不像@Paxz。然后,您可以选择忽略标签,或者接受我可以信任@Paxz和可疑的传递驱动程序。未经明确同意,您不能只是将包裹推过前门。当您信任整个链时,标贴上会显示“不是炸弹-相信我,我已被炸弹专家验证”,因为您信任炸弹专家,因此客户将毫无疑问地接受该包裹。