SSH-Bot Statistik

Posted on So 10 April 2022 in Computer & Electronics

In einem Post vor ein paar Wochen hatte ich erzählt, wie ich endlessh auf meinem Homeserver installiert habe, um die ssh-scanner Deppen ein wenig zu ärgern. Vermutlich bringt es nicht wirklich was, aber es verschafft mir ein wohliges Gefühl.

Heute wollen wir uns mal anhand der Logfiles ansehen, wieviele ssh-Attacken überhaupt so passieren.

Daten

Zunächst stellt sich die Frage, wo wir überhaupt Infos dazu finden, wer alles so versucht hat, sich via ssh einzuloggen. Also begeben wir uns mal nach /var/log/, wo derartiges zu erwarten ist. Dort liegen diverse logfiles – aber in welchem/n landen die Meldungen von endlessh?

Dazu verwende ich den silver-searcher, kurz ag, der ist eine schnelle Implementierung des Such-Tools ack. Wer das noch nicht kennt, sollte es dringend anschauen – damit kann man rasend schnell und bequem herausfinden, in welchen Files ein Begriff (typischerweise eine Variable oder ein Befehl) vorkommt.

❯ ag endlessh
user.log:1:Apr 10 00:00:25 hal endlessh[780]: 2022-04-09T22:00:25.627Z ACCEPT host=::ffff:178.62.118.126 port=61000 fd=207 n=204/4096
user.log:2:Apr 10 00:01:05 hal endlessh[780]: 2022-04-09T22:01:05.628Z CLOSE host=::ffff:178.62.118.126 port=61000 fd=207 time=40.001 bytes=45
user.log:3:Apr 10 00:19:11 hal endlessh[780]: 2022-04-09T22:19:11.877Z ACCEPT host=::ffff:112.85.42.229 port=53414 fd=207 n=204/4096
[...]

Uiii – viele Zeilen. Zu viele. Also etwas nachbearbeiten:

❯ ag endlessh | cut -f 1 -d: | sort -u
messages
messages.1
syslog
syslog.1
user.log
user.log.1

Besser. Am wenigsten Rauschen gibt es in den usr.log files. Also nehmen wir die. Zuerst habe ich mal drei davon in einer Datei zusammengeführt. Und als nächstes schmeißen wir mal alles raus, was uns nicht interessiert:

❯ grep endlessh user.log > user.log.clean

Wenn man sich den Inhalt ansieht findet man zwei verschiedene Arten von Einträgen:

07T19:24:02.901Z ACCEPT host=::ffff:112.85.42.229 port=45982 fd=208 n=205/4096
07T19:24:22.904Z CLOSE host=::ffff:112.85.42.229 port=45982 fd=208 time=20.003 bytes=5

Also ACCEPT und CLOSE. Letztere enthalten eigentlich alle Information, die man so haben können wollte: Timestamp, Dauer der Verbindung (time) und die Anzahl der ausgetauschten Bytes.

Damit sollte sich doch was machen lassen. Als erstes aber muss ich das alles mal parsen und in Tabellenform bringen, damit es analysierbar wird. Dazu bauen wir ein kleines Python Script:

#!/usr/bin/env python3
"Format user.log entries as CSV"
import sys, re

print(",".join(["timestamp", "action", "host", "port", "time", "bytes"]))
for line in sys.stdin:
    line = line.rstrip()
    line = re.sub("^.*endlessh\[[0-9]+\]: ", "", line)
    timestamp, action, fields = line.split(" ", maxsplit=2)
    fields = fields.split(" ")
    fields = dict(x.split("=") for x in fields)
    if action == "CLOSE":
        print(
            ",".join(
                [
                    timestamp,
                    action,
                    fields["host"],
                    fields["port"],
                    fields["time"],
                    fields["bytes"],
                ]
            )
        )
    elif action == "ACCEPT":
        print(",".join([timestamp, action, fields["host"], fields["port"], "", ""]))

Und damit können wir die Daten nun formatieren:

❯ ./format.py < user.log.clean > user.csv

... und in R analysieren.

Die Logs, die ich hier auswerte decken den Zeitraum der letzten 13 Tage ab und enthalten 2975 akzeptierte und 2840 abgeschlossene Verbindungen. D.h. 135 sind aktuell offen. Im Mittel gab es also 228 Verbindungen am Tag.

Wie lang dauern die Sessions?

Meine Vermutung war, dass die ssh Bots auch nicht blöd sind und nach ein paar Sekunden aufgeben, um nicht zu viel Zeit zu verschwenden. Für sehr viele stimmt das auch, aber eine erstaunlich große Zahl lässt sich gefühlt ewig festhalten:

Der geduldigste Bot hat sich 72756 Sekunden festhalten lassen – das sind beeindruckende 20 Stunden! Der Median lag immerhin noch bei 1025s = 17min. 60% der Bots blieben länger, als 30s und fast die Hälfte (49.9%) waren über eine Stunde gebunden.

Das hatte ich nicht erwartet.

Wieviel Daten werden übertragen?

Im Median wurden bei den Sessions 1784 Bytes ausgetauscht. In der dicksten Session waren es 125 kB.

Erwartungsgemäß korreliert die Dauer der Verbindung sehr stark (\(r^2=0.9999\)) mit dem Datenvolumen:

Connections nach Tageszeit

Außerdem hat mich interessiert, ob es irgendein zeitliches Muster für die Bot-Angriffe gibt. Meine Annahme war, dass Bots nie müde werden und die Uhrzeiten der Connections mehr oder weniger gleichverteilt sind. Und damit liege ich sowas von falsch:

Wie es scheint, halten sich viele ssh-Bots einigermaßen an deutsche Bürozeiten. WTF???

Da wir hier nur knapp 2 Wochen abdecken macht eine Analyse nach Wochentag wenig Sinn. Vielleicht reiche ich das in der Zukunft einmal nach.

Wieviele verschiedene IP-Adressen?

Im Datensatz finden sich insgesamt 240 einzigartige IP-Adressen. Und per Augenmaß sind manche sehr aktiv und andere kommen eher selten vor. Also schauen wir uns das mal an:

Schaut man in die Daten findet man dies: 140 IP Adressen haben genau einmal versucht sich zu verbinden, 35 Adressen hatten zwei Connections, drei Connections gab es noch bei 14 IPs. Am anderen Ende des Spektrums gab es je eine IP, die es 746 bzw. 816 mal versucht haben.

In der Grafik ist das aber kaum zu erkennen. Das ist durchaus typisch bei solchen Verteilungen – es dürfte sich hier um eine sog. Power-Law Verteilung handeln. Und die kann man am besten visualisieren, wenn man beide Achsen logarithmisch darstellt – dann sollte der Zusammenhang in etwa linear aussehen, wenn es eine Power-Law Verteilung ist:

Woher kommen die Angriffe?

Zuguterletzt wüsste ich noch gerne, woher die Attacken eigentlich kommen. Anhand der IP-Adressen könne wir versuchen, das Ursprungsland zu identifizieren. Konkret habe ich dazu die API von ipgeolocation.io verwendet. Bei denen gibt es einen kostenlosen Account, der zwar limitiert ist, aber für die Zwecke dieser Auswertung völlig ausreichend ist.

Natürlich muss man diese Daten sehr mit Vorsicht genießen, denn es ist anzunehmen, dass ein Angreifer sowas nicht von seinem heimischen PC aus macht, sondern eher fremder Leute Rechner dafür einspannt, die er unter Kontrolle gebracht hat. Zum Zweck der Analyse betrachte ich nur unique IPs. Und so sieht die Länderverteilung aus:

Fazit

Ich habe in den Daten durchaus ein paar Überraschungen gefunden. Insbesondere hat mich verwundert, dass es wirklich gelingt einen nicht unerheblichen Teil der Connections sehr in die Länge zu ziehen. Aber machen wir uns nichts vor – auch die Bot-Programmierer haben mit Sicherheit schon von asynchronem I/O gehört und so ist nicht zu erwarten, dass sie das besonders schmerzt. Vor allem da sie vermutlich eine Armada gehackter Fremdrechner zur Verfügung haben. Aber vielleicht streut es ja doch wenigstens ein kleines bisschen Sand ins Getriebe einiger naviverer Angreifer.