Verteilte Erkennung von fehlgeschlagenen SSH-Loginversuchen

From
Revision as of 13:54, 11 October 2014 by Mattes (talk | contribs)
Jump to navigation Jump to search

Die derzeitige Situation

Auf den über SSH zugänglichen Rechnern (Gruenau- und Vogel-Rechner) laufen zwei verschiedene Betriebssysteme – OpenSUSE (Linux) und Solaris.

Die Behandlung fehlgeschlagener SSH-Loginversuche ist je nach Betriebssystem etwas unterschiedlich implementiert.

OpenSUSE

Fehlgeschlagene SSH-Logins werden unter OpenSUSE vom System in /var/log/btmp protokolliert. Ältere Einträge können sich auch in /var/log/btmp.* befinden. btmp ist üblicherweise nur für root les- und beschreibbar.

Das Shell-Skript /usr/bin/check-sshd wird in regelmäßigen Abständen von crond aufgerufen. Es listet alle btmp-Einträge mit Hilfe des Befehls lastb -a -i auf.

Ausschnitt aus einer Ausgabe von \emph{lastb -a -i} unter Linux (hier Ubuntu~14.01:

oliversc ssh:notty    Thu Oct  2 11:22 - 11:22  (00:00)     141.20.198.10
derp     ssh:notty    Thu Oct  2 11:17 - 11:17  (00:00)     141.20.193.124
maximili ssh:notty    Thu Oct  2 11:17 - 11:17  (00:00)     141.20.192.234
admin    ssh:notty    Wed Oct  1 15:43 - 15:43  (00:00)     61.174.50.225
bizz     ssh:notty    Wed Oct  1 15:32 - 15:32  (00:00)     127.0.0.1

lastb -a -i liefert einen btmp-Eintrag pro Zeile in Textform. Das erste Feld enthält den beim Login-Versuch verwendeten Benutzernamen, z.B. „derp“. Das zweite Feld gibt das Gerät an, von dem aus der Login vorgenommen wurde, im Falle von SSH-Logins „ssh:notty“. Die folgenden Felder geben das Datum und die Uhrzeit des Loginversuchs an. Das letzte Feld die IP-Adresse des entfernten Rechners. Die IP-Adresse kann als IPv4- oder IPv6-Adresse ausgegeben werden. Aus der Ausgabe von lastb filtert das Skript nur das letzte Feld, also die IP-Adresse, heraus.

Das Skript sucht nach IP-Adressen, die mindestens -mal direkt aufeinander folgen, wobei eine im Skript festgelegte Konstante ist. Diese IP-Adressen werden behalten, alle anderen verworfen.

Alle von iptables blockierten Adressen werden entfernt.

Danach werden Adressen der Netzwerke 141.20.0.0/16 (Humboldt-Universität) und 127.0.0.0/8 (Loopback), sowie weitere Adressen, die in /etc/hosts der Humboldt-Universität zugeordnet sind, aus der Liste entfernt.

Die übrigen Adressen werden über einen Aufruf von iptables auf unbegrenzte Zeit für SSH (TCP, Port 22) blockiert.

Solaris

Unter Solaris werden fehlgeschlagen SSH-Loginversuche vom System in der Datei /var/log/sshd.log protokolliert. Ältere Einträge können sich auch in /var/log/sshd.log.* befinden. Die Logdateien sind üblicherweise nur für root les- und beschreibbar.

Ausschnitt aus /var/log/sshd.log unter Solaris:

Aug  8 04:48:12 eule sshd[25199]: [ID 800047 local7.notice] Failed none for root from 141.20.198.10 port 1204 ssh2
Aug  8 04:48:12 eule sshd[25199]: [ID 800047 local7.notice] Failed password for root from 141.20.193.124 port 1204 ssh2
Aug  8 04:48:16 eule sshd[25199]: [ID 800047 local7.info] Disconnecting: Too many authentication failures for root
Aug  8 21:08:20 eule sshd[9925]: [ID 800047 local7.info] Illegal user admin from 141.20.192.234
Aug  8 21:08:20 eule sshd[9925]: [ID 800047 local7.info] Failed none for <invalid username> from 61.174.50.225 port 55581 ssh2
Aug  8 21:08:21 eule sshd[9925]: [ID 800047 local7.info] Failed keyboard-interactive for <invalid username> from 141.20.198.10 port 55581 ssh2

crond ruft regelmäßig das Shell-Skript /usr/sbin/check-sshd auf.

Das Skript filtert diejenigen Zeilen heraus, die die Zeichenketten „Failed keyboard-interactive“, „Illegal user“, „Failed password for <invalid“ oder „Failed password for“ enthalten. Da die Zeilen kein einheitliches Format besitzen, wird anhand dieser Zeichenketten entschieden, an welcher Position sich die IP-Adresse des entfernten Rechners befindet. Die Adresse wird extrahiert.

Das Skript sucht nach IP-Adressen, die mindestens -mal direkt aufeinander folgen, wobei eine im Skript festgelegte Konstante ist. Diese IP-Adressen werden behalten, alle anderen verworfen.

Wie unter OpenSUSE werden Adressen der Netzwerke 141.20.0.0/16 und 127.0.0.0/8 aus der Liste entfernt. Einträge in /etc/hosts werden allerdings nicht beachtet.

Alle von ippool blockierten Adressen werden entfernt.

Die restlichen Adressen werden mit Hilfe von ippool auf unbegrenzte Zeit blockiert.

Problemanalyse und Design

Erkennung von Angriffen

Da die Rechner derzeit nicht miteinander kommunizieren, werden Angriffe nur von einzelnen Rechnern erkannt. Die IP-Adresse des Angreifers wird lokal blockiert.

Local detection and blocking.png

Es wird gewünscht, dass ein auf einem Rechner erkannter Angriff dazu führt, dass die Angreiferadresse möglichst schnell auf allen Rechnern blockiert wird.

Distributed detection and blocking 1.png

Außerdem sollen aufeinanderfolgende, fehlgeschlagene Loginversuche an mehreren Rechnern, genauso als Angriff erkannt werden, als wären sie auf einem einzigen Rechner durchgeführt worden.

Distributed detection and blocking 2.png

Client-Server-Architektur

Beim Austausch von Daten über NFS würde der Komplexität der Netzwerkkommunikation von NFS übernommen. Die einzelnen Rechner könnten Daten über fehlgeschlagene Loginversuche in eigene Dateien schreiben. Die anderen Rechner könnten die Daten leicht auslesen. Wenn es möglich wäre, dass die Rechner über Änderungen an den Dateien informiert würden, z.B. über select oder inotify, könnten verteilte Angriffe schnell erkannt und blockiert werden. Ist das nicht möglich, müssen die Daten in regelmäßigen Abständen ausgetauscht werden, was einem Angreifer ein größeres Zeitfenster zwischen erstem Versuch und Blockieren lassen würde.

Eine rein verteilte Lösung ohne Server würde vermutlich eine komplexe Kommunikation zwischen den Rechnern erfordern. Jeder Rechner müsste alle anderen über Loginversuche informieren, was möglicherweise zu stärkerem Netzwerkverkehr führen würde, als bei den anderen Lösungen. Die Menge der beteiligten Rechner müsste verwaltet werden. Alle Rechner müssten für ihre Kommunikation einen bekannten Port öffnen.

Bei mehreren Clients und einem zentralen Server wäre die Kommunikation zwischen den Clients und dem zentralen Server etwas einfacher. Der Server könnte alle Daten über Loginversuche von den Clients annehmen, darin Angriffe erkennen und dann die Clients darüber informieren. Wenn die Clients die Verbindung zum Server aufbauen, bräuchten sie keinen eigenen Server-Port. Die Verbindung kann dauerhaft gehalten werden. Dadurch kennt der Server immer alle beteiligten Clients, die er informieren muss. Angriffe könnten unmittelbar erkannt und blockiert werden. Im Falle eines Serverausfalls könnten die Clients auf eine lokale Erkennung zurückfallen, so wie derzeit schon implementiert.

In Abwägung der Vor- und Nachteile der einzelnen Lösungen, haben wir uns für eine Client-Server-Lösung entschieden, wobei auch die NFS-Lösung sehr vielversprechend aussah. Da das Institutsnetzwerk sehr stabil ist, bestünde auch nur geringe Gefahr, dass der Server ausfiele und damit die verteilte Erkennung lahmlege.