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
Kommentare
Ansicht der Kommentare: Linear | Verschachtelt
Rainer am :
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 am :
Ich habe noch ein paar Hüte hier. Die schützen wirklich gut …
Dominik am :