neunzehn83.de

Ein Mann, ein Blog, kein Plan.

fail2ban.log mit fail2ban überwachen für hartnäckige Angreifer

Wenn man mit fail2ban die eigene Logdatei überwacht kann man besonders hartnäckige Angreifer für einen längeren Zeitraum ausschließen. Dazu wird ein eigener Filter auf die fail2ban.log Datei angelegt. Fail2ban logt hier sämtliche bans und unbans. Wenn also ein Angreifer bspw. bereits mehrere Male wegen fehlgeschlagener SSH Login-Versuche aufgrund des "ssh"-Jails gebannt wurde, kann dieser jetzt mit einer längeren bantime versehen werden.

Beispiel aus der fail2ban.log für einen geduldigen Angreifer, der jedes Mal die bantime des ssh-Jails abwartet:

2016-05-24 04:28:30,113 fail2ban.actions[726]: WARNING [ssh] Ban 218.255.3.67
2016-05-24 04:38:30,867 fail2ban.actions[726]: WARNING [ssh] Unban 218.255.3.67
2016-05-24 04:38:49,899 fail2ban.actions[726]: WARNING [ssh] Ban 218.255.3.67
2016-05-24 04:48:50,681 fail2ban.actions[726]: WARNING [ssh] Unban 218.255.3.67
2016-05-24 04:49:13,715 fail2ban.actions[726]: WARNING [ssh] Ban 218.255.3.67
2016-05-24 04:59:14,497 fail2ban.actions[726]: WARNING [ssh] Unban 218.255.3.67
2016-05-24 04:59:38,533 fail2ban.actions[726]: WARNING [ssh] Ban 218.255.3.67
2016-05-24 05:09:39,313 fail2ban.actions[726]: WARNING [ssh] Unban 218.255.3.67

Der Filter für die fail2ban.log ist somit eigentlich ganz einfach. Taucht eine IP hier mehr als maxretry auf, erfolgt ein Ban mit extra hoher bantime.

Wir legen einen Filter für die fail2ban eigene Logdatei unter /etc/fail2ban/filter.d/fail2ban.conf an:

[Definition]
failregex = fail2ban.actions\[(.*)\]?: WARNING \[(.*)\] Unban <HOST>
ignoreregex = fail2ban.actions\[(.*)\]?: WARNING \[fail2ban\] Unban <HOST>

Wir aktivieren unser Jail in /etc/fail2ban/jail.local:

[fail2ban]
enabled = true
action   = iptables-allports[name=fail2ban]
filter = fail2ban
logpath = /var/log/fail2ban.log
findtime = 86400
bantime = 86400

Dieser Filter ist deutlich rabiater als die Standardwerte von fail2ban und blockt alle Ports für einen ganzen Tag.

Je nach fail2ban Version kann es vorkommen, dass der Unban des zuerst auslaufenden ssh-Jails auch den fail2ban-Jail aufhebt. Ich konnte dies mit fail2ban unter Debian Jessie zwar nicht nachvollziehen, ein Workaround hierzu wäre aber beim fail2ban eigenen Jail auf die Unbans statt Bans zu monitoren, somit ist der fail2ban-Jail niemals parallel zu anderen Jails aktiv, sondern erst direkt nach deren Aufhebung.

Verschleierung von "SPIEGEL Plus" unter der Lupe

SPIEGEL Plus ist das neue Bezahlangebot von spiegel.de bei dem einzelne Artikel teilweise nur "verschwommen" angezeigt werden bis man diese eben durch einen kleinen Centbetrag freischaltet. So sieht das dann aus:

SPON1

Aus rein technischem Hintergrund habe ich mir diese Verschleierung der SPIEGEL Plus Texte einmal genauer angeschaut - und war überrascht wie einfach man an die unverschleierten Texte rankommt.

Über dem verschleiertem Text liegt ein Filter, der für diese verschwommene Optik verantwortlich ist. Mit einem Web-Debug-Tool wie Firebug lässt sich diese CSS-Regel aber einfach entfernen. Darunter kommt dann ein verschleierter aber lesbarer Text zum Vorschein:

SPON2

Dieser Text könnte natürlich tatsächlich ordentlich verschlüsselt sein und sich somit nicht ohne Weiteres in den Originaltext zurückwandeln lassen. Was hier aber bereits auffällt, ist die Tatsache, dass die Wortlängen wohl beim Verschleiern erhalten bleiben. Zudem fällt auf, wenn man annimmt bei dem Ausschnitt handelt es sich um ein Interview, dass der Name des Interviewers (fett dargestellt) mit einem Semikolon endet - üblich wäre hier wohl ein Doppelpunkt. Diese zwei Zeichen liegen in der Zeichentabelle ziemlich nah beinander.

ASCII-Tabelle:
DEC CHAR
57  9
58  :
59  ;

Der Verdacht liegt nahe, dass hier einfach jeder Charcode um eins erhöht wurde, und der Text somit verschleiert wurde. Wir testen das!

Dabei hilft die Tatsache, dass jeder verschleierter Absatz eine Klasse "obfuscated" hat. Es ist also ein Leichtes, mit Javascript sämtliche p-Elemente mit dieser Klasse durchzugehen, die Charcodes aller Buchstaben um eins zu verringern und das Ergebnis wieder in das p zu schreiben. Das Leerzeichen hat mit 20 übrigens den niedrigsten Charcode und ist deshalb als einzige Ausnahme von dieser Subtraktion ausgeschlossen, da davor in der Zeichentabelle die nicht-druckbaren Zeichen beginnen.

  1. // Verschwommen-Filter entfernen
  2. document.getElementsByClassName('obfuscated-content')[0].parentElement.className='';
  3. // Hinweis-Box entfernen
  4. document.getElementsByTagName('svg')[0].nextSibling.nextSibling.innerHTML='';
  5. // Beim durchlaufen der Chars müssen wir Ersetzungen innerhalb von Tags auslassen
  6. var inside_tag = 0;
  7. // alle verschlüsselten Elemente durchlaufen
  8. var p=document.getElementsByClassName('obfuscated');
  9. for (var i=0; i<p.length; i++) {
  10. var result ='';
  11. var text = p[i].innerHTML;
  12.  
  13. // Alle Buchstaben durchlaufen
  14. for (var j=0; j<text.length; j++){
  15. if (text[j]=='<') inside_tag = 1;
  16. var cc = text.charCodeAt(j);
  17. var diff = cc==32 ? 0 : 1;
  18. result += inside_tag ?
  19. text[j] :
  20. String.fromCharCode(cc+diff); // wir _addieren_ diff
  21. if (text[j]=='>') inside_tag = 0;
  22. }
  23. p[i].innerHTML = result;
  24. }
  25. alert(':)');

(Um keinen funktionsfähigen Code hier anzubieten, wird oben "diff" zum Charcode (cc) addiert statt subtrahiert!)

Für Testzwecke(!) kann dies auch komfortabel direkt auf der Seite in der URL-Leiste ausgeführt werden. Obiger Code als Einzeiler:

  1. avascript:document.getElementsByClassName('obfuscated-content')[0].parentElement.className='';document.getElementsByTagName('svg')[0].nextSibling.nextSibling.innerHTML='';tg=0;p=document.getElementsByClassName('obfuscated');for(var i=0;i<p.length;i++){f='';t=p[i].innerHTML;l=t.length;for(var j=0;j<l;j++){if(t[j]=='<')tg=1;cc=t.charCodeAt(j);diff=cc==32?0:1;f+=tg?t[j]:String.fromCharCode(cc+diff);if(t[j]=='>')tg=0;}p[i].innerHTML=f;}alert(':)');

Google-Chrome unterschlägt aus Sicherheitsgründen das "javascript:" am Anfang des Strings, wenn man das direkt aus der Zwischenablage so einfügt. Deshalb muss das "j" selbst in die Adressleiste getippt werden und dann kann obiger Code gepastet werden.

Und damit hier keine Missverständnisse aufkommen: Dies ist keineswegs eine Anleitung, um das Bezahlangebot von spiegel.de zu umgehen! Hier geht es rein um die technischen Aspekte dieser Verschleierung. Wer sich tatsächlich für den Artikel-Inhalt interessiert sollte diesen natürlich einfach kaufen! Aus diesem Grund ist der Beispielcode auch an einer Stelle verändert, um keine copy-paste Lösung hier anzubieten!

Wo bleibt E-Mail 2.0?

Web 2.0, Industrie 4.0, IPv6, ... und E-Mail 1.0?

Die E-Mail ist schon sehr alt. Sogar schon älter als das Internet. Vieles hat sich seit deren Erfindung Anfang der 70er Jahre getan. Mehrere (R)evolutionen bei Internet- und HTTP-Protokollen, Verschlüsselungsalgorithmen und Authentifizierungsverfahren zogen scheinbar spurlos an der E-Mail vorüber. Obwohl die Einführung dieser Neuerungen teilweise große Umstellungen mit sich brachten, wurden damals, wie bspw. bei der Einführung von IPv6, keine Kosten und Mühen gescheut. Für die E-Mail und deren Protokolle scheint das alles nicht zuzutreffen. Warum eigentlich?

Status Quo

95% aller gesendeten E-Mails sind SPAM. Eine verschlüsselte E-Mail zu versenden ist viel zu kompliziert. Die Einrichtung von E-Mail-Accounts (außer in proprietären Clients/Apps) ebenfalls: SMTP-Host? IMAP oder POP3? Ports, SSL, SMTP-Auth? Sent/Gesendete Elemente/Gesendete Objekte Ordner? Fragen über Fragen ..

Postfix

Postfix ist einer der am weitest verbreiteten Mailserver. Das ist schon wirklich unglaublich. Ich habe das hier in meinem Blog schon öfters erwähnt, aber ich habe jedesmal beim Konfigurieren den Eindruck, Postfix denkt es sei im Arpanet und man muss ihn mit jedem Konfigurationsparameter prügeln und zwingen, sich wie ein ordentlicher Mailserver zu verhalten. Scheinbar einfache Dinge wie die Erlaubnis zu relayen pro Account, Mail-Sende-Limits pro Account, etc. sind unglaublich kompliziert und umständlich umzusetzen. Ich kenne außerdem keinen, der aus Postfixs Log-Dateien oder der Mailqueue auf Anhieb schlau geworden ist.

Praxis-Szenario

Mailbox-Zugangsdaten gelangen durch einen infizierten Client in die Hände eines Spammers. Dies ist kein zu außergewöhnliches Ereignis. Der Spammer kann dann ohne Probleme in Kürze hunderttausende Mails versenden. Postfix bietet hier keine einfache Möglichkeit Sendelimits umzusetzen oder auch nur Warnungen zu versenden. Sind dann tausende Mails in der Mailqueue, können die des kompromittierten Accounts (sprich per SASL-Username) auch nicht ohne Weiteres gezielt aus der Queue entfernt werden.

Wunschkonzert

Wie schön wäre E-Mail 2.0 mit Mailservern, "written from scratch", im Hier und Jetzt, die verschlüsselte Authentifizierung und Übertragung aus dem Effeff beherrschen, die E-Mails nicht hin-und-her pipen und queuen, sondern sich der Spam-Thematik im Kern bewusst sind und die eine einfache und standardisierte Autodiscover-Funktionalität bieten.

Tutorial: SSL-Zertifikate von Let's Encrypt

Wie bereits geschrieben verwende ich für diesen Blog jetzt ein SSL Zertifikat von Let's Encrypt. Und das funktioniert erstaunlich gut. Zu Beginn kann man aber schon mal etwas überfordert sein, da das Vergabesystem von Let's Encrypt sich doch von allen bisherigen Vergabestellen stark unterscheidet (nicht nur im Preis :)).

Deshalb hier eine kompakte Anleitng von Null bis SSL. Ich verwende den alternativen Client acme-tiny, da mir der offizielle Client viel zu mächtig und selbstständig erschien. acme-tiny hingegen ist sehr übersichtlich, eine einfache Python-Datei und gerade mal 200 Zeilen groß.

Wir erstellen uns zunächst ein eigenes Verzeichnis und legen darin das acme-tiny.py Script ab sowie das Zwischenzertifikat von Let's Encrypt, welches wir an alle erhaltenen Zertifikate anhängen müssen.

mkdir acme-tiny
cd acme-tiny/
wget -O - https://letsencrypt.org/certs/lets-encrypt-x1-cross-signed.pem > intermediate.pem
wget -O - --no-check-certificate http://raw.githubusercontent.com/diafygi/acme-tiny/master/acme_tiny.py > acme_tiny.py

acme-tiny erstellt für uns automatisch einen Let's Encrypt Account. Hierfür benötigen wir vorab einen Private-Key, welchen wir wie folgt erstellen:

openssl genrsa 4096 > account.key

Um eine Domain zu verifizieren ruft LE eine URL auf dieser Domain auf und erwartet einen bestimmten Inhalt. acme-tiny erstellt diesen Inhalt als Datei im per Parameter angegebenen Ordner. Via Webserver-Konfiguration muss man sicherstellen, dass der Ordner unter folgender URL gelistet wird: domain.com/.well-known/acme-challenge/. Wichtig: LE ruft für alle Subdomains im Zertifikat ebenfalls die .well-known Location auf.

Wir legen uns also am besten an zentraler Stelle einen Ordner für Challenges an:

sudo -u www-data mkdir /var/www/challenges

Ein passender Apache Alias könnte so aussehen:

Alias /.well-known/acme-challenge /var/www/challenges

Alternativ kann der Ordner ".well-known/acme-challenge" natürlich auch tatsächlich auf dem Dateisystem angelegt werden oder als Symlink nach /var/www/challenges zeigen.

Soviel zu den allgemeinen (einmalig notwendigen) Schritten. Im folgenden das Prozedere um tatsächlich ein SSL-Zertifikat für eine bestimmte Domain zu erhalten. Wir möchten die Domain example.org sowie die Subdomains www.exsmple.org und mail.example.org mit einem einzigen Zertifikat sichern.

Für jedes Zertifikat benötigen wir zunächst einen Private-Key

openssl genrsa 4096 > example.org.key

Jetzt erstellen wir den CSR mit dem wir unser SSL-Zertifikat beantragen:

openssl req -new -sha256 -key example.org.key -subj "/" -reqexts SAN -config <(cat /etc/ssl/openssl.cnf <(printf "[SAN]\nsubjectAltName=DNS:example.org,DNS:www.example.org,DNS:mail.example.org")) > example.org.csr

Jetzt führen wir acme-tiny aus:

python acme_tiny.py --account-key ./account.key --csr ./example.org.csr --acme-dir /var/www/challenges/ > ./example.org.crt

Die Ausgabe sollte so oder so ähnlich aussehen:

Parsing account key...
Parsing CSR...
Registering account...
Already registered!
Verifying example.org...
example.org verified!
[..]
Signing certificate...
Certificate signed!

Das Zertifikat muss jetzt um das Intermediate erweitert werden:

cat example.org.crt intermediate.pem > example.org.pem

Das wars! Das Zertifikat "example.org.pem" und der zugehörige Key "example.org.key" kann jetzt für Apache, Postfix, Dovecot, etc. verwendet werden!

Gültigkeit der Zertifikate

Zertifikate von LE haben aktuell eine Gültigkeit von 3 Monaten, in Zukunft wahrscheinlich noch weniger. Um ein SSL-Zertifikat zu aktualisieren genügt der Aufruf von acme-tiny. Danach muss nur noch das Intermediate-Zertifikat angehängt werden und das alte Zertifikat damit überschrieben werden. Anschließend müssen alle Dienste, die dieses Zertifikat nutzen reloaded werden.

Dies kann also von einem einfachen batch-script und Aufruf per cron erledigt werden.

Probleme

Erscheint folgende Fehlermeldung

ImportError: No module named argparse

benötigt man noch folgende Datei im selben Verzeichnis wo sich die acme-tiny.py befindet:

https://raw.githubusercontent.com/ThomasWaldmann/argparse/master/argparse.py

SSL-Zertifikat von Let's Encrypt auf neunzehn83.de

Knapp ein Jahr ist's her, als ich meinen Blog mit SSL ausgestattet habe. Dies bedeutet auch, dass nun das kostenlose SSL-Zertifikat von StartSSL ausläuft und verlängert werden müsste. Da aber Let's Encrypt gerade in aller Munde ist, schreit dies natürlich danach es auszuprobieren.

neunzehn83.de SSL

Der Prozess, ein Zertifikat von Let's Encrypt zu erhalten, ist zu Beginn gar nicht so einfach, wenn man ihn mit anderen Vergabestellen vergleicht. Hat man den Client (oder besser: einen alternativen) erstmal eingerichtet, ist das Erhalten sowie erneuern von Zertifikaten aber sehr einfach. Mehr dazu gibt es hier bald zu lesen..

Archiv »