Skip to content

Fingerprints von SSL-Seiten prüfen

Das Desaster um die niederländische Zertifizierungsstelle DigiNotar zieht derzeit immer noch seine Kreise. Mir scheint es noch zu früh, um hier etwas dazu zu schreiben. Vielmehr will ich ein paar Worte verlieren, wie ich „meine eigene CA betreibe“. Denn schon seit längerem vertraue ich nicht, den von den Browsern mitgelieferten Zertifizierungsstellen (CA). Zumeist lösche ich alle und gebe dann einzeln Vertrauen.

Der beste Weg, um einem SSL-Zertifikat zu vertrauen, wäre, sich bei dem Betreiber zu melden und über einen sicheren Kanal den Fingerprint des Zertifikats zu klären. Mein Browser zeigt mit für die Seite Wikipedia-SSL-Seite den Fingerprint (SHA-1) BA:8A:BE:34:B1:34:3B:AF:06:05:4B:48:A9:27:AA:D9:B4:75:45:6E an. Wenn ich bei der Wikipedia anrufe und diese mir denselben nennen, so habe ich das korrekte Zertifikat. Dabei nehme ich natürlich an, dass das Telefon ein sicherer Weg zum Austausch der Informationen ist. Aber beispielsweise druckt die lokale Sparkasse eben diesen Fingerprint auf ihre Dokumente. Damit kann ich das als Kunde leicht verifizieren.

Wie das Beispiel Wikipedia aber schon zeigt, ergibt sich da ein Problem.Woher bekomme ich den Fingerprint? Muss ich bei Jimmy Wales direkt anrufen oder gar nach FloridaKalifornien¹ reisen? Hier kam nun meine Idee ins Spiel.

Ich habe auf diversen Servern einen Zugang, d.h. ich kann mich von der Ferne einloggen und dann dort arbeiten. Die Rechner stehen in verschiedenen Netzen und zum Teil auf verschiedenen Kontinenten. Nun logge ich mich auf den Servern ein, lade das Zertifikat herunter und lasse mir den Fingerprint anzeigen. Wenn dieser auf allen Rechner gleich ist, dann gehe ich davon aus, dass ich das korrekte Zertifikat angezeigt bekomme. In dem Fall akzeptiere ich das und vertraue dem. Sollten die Fingerprints abweichen, dann akzeptiere ich das nicht und recherchiere dem in der Regel ein wenig hinterher.

Jörg Sommer hat das nun ein wenig automatisiert und ein zsh-Skript (Quelltext weiter unten) geschrieben. Das wird folgendermaßen aufgerufen:

ssl-fp-check [-l] sslsi.te[:port] ssh1 [ssh2] [ssh3] ...

Dabei ist sslsi.te die Webseite, die geprüft werden soll. Ohne die Angabe eines Ports verwendet das Skript standardmäßig 443. Danach wird eine oder mehrere SSH-Verbindungen angegeben. Das Skript wird nun versuchen, sich überall einzuloggen und gibt dann den Fingerprint aus. Für den Fall, dass es auf dem Zielsystem kein OpenSSL gibt, existiert die Option -l. Dabei wird dann ein Tunnel gebaut und das lokale installierte OpenSSL verwendet.

Also für Wikimedia habe ich folgendes eingeben:

ssl-fp-check secure.wikimedia.org a b c d
a: SHA1 Fingerprint=BA:8A:BE:34:B1:34:3B:AF:06:05:4B:48:A9:27:AA:D9:B4:75:45:6E
b: SHA1 Fingerprint=BA:8A:BE:34:B1:34:3B:AF:06:05:4B:48:A9:27:AA:D9:B4:75:45:6E
c: SHA1 Fingerprint=BA:8A:BE:34:B1:34:3B:AF:06:05:4B:48:A9:27:AA:D9:B4:75:45:6E
d: SHA1 Fingerprint=BA:8A:BE:34:B1:34:3B:AF:06:05:4B:48:A9:27:AA:D9:B4:75:45:6E

Die SSH-Server a, b, c und d gaben also denselben Fingerprint aus. Also würde ich dem ganzen doch vertrauen. :-)

Ich werde das Skript jetzt wahrscheinlich immer verwenden. Es macht das Leben doch deutlich einfacher.


#!/bin/zsh -fuC

# Get the fingerprint of a SSL-connection via SSH from different hosts to check
# that it’s the same from everywhere, i.e. there’s no or the same man in the
# middle.

ssh_local_port=13724

process_fp()
{
    if [[ ${#master_fp:-} -gt 0 && $master_fp != $1 ]]
    then
        print “\e[1m$1\e[0m”
    else
        print $1
    fi
    if [[ ${#master_fp:-} -eq 0 ]]
    then
        master_fp=$1
    fi
}

if [[ $1 == (-l|--local-openssl) ]]
then
    local_openssl=true
    shift
else
    local_openssl=false
fi

dest=$1
shift
hosts=( $@ )

if [[ $dest != *:* ]]
then
    dest+=:443
fi

if $local_openssl
then
    sock_dir=$(mktemp -d)
    trap ‘for i in $sock_dir/*(N); do ssh -S $i -O exit 2>/dev/null; done;
      rm -r $sock_dir’ EXIT INT TERM KILL

    for host in $hosts
    do
        ssh_socket=$sock_dir/$host
        if ssh -S $ssh_socket -NTf -o ExitOnForwardFailure=yes \
          -L ${ssh_local_port}:$dest $host
        then
            out=$(openssl s_client -connect localhost:$ssh_local_port \
              /dev/null \
              |openssl x509 -fingerprint -noout \
              || true)
            ssh -S $ssh_socket -O exit $host 2>/dev/null
            print -n “${host}: ”
            process_fp $out
        else
            print “connection to $host via ssh failed” >&2
        fi
    done
else
    for host in $hosts
    do
        out=$(ssh -n $host openssl s_client -connect $dest 2\>/dev/null \
          \|openssl x509 -fingerprint -noout \
          || true)
        print -n “${host}: ”
        process_fp $out
    done
fi

Trackbacks

No Trackbacks

Comments

Display comments as Linear | Threaded

Rainer on :

Und wie prüfst Du die Authentizität der ssh-Server? Beim ersten Connect in die known_hosts schreiben, sicher. Aber voher den Owner anrufen und den Fingerprint vorlesen lassen, sonst güldet das nicht!!!!
Und die known_hosts hast Du hoffentlich auf einem USB-Stick, dessen Schreibschutz Du nur eben zum Schreiben entfernst. Und bitte Hashsummen der known_hosts irgendwo in alt.anonymous oder so posten. Oder ein ewiges Logfile führen.
Übrigens sind Aluhüte sehr kleidsam! ;-)

Jens Kubieziel on :

Die meisten habe ich mal selbst installiert. Bei den anderen habe ich mit dem Admin irgendwann mal ein Keysigning gemacht und kann daher vertrauenswürdig kommunizieren. Nur in einem Fall bekam ich den Fingerprint als JPG-Bildchen in einer Mail.

Ich habe noch ein paar Hüte hier. Die schützen wirklich gut … :-)

Dominik on :

Einen ähnlichen ansatz verfolgt Perspectives: http://perspectives-project.org/

Add Comment

Enclosing asterisks marks text as bold (*word*), underscore are made via _word_.
Standard emoticons like :-) and ;-) are converted to images.
BBCode format allowed
E-Mail addresses will not be displayed and will only be used for E-Mail notifications.

To prevent automated Bots from commentspamming, please enter the string you see in the image below in the appropriate input box. Your comment will only be submitted if the strings match. Please ensure that your browser supports and accepts cookies, or your comment cannot be verified correctly.
CAPTCHA

You can use [geshi lang=lang_name [,ln={y|n}]][/geshi] tags to embed source code snippets.
Form options
cronjob