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).
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.
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?
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.
Update 4: LWP 6.00 finally solves the problem. See my answer for details.
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).
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
.
So use LWP::UserAgent 6;
should be sufficient to have server certificates validated.