如何让 LWP 验证 SSL 服务器证书?
我如何获得 LWP 来验证我正在连接的服务器的证书是否由受信任的机构签名并颁发给正确的主机?据我所知,它甚至不检查证书是否声称用于我要连接的主机名.这似乎是一个主要的安全漏洞(尤其是最近的 DNS 漏洞).
How can I get LWP to verify that the certificate of the server I'm connecting to is signed by a trusted authority and issued to the correct host? As far as I can tell, it doesn't even check that the certificate claims to be for the hostname I'm connecting to. That seems like a major security hole (especially with the recent DNS vulnerabilities).
更新: 原来我真正想要的是 HTTPS_CA_DIR
,因为我没有 ca-bundle.crt.但是 HTTPS_CA_DIR=/usr/share/ca-certificates/
做到了.无论如何,我将答案标记为已接受,因为它已经足够接近了.
Update: It turns out what I really wanted was HTTPS_CA_DIR
, because I don't have a ca-bundle.crt. But HTTPS_CA_DIR=/usr/share/ca-certificates/
did the trick. I'm marking the answer as accepted anyway, because it was close enough.
更新 2: 事实证明,HTTPS_CA_DIR
和 HTTPS_CA_FILE
仅适用于使用 Net::SSL 作为底层 SSL 库的情况.但是 LWP 也适用于 IO::Socket::SSL,它会忽略这些环境变量并愉快地与任何服务器通信,无论它提供什么证书.有没有更通用的解决方案?
Update 2: It turns out that HTTPS_CA_DIR
and HTTPS_CA_FILE
only apply if you're using Net::SSL as the underlying SSL library. But LWP also works with IO::Socket::SSL, which will ignore those environment variables and happily talk to any server, no matter what certificate it presents. Is there a more general solution?
更新 3: 不幸的是,解决方案仍然不完整.Net::SSL 和 IO::Socket::SSL 都不会根据证书检查主机名.这意味着某人可以获得某个域的合法证书,然后在 LWP 不抱怨的情况下冒充任何其他域.
Update 3: Unfortunately, the solution still isn't complete. Neither Net::SSL nor IO::Socket::SSL is checking the host name against the certificate. This means that someone can get a legitimate certificate for some domain, and then impersonate any other domain without LWP complaining.
更新 4: LWP 6.00 终于解决了问题.有关详细信息,请参阅我的答案.
Update 4: LWP 6.00 finally solves the problem. See my answer for details.
这个长期存在的安全漏洞终于在 libwww-perl.从该版本开始,默认情况下 LWP::UserAgent 验证 HTTPS 服务器是否提供有效证书匹配预期的主机名(除非 $ENV{PERL_LWP_SSL_VERIFY_HOSTNAME}
设置为 false 值,或者,如果根本没有设置该变量,则为了向后兼容,$ENV{HTTPS_CA_FILE}
> 或 $ENV{HTTPS_CA_DIR}
已设置).
This long-standing security hole has finally been fixed in version 6.00 of libwww-perl. Starting with that version, by default LWP::UserAgent verifies that HTTPS servers present a valid certificate matching the expected hostname (unless $ENV{PERL_LWP_SSL_VERIFY_HOSTNAME}
is set to a false value or, for backwards compatibility if that variable is not set at all, either $ENV{HTTPS_CA_FILE}
or $ENV{HTTPS_CA_DIR}
is set).
这可以通过 LWP::UserAgent 的新 ssl_opts 选项控制.有关如何定位证书颁发机构证书的详细信息,请参阅该链接.但是小心,LWP::UserAgent 过去的工作方式,如果你向构造函数提供了一个 ssl_opts
哈希,那么 verify_hostname
默认为 0 而不是 1.(这个错误 已在 LWP 6.03 中修复.)为了安全起见,始终指定 verify_hostname =>1
在您的 ssl_opts
中.
This can be controlled by the new ssl_opts option of LWP::UserAgent. See that link for details on how the Certificate Authority certificates are located. But be careful, the way LWP::UserAgent used to work, if you provide a ssl_opts
hash to the constructor, then verify_hostname
defaulted to 0 instead of 1. (This bug was fixed in LWP 6.03.) To be safe, always specify verify_hostname => 1
in your ssl_opts
.
所以 use LWP::UserAgent 6;
应该足以验证服务器证书.
So use LWP::UserAgent 6;
should be sufficient to have server certificates validated.