security - How to verify the SSL fingerprint by command line? (wget, curl, ...)

21
2014-04
  • James Mitch

    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 or curl --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.

  • Answers
  • James Mitch

    Source

    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
    
  • James Mitch

    source

    #!/usr/bin/perl
    # http://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.

  • izx

    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

  • Related Question

    security - How do I make sure my IM client is using the right SSL certificate?
  • jrg

    Google's had fraudulent SSL certificates issued for their domains.

    enter image description here

    So, the question I have is, "How do I make sure Pidgin/Empathy trust the correct certificate?"


  • Related Answers
  • Justin Andrusk

    It really comes down to; who do you really trust? I personally would create my own self-signed certificate and would simply use that one. This is because I Know I created it and I was not relying on a third-party that could be or will be compromised. So then you would just need to trust yourself;)