如何通过命令行验证 SSL 指纹?(wget,卷曲,...)

信息安全 tls
2021-08-21 18:17:50

wget使用命令行网站下载器,例如curl或任何其他... 在脚本中...

我有网站的 SHA-1 和 SHA-256 证书指纹。由于安全问题 ( 1 ) ( 2 ),我不想使用公共 SSL 证书颁发机构系统。指纹必须是硬编码的。

wget 之类的应用程序可以检查 SSL 指纹吗?

wget 没有这样的功能。( 3 )

使用wget --ca-certificate或者curl --cacert我将不得不运行我自己的本地证书颁发机构,我想阻止这种情况,因为这会增加很多复杂性。这也是非常困难的,以前没有人这样做过。( 4 )

没有任何工具,例如
download --tlsv1 --serial-number xx:yy:zz --fingerprint xxyyzz https://site.com

解决方案当然不能受到 TOCTOU 的攻击。( 5 ) MITM 可以让 openssl 客户端请求返回一个有效指纹,并篡改以下 wget 请求。

1个回答

新答案:

查看您的链接#4,您似乎已经调查了现有的实用程序并收到了您想要的内容必须进行编程的答案。这样做是相对微不足道的。以下 Perl 脚本将执行您想要的操作:

#!/usr/bin/perl
# Code snippets taken from Net::SSLeay documentation and mildly modified.
# Requires a newer version of SSLeay (tested with 1.48)
# Needless to say, verify correct $host and $fingerprint before testing!!!

use Net::SSLeay qw(get_https3);

$host = "www.google.com";
$port = 443;
$fingerprint = "C1:95:6D:C8:A7:DF:B2:A5:A5:69:34:DA:09:77:8E:3A:11:02:33:58";

($p, $resp, $hdrs, $server_cert) = get_https3($host, $port, '/');
if (!defined($server_cert) || ($server_cert == 0)) {
    warn "Subject Name: undefined, Issuer  Name: undefined";
} elsif (Net::SSLeay::X509_get_fingerprint($server_cert, "sha1") ne $fingerprint) {
    warn 'Invalid certificate fingerprint '
        .  Net::SSLeay::X509_get_fingerprint($server_cert, "sha1")
        . ' for ' . Net::SSLeay::X509_NAME_oneline(
             Net::SSLeay::X509_get_subject_name($server_cert));
} else {
    print $p;
}

正如 Net::SSLeay 文档中所述,此方法意味着在 HTTP 事务之后进行验证,因此如果您想在发送数据之前验证您正在与正确的服务器对话,则不应使用此方法。但是,如果您所做的只是决定是否信任您刚刚下载的内容(这听起来就像您来自参考文献#4),那很好。

旧答案:

您可以按照此处所述使用 openssl

以机智,

openssl s_client -connect <host>:<port> < /dev/null 2>/dev/null | openssl x509 -fingerprint -noout -in /dev/stdin

(旧答案是)已更新

正如@Gilles 所指出的,这不符合将证书验证与实际内容检索相结合的要求。

因为 openssl s_client 将证书信息和服务器响应结合到标准输出流中,所以不能简单地用于此目的。可能可以编写一个脚本,该脚本会根据一些简单的测试解析将组合输出和两者分开,但这并不完全是一个交钥匙解决方案。