How to verify the SSL fingerprint by command line? (wget, curl, ...)
Solution 1
Install required software:
apt-get install ca-certificates curl
Download the public SSL certificate:
openssl s_client -connect torproject.org:443 -CAfile /usr/share/ca-certificates/mozilla/DigiCert_Assured_ID_Root_CA.crt >./x.cert </dev/null
Or better:
echo -n | openssl s_client -connect torproject.org:443 -CAfile /usr/share/ca-certificates/mozilla/DigiCert_Assured_ID_Root_CA.crt | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > ./torproject.pem
Get SHA-1 fingerprint:
openssl x509 -noout -in torproject.pem -fingerprint -sha1
Get SHA-256 fingerprint:
openssl x509 -noout -in torproject.pem -fingerprint -sha256
Manually compare SHA-1 and SHA-256 fingerprints with torproject.org FAQ: SSL.
.
Optionally render the ca-certificates useless for testing purposes. Using curl here, but wget has a bug Bug and uses the ca-files anyway.
sudo mv /usr/share/ca-certificates /usr/share/ca-certificates_
Download with curl and the pinned certificate:
curl --cacert ./torproject.pem https://check.torproject.org/ > check.html
Solution 2
In tcsh:
echo | openssl s_client -connect host.example.com:443 |& openssl x509 -fingerprint -noout
Solution 3
This is also enough:
openssl x509 -fingerprint -in server.crt
Solution 4
This is fairly easy to do with the openssl
command and its client functionality.
The following little script will take a given domain (no https prefix) and an SHA-1 fingerprint, and exit with no error (0) if the retrieved fingerprint matches, but with exit code 1 if there is no match. You can then incorporate it into your script by simply testing the last exit code $?
:
#!/bin/bash
FPRINT=`echo -n | openssl s_client -connect $1:443 2>/dev/null \| openssl x509 -noout -fingerprint | cut -f2 -d'='` if [ "$2" = "$FPRINT" ]; then exit 0 else exit 1 fi
Solution 5
#!/usr/bin/perl
# https://security.stackexchange.com/questions/20399/how-to-verify-the-ssl-fingerprint-by-command-line-wget-curl
# 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;
}
As is outlined in the Net::SSLeay documentation, this method means verification after the HTTP transaction, and so should not be used if you want to verify you're talking to the right server before sending them data. But if all you're doing is deciding whether or not to trust what you just downloaded (which is sounds like you are from your reference #4) this is fine.
Related videos on Youtube
James Mitch
Hello everyone here, call me james. I am running Connecting Cool news and I like to invite everyone to visit the site every single day. I like stackoverflow because it is my chance to learn this.
Updated on September 18, 2022Comments
-
James Mitch over 1 year
Using a command line website downloader, such as
wget
,curl
or any other one... In a script...I have the SHA-1 and the SHA-256 certficate fingerprint of a website. Due to security concerns (1) (2), I don't want to use the public SSL certificate authority system. The fingerprint must be hard coded.
Can a wget like application check the SSL fingerprint?
wget does not have such a functionality. (3)
Using
wget --ca-certificate
orcurl --cacert
I would have to run my own local certificate authority, which I'd like to prevent, because that adds a lot complexity. It's also ultra difficult and no one did that ever before. (4)Isn't there any tool, like
download --tlsv1 --serial-number xx:yy:zz --fingerprint xxyyzz https://site.com
?The solution must of course not be vulnerable to TOCTOU. (5) The MITM could let return a valid fingerprint for the openssl client request and tamper with the following wget request.
-
Haider over 9 yearsVisitors: do note that this was cross-posted to the infosec SE. One of the self-answers was copied from there. This is frowned-upon behaviour, btw.
-
-
James Mitch over 11 yearsIt's vulnerable to TOCTOU. [1] The MITM could let return a valid fingerprint for the openssl client request and tamper with the following wget request. [1] en.wikipedia.org/wiki/Time_of_check_to_time_of_use
-
ish over 11 yearsTrue, in theory. It would be fairly easy to modify
wget
and compile it with OpenSSL so that it performs what you want inline, but that is beyond the scope of an AU answer. -
taneli over 11 yearsSo, how about using s_client to also retrieve the document? Something like
(echo -ne "Host: ${HOST}\n\rGET ${URL}\n\r" && yes) 2>/dev/null | openssl s_client -connect ${HOST}:443
should work, no? Well, you have to split the SSL session info from the actual content reply. -
Frederick Nord about 9 yearsthis doesn't work in the presence of a proxy, though :-/
-
number5 over 8 yearsworks in
zsh
, should work for bash too -
Lars over 6 yearsPlease note that the -CAfile option is completely ignored in your example.
-
林果皞 almost 6 yearsAdd
-md5
option to retrieve MD5 Fingerprint.-md5
must not put in between-in
andserver.crt
.