Tiny Private Threat Response (tPTR) zur Absicherung des heimischen Mac

Einleitung

Wer wie ich daheim einen Mac betreibt und auf seinem Gerät z. B. Port 22 für ssh und Port 80 für einen Webserver geöffnet hat, wird evtl. bereits festgestellt haben, dass die Angriffsversuche seit Corona noch einmal zugenommen haben. Haben Sie bisher noch keinen Blick auf die entsprechenden Log-Dateien geworfen, empfiehlt es sich jetzt:

  • das Apache Log befindet sich in einer Catalina Standardinstallation in "/var/log/apache2/access.log" und kann mit jedem Administrator Account durch Eingabe von
    "less /var/log/apache2/access.log" eingesehen werden

  • das ssh Log ist in macOS etwas weniger leicht unzugänglich, kann aber mit
    "log show --info --source --predicate 'processImagePath contains[c] "sshd"' --style syslog --start 2020-04-25"
    eingesehen werden, natürlich sollte als Startdatum ein angepasstes, sinnvolles gesetzt werden

 

Und so entsteht der Wunsch, die eigene Umgebung besser abzusichern, dabei aber auch nicht gleich mit der ganz großen Kanone zu schießen: Natürlich hat das macOS eine eingebaute Firewall, dieser aber dedizierte Regeln beizubringen, ist zumindest über das UI Panel nicht möglich - eingehende (oder ausgehende) Verbindungen können lediglich zugelassen oder verboten werden. Aber was nützt eine Webseite, die von niemandem mehr erreicht werden kann ?

Allerdings bietet macOS mit pf einen Paketfilter, der dem aus der Linuxwelt bekannten iptables funktional ähnelt. Und diesen habe ich mir für eine dynamisch angepasste Absicherung zu Nutze gemacht und so eine kleine private Threat Response aufgebaut, die grundsätzlich erst einmal weltweite Zugriff lässt, aber mit Hilfe ein paar kleiner Scripte innerhalb weniger Sekunden attackierende IP Adressen blockiert.

Um es vorweg zu nehmen: die hier vorgestellten Scripte, erforderlichen Listen von IP Adressen, eine Beispiel Konfiuration für pf, sowie 2 Scripte für Installation / Deinstallation sind alle in der ZIP Datei enthalten und können nach Installation und ganz wenigen Anpassungen sofort eingesetz werden. Eine detaillierte Übersicht aller Dateien findet sich am Ende dieser Seite.

Download v2020-05-08/tPTR.mac.2020-05-08.01.zip

 

Nachstehender Screenshot verdeutlicht die aktuelle Situation anhand einer Auswertung von Angriffsversuchen auf den Webserver im April (Hitlisten Anführer war übrigens eine chinesische IP Adresse mit 943 Versuchen in gut 10 Minuten). Die Auswertung ist mit der freien Version von splunk>enterprise von Splunk Inc. und bei geöffnetem Paketfilter erstellt worden.

Bildschirmfoto_2020-04-30_um_09.07.04.png

 

Die Lösung in der Übersicht

Ein Perl Programm (mini_weblog_crawler.pl) wertet periodisch (Frequenz einstellbar) das access.log des Webservers nach HTTP Response Codes >= 400 aus. Hierbei wird eine (in Stunden oder Minuten) einstellbare Zeit im Log zurück geschaut (Lookback Time) und die Versuche pro IP Adresse werden gezählt. Überschreitet diese Anzahl den einstellbaren Schwellwert (Threshold), wird die IP Adresse für die Blocking Rule des Paketfilters ausgegeben. Dabei kann das Perl Programm entweder die einzelne IP Adresse zurückliefern oder über whois das zugehörige Netzwerk ermitteln und ausgeben (Scope).

Zusätzlich wird die IP Adresse in ein Register eingetragen und so für einen einstellbaren Zeitraum (Block Duration) geblockt, da das Register am Anfang immer wieder eingelesen und das Blockade Ende mit der aktuellen Zeit vergleicht.

Das Perl Programm ist von einem Shell Script ummantelt, welches die Parameter prüft, das Programm aufruft, die IP Adressliste dem Paketfilter übergibt und den Paketfilter im Anschluss zwingt, die neue Konfiguration einzulesen und zu verwenden.

Eine plist sorgt dafür, dass dieser Ablauf mit dem Apple Werkzeug launchctl periodisch ausgeführt wird. Alle Aktionen (blocken, entblocken, Fehlermeldungen) werden von dem Wrapper-Script sowohl in eine eigene Logdatei ('/var/log/mini_weblog_crawler.log') geschrieben, als auch mit dem Systemwerkzeug logger in die Logging Datenbank von macOS protokolliert und können hier wiederum mit den entsprechenden Werkzeugen ausgewertet werden.

Die Parameter Ausführungsfrequenz, Threshold, Lookback Time, Scope und Block Duration werden an späterer Stelle ausführlich diskutiert.

 

Basiskonfiguration von pf

In der Basiskonfiguration definiert Apple lediglich anchor Punkte für die eigene (com.apple) Domäne. Hier gilt es anzusetzen. Nachfolgender Screenshot zeigt eine beispielhafte Konfiguration für pf (die orange hervorgehobene zweite Hälfte der Datei):

Bildschirmfoto_2020-05-06_um_09.02.15.png

 

Grundsätzliche Überlegungen im Vorwege

Für mich ist die zu erreichenden Ziele wie folgt zu umreißen:

  • Port 22 (ssh) soll grundsätzlich blockiert sein, außer aus deutsch-sprachigen Netzwerken (weil ich mich hier öfter aufhalte) und im internen Netz natürlich
  • Port 80 (Webserver) soll grundsätzlich verfügbar sein, außer für IP Adressen, die sich angriffslustig zeigten

Anmerkung: Es ist noch ein auskommentiertes 'block drop ... all' enthalten, um ggf. schnell und ohne große Editierarbeit alle Zugriffe zu blockieren. Dies ist lediglich ein wenig der eigenen Paranoia und Faulheit geschuldet. :-)

Um die Konfigurationsdatei möglichst übersichtlich zu halten, habe ich

  • die betroffenen Netzwerkinterfaces in einer Liste zusammengefasst 'ext_if_list = "{en0, en1, en2, en3}"'
  • eine Tabelle für die IP Adressen der Angreifer definiert und persistiert 'table <badguys> persist file "/etc/pf.badguys"' (diese ist aber anfangs leer)
  • die IP Adressen der "deutsch-sprachigen" Netzwerke in 3 Tabellen ausgelagert, deren Pfad und Name in der jeweiligen
    'table <goodguysXX> persist file <file_name>' Anweisung definiert sind, wobei XX das zweibuchstabige Länderkürzel darstellt.
    (Adresslisten dieser Art lassen sich im Internet finden, müssen für die Verwendung mit pf allerdings ein wenig editiert werden. Daher habe ich auch diese im Downloadbereich abgelegt und werde sie dort regelmäßig aktualisieren.)

Im Anschluss folgen die Blocking Rules, deren erste wie bereits gesagt auskommentiert ist und alles abriegelt.

Die zweite Regel 'block drop in on $ext_if_list proto tcp from any to any port 22' blockiert erst einmal jeden Zugriff über TCP auf Port 22 (ssh). 

Das spannende ist die dritte Regel 'block drop in on $ext_if_list from <badguys> to any'. Hierdurch werden alle in der Tabelle 'badguys' enthaltenen IP Adressen vollständig blockiert. Die dieser Tabelle zugrunde liegende Datei wird von dem Perl Programm nach Auswertung des access.log des Webservers periodisch neu erzeugt und bildet somit das Herzstück der tiny Private Threat Response (tPTR).

Daran schließen sich die 'pass in ...' Regeln an, die es einigen Netzwerken gezielt erlauben, zuzugreifen, egal was ansonsten geblockt ist.

Wichtig:

Soll alles geblockt werden (siehe auch auskommentierte Block All Regel weiter oben), müssen natürlich auch zumindest die letzten drei Einträge der "goodguys" auskommentiert werden (!).

 

Installation und Deinstallation

Installation - Automatischer Teil

Mithilfe des halbautomatischen Installationsscripts 'install_tPTR_mac.sh' ist die Installation relativ einfach erledigt und geht aufgrund der geringen Größe der Objekte sehr schnell vonstatten. Scripte werden nach '/usr/local/sbin' kopiert und der Pfad ggf. vorher erzeugt. Auf diese Weise gibt es keine Probleme mit den von Apple vorgesehen Standardverzeichnissen. 

Die IP Adresslisten für die Länder DE, AT und CH namens 'pf.ip_addresses.xx.lst' werden in das Verzeichnis '/etc' kopiert und dürften dort ebenfalls mit nichts kollidieren. Zusätzlich werden die ebenfalls erforderlichen, anfangs leeren Dateien 'pf.badguys' und 'pf.ip_register' erzeugt.

Danach folgen die etwas aufwändigeren und teils manuellen Schritte der Installation: das Editieren der Konfigurationsdateien. Insbesondere für die Konfiguration des Paketfilters ist hier Obacht angesagt.

(Anm. an dieser Stelle: die Entwicklung einer vollautomatischen Installationsroutine, welche ggf. vorhandene Ausprägungen der Konfigurationsdatei von pf mit berücksichtigt, war in der gegebenen Zeit nicht möglich und hätte vom Aufwand her auch alles andere weit in den Schatten gestellt. Insofern müssen Sie an dieser Stelle leider selbst ein wenig Hand anlegen.)

Jeder dieser drei Schritte wird mit einer Frage an den Benutzer eingeleitet. Das Script wartet mit der Ausführung auf die Antwort. Für die erforderlichen Bearbeitungsschritte werden die Editoren vi, nano oder TextEdit zur Auswahl angeboten. Bei beiden Bearbeitungssequenzen ist bei Verwendung von  TextEdit unbedingt darauf zu achten, dass der Editor nicht mit einem Klick auf den Schließknopf, sondern definitiv mit ALT+Q bzw. Auswahl der Funktion "beenden" beendet wird, da das aufrufende Shell-Script  sonst kein Signal über die erfolgreiche Beendigung des Editors bekommt (bei vi bzw. nano ist das nicht der Fall).

 

Installation - Manueller Schritt 1

Im ersten Schritt muss die Konfigurationsdatei '/etc/pf.conf' modifiziert werden. Bevor das geschieht, wird eine Sicherungskopie der existierenden Datei erstellt. Danach wird die mit ausgelieferte Beispiel-Konfigurationsdatei mit TextEdit angezeigt. Parallel dazu wird die bereits vorhandene, i.d.R. im Basiszustand befindliche Konfigurationsdatei mit dem Texteditor Ihrer Wahl angezeigt. Normalerweise müssen nur die Zeilen der unteren Hälfte von der Beispiel-Datei in die Originalversion kopiert werden. Hierzu einfach in der Originalversion eine neue Zeile einfügen und dann mit Copy & Paste (CMD+C; CMD+V) den Inhalt aus der Beispieldatei markieren, kopieren und einfügen. Wie in obigem Screenshot zu erkennen, sind die zu kopierenden Zeilen ja durch einen entsprechenden Hinweis gekennzeichnet.

 

Installation - Manueller Schritt 2

Im zweiten Schritt werden die Ausführungsparameter des mini_weblog_crawler.pl in der plist gesetzt. Auch hierzu werden wieder die drei bereits bekannten Editoren zur Auswahl angeboten und im Fall der Verwendung von TextEdit gilt für die Beendigung desselben erneut: ALT+Q (keinesfalls den Schließknopf betätigen).

Diese Datei ist im XML Format und kann an folgenden Stellen angepasst werden (blau hervorgehoben):

scn_03.plist.png

 

Anzupassen sind hier eventuell

    1. Pfad und Name der Logdatei des Webservers 
    2. Schwellwert (Threshold) für die Anzahl von Angriffsversuchen ab der die angreifende IP Adresse blockiert wird
      Format: numerisch, im Bereich 1-99999
    3. Scope, gibt an ob nur einzelne IP Adressen (i) oder ganze Netzwerke (n) blockiert werden sollen
      Format: character, i | n
    4. Lookback Time, gibt an, wieweit im Webserver Log zurück geschaut werden soll, um mit der Zählung von Ereignissen mit HTTP Response Code >= 400 zu beginnen
      Format: numerisch
    5. Lookback Time Unit, Zeiteinheit des Wertes Lookback Time (4.) in Stunden (H) oder Minuten (M)
      Format: character H | M
    6. Block Duration, Dauer der Blockade der IP Adresse / des Netzwerkes; hier Zeitwert und Einheit Stunden (h) oder Minuten (m) zusammen
      Format: 1..99h|m

Wer mag, kann auch die Werte 'RunAtLoad' (am Anfang der plist) und 'StartInterval' unterhalb der blauen Markierung anpassen.

Mit dem Schalter 'RunAtLoad' wird spezifiziert, ob dieser Prozess von macOS beim Neustart mit gestartet wird oder nicht ('false') und der Wert 'StartInterval' bestimmt das Ausführungsintervall in Sekunden.

Während 'RunAtLoad' = 'false' wenig Sinn macht, da man bei jedem Neustart des Rechners selbst daran denken müsste den Paketfilter pf wieder neu zu starten, kann die Einstellung von 'StartInterval' in Ihrem Kontext durchaus angebracht sein.

Auf die Implikationen der einzelnen Werte gehe ich weiter unten ein.

 

Installation - Manueller Schritt 3

Als letztes fragt das Installationsscript dann, ob der Paketfilter aktiviert werden soll oder nicht. Im Fall der Aktivierung wird der Paketfilter pf nun per launchctl gestartet und wie eingestellt periodisch ausgeführt. In beiden Fällen ist die Installation damit abgeschlossen.

Ein Blick in die verschiedenen Files nach einer gewissen Laufzeit und natürlich abhängig von der Anzahl von Angriffen, denen Sie sich ausgesetzt sehen, zeigt sich folgendes Bild:

scn_04.logview.png

 

Deinstallation

Um die tiny Private Threat Response (tPTR) wieder vom System zu entfernen, reicht der Aufruf des Scripts 'uninstall_tPTR_mac.sh' (mit sudo) völlig aus. Das Script führt folgende Schritte aus:

  • stoppen des Paketfilters, wiederherstellen der ursprünglich Konfigurationsdatei '/etc/pf.conf' (sofern die Sicherungsdatei noch vorhanden ist) und neu starten des Paketfilters mit neuer (alter) Konfigurationsdatei
  • löschen der Dateien '/etc/pf.badguys', '/etc/pf.ip_register' sowie aller '/etc/pf.goodguysXX' Dateien
  • löschen des Logfiles '/var/log/mini_weblog_crawler.log'
  • löschen des Startscripts und des Programms in 'usr/local/sbin'
  • löschen der plist dafür

Damit ist das System bezogen auf die tPTR wieder im vorherigen Zustand und die Deinstallation abgeschlossen.

 

Die Parameter

Meiner Beobachtung über mehrere Wochen hinweg, kommen drei unterschiedliche Arten von Angreifern vor:

  1. der Heavy Attacker mit über 1000 Versuchen in bis zu 10 Minuten (China, Russland, USA), IP Adressen tauchen häufiger auf
  2. das Script Kid mit 4 bis 10 Versuchen innerhalb von 2 Sekunden, IP Adressen tauchen nicht wieder auf
  3. der SloMo Attacker mit 1 Versuch pro 10 Minuten, dafür kontinuierlich, IP Adressen kommen gelegentlich wieder vor

Attacker 1.) versucht sehr komplexe GET Nachrichten abzusetzen, teils mit schrägen Hexadezimalwerten und/oder SQL Injection.
Um diesen möglichst schnell zu erwischen, da er ein hohes Bedrohungspotential hat, muss die Taktfrequenz in der plist auf einen möglichst niedrigen Wert gesetzt werden. Die Lookback Time kann dafür gering gehalten werden, was das Einlesen des Webserver Logs natürlich verkürzt. Man könnte für diesen Attacker grundsätzlich mit einem hohen Threshold von > 50 Angriffsversuchen arbeiten, da diese Anzahl von Versuchen immer zustande kommt.

Attacker 2.) besitzt kein so großes Bedrohungspotential, startet nicht viele Versuche und diese sind auch nicht wirklich gefährlich. Mit den obigen Einstellungen für 1.) würde er durch das Raster fallen.

Attacker 3.) startet ebenfalls sehr komplexe Angriffsversuche, aber mit sehr geringer Frequenz. Um diesen herauszufilten, muss die Lookback Time höher und der Threshold sehr niedrig gesetzt werden.

Diese Beobachtungen haben dazu geführt, dass ich bei einer Ausführungsfrequenz von 10 (also alle 10 Sekunden) mit dem niedrigsten Threshold von 1 und einer Lookback Time von 1 Stunde (30 Minuten wären auch ok) arbeite. Auch die hohe Ausführungsfrequenz belastet das System nicht messbar, da der gesamte Vorgang nicht sonderlich CPU-intensiv ist.

 

Inhalt der ZIP Datei

Ein 'unzip -l tPTR.mac.2020-05-08.01.zip' ergibt diese Liste:

Archive:  v2020-05-08/tPTR.mac.2020-05-08.01.zip
   Length      Date   Time    Name
---------  ---------- -----   ----
     6256  05-08-2020 13:26   install_tPTR_mac.sh
      793  05-08-2020 13:26   local.upd_pf_from_http_log.plist
    13802  05-08-2020 13:26   mini_weblog_crawler.pl
     1945  05-08-2020 13:26   pf.conf.sample
     5724  05-08-2020 13:26   pf.ip_addresses.at.lst
     8907  05-08-2020 13:26   pf.ip_addresses.ch.lst
    28525  05-08-2020 13:26   pf.ip_addresses.de.lst
     1669  05-08-2020 13:26   uninstall_tPTR_mac.sh
     2674  05-08-2020 13:26   upd_pf_from_http_log.sh
---------                     -------
    70295                     9 files

 

Die md5 Checksumme sollte folgendes ergeben:

my_host$ md5 tPTR.mac.2020-05-08.01.zip
MD5 (tPTR.mac.2020-05-08.01.zip) = 19cf1931dc9150b930550db8e4cfdf9e