Ein Kryptominer auf dem eigenen Server
Beim Umzug auf die neue Maschine ist mir ein Prozess aufgefallen, der dort nichts zu suchen hatte. Wie ich ihn gefunden habe, was er war und welche Konsequenzen ich gezogen habe.
937 Wörter · 5 Min. Lesezeit
- sicherheit
- vorfall
- infrastruktur
Beim Vorbereiten des Serverumzugs bin ich über etwas gestolpert, das mir den Rest des Tages gekostet hat: Ein Prozess lief, der dort nicht hingehörte, und er verbrauchte Rechenzeit.
Es war ein Kryptominer.
Wie es aufgefallen ist
Nicht durch eine Meldung, nicht durch eine Überwachung. Sondern weil ich beim Aufsetzen der neuen Maschine die Auslastung der alten verglichen habe und die Zahlen nicht zu dem passten, was dort laufen sollte.
Das ist der unangenehmste Teil dieser Geschichte: Meine Überwachung hat es nicht bemerkt. Sie prüft, ob Dienste laufen, ob Sicherungen entstehen, ob Platz da ist. Sie prüft nicht, ob etwas läuft, das nicht laufen sollte.
Was ich gemacht habe, in dieser Reihenfolge
Erst geschaut, dann gehandelt. Der Reflex ist, den Prozess sofort zu beenden. Das ist falsch — mit dem Prozess verliert man die Information, wie er dorthin kam.
Also erst: Welcher Prozess, unter welchem Benutzer, gestartet von wem, welche Datei, welche Netzwerkverbindungen, seit wann.
ps -ef --forest
ls -l /proc/<pid>/exe /proc/<pid>/cwd
ss -tnpDann den Weg gesucht. Der Prozess lief unter dem Benutzer eines Dienstes, nicht als Systemverwalter. Das war die erste gute Nachricht — die Rechtetrennung hatte gehalten.
Anhaltspunkte: Zeitpunkt des Starts, Änderungszeit der Datei, Einträge in den Zugriffsprotokollen des Webservers rund um diesen Zeitpunkt, Zeitplanaufträge des Benutzers.
Dann eingefroren, nicht bereinigt. Netzwerkverbindungen unterbunden, Prozess beendet, Datei gesichert statt gelöscht.
Dann die Zugangsdaten getauscht. Alle. Nicht die, von denen ich glaubte, dass sie betroffen sein könnten.
Dann neu aufgesetzt. Das ist die wichtigste Entscheidung des ganzen Tages: Ein System, auf dem fremder Code lief, wird nicht bereinigt, sondern ersetzt. Man kann nicht beweisen, dass man alles gefunden hat.
Der Umzug auf die neue Maschine war ohnehin geplant. Er ist damit von „in den nächsten Wochen" zu „jetzt" geworden — und zwar als Neuaufbau, nicht als Kopie.
Warnung
Der Fehler, den man in dieser Lage macht: sich auf die Suche nach der Lücke zu konzentrieren und darüber die Zugangsdaten zu vergessen. Alles, was auf dieser Maschine lag, muss als offengelegt gelten — Konfigurationsdateien, Datenbankinhalte, hinterlegte Schlüssel, gespeicherte Zugänge zu anderen Systemen. Der Tausch kommt vor der Analyse.
Was ich über den Weg herausgefunden habe
Ehrlich: nicht mit letzter Sicherheit. Was ich sagen kann, ist, dass der Prozess unter einem Dienstbenutzer lief und dass es zeitlich zu einer Phase passt, in der ein Dienst auf einer veralteten Fassung lief.
Das reicht mir als Erkenntnis. Die Konsequenz ist ohnehin dieselbe, egal welcher Weg es war, und sie ist unspektakulär: Aktualisierungen zeitnah, Dienste mit möglichst wenig Rechten, und keine Anwendung, die im Internet erreichbar ist, ohne dass jemand ihre Fassung im Blick hat.
Die Konsequenzen
Der Umzug wurde ein Neuaufbau. Nichts wird kopiert außer Nutzdaten — Datenbanken, hochgeladene Dateien, Weltdaten. Keine Konfigurationsdateien, keine Skripte, keine Zeitpläne, keine Benutzerkonten.
Jeder Dienst läuft jetzt in einem Container mit eigenen Grenzen. Das war ohnehin der Plan. Nach diesem Tag ist es keine Aufräumaktion mehr, sondern eine Sicherheitsmaßnahme: Ein kompromittierter Dienst hat dann eine deutlich kleinere Reichweite.
Die Überwachung hat eine neue Prüfung bekommen. Nicht nur „läuft, was laufen soll", sondern auch: Wie hoch ist die Grundlast, und weicht sie ab? Ein Miner fällt genau dort auf, weil er das einzige tut, was er tun kann — Rechenzeit verbrauchen.
Ausgehende Verbindungen sind jetzt eingeschränkt. Ein Dienst, der nur eingehende Anfragen beantwortet, muss nicht beliebige Ziele im Internet erreichen können.
Was ich beim Neuaufsetzen mitgenommen habe — und was nicht
Die Entscheidung, nichts zu kopieren, war schnell getroffen und in der Umsetzung mühsam. Deshalb die Liste, wie ich getrennt habe.
Mitgenommen: Datenbanken. Hochgeladene Dateien. Weltdaten der Spielserver. Inhalte. Alles, was Nutzdaten sind und sich prüfen lässt.
Nicht mitgenommen: Konfigurationsdateien. Skripte. Zeitpläne. Benutzerkonten. Systemeinstellungen. Alles, was Verhalten bestimmt.
Die Begründung für diese Trennung: Nutzdaten kann ich prüfen — Zeilenzahlen, Prüfsummen, Stichproben. Bei einem Skript oder einer Konfigurationsdatei kann ich nicht mit Sicherheit sagen, ob eine Zeile darin steht, die dort nicht hingehört. Also werden sie neu geschrieben.
Das hat den Umzug um Tage verlängert. Es hatte einen Nebeneffekt, der die Zeit teilweise zurückgeholt hat: Beim Neuschreiben ist eine Menge Altlast weggefallen — Skripte für Dienste, die es nicht mehr gibt, Zeitpläne, deren Zweck niemand mehr kannte, Einstellungen ohne Begründung.
Die Prüfungen, die ich seitdem laufen habe
Aus diesem Tag sind vier Kontrollen entstanden, die es vorher nicht gab.
Grundlast im Wochenvergleich. Ein Prozess, der Rechenzeit verbraucht, ohne dazuzugehören, fällt genau hier auf.
Offene Ports von außen, verglichen mit einer erwarteten Liste.
Ausgehende Verbindungen von Diensten, die keine brauchen. Ein Dienst, der plötzlich nach außen spricht, ist ein Signal.
Änderungen an Dateien, die sich nicht ändern sollten. Startskripte, Konfigurationen, Zeitpläne.
Die dritte Prüfung ist die, die ich am wichtigsten finde, und sie war mir vorher nie in den Sinn gekommen. Fast jede Schadsoftware muss nach außen sprechen — um Anweisungen zu holen, um Ergebnisse abzuliefern, um einem Verbund beizutreten. Ein Dienst, der nur eingehende Anfragen beantwortet und dessen ausgehende Verbindungen eingeschränkt sind, ist deutlich weniger wert für jemanden, der ihn übernimmt.
Was ich mitnehme
Rechtetrennung hat funktioniert. Der Prozess lief unter einem Dienstbenutzer und kam nicht weiter. Das ist der Grund, warum ich seit Jahren nichts als Systemverwalter laufen lasse — und der Tag, an dem sich das ausgezahlt hat.
Überwachung prüft, was man sich vorstellt. Meine hat alle Fragen beantwortet, die ich ihr gestellt habe. Nach einem Ausfall stellt man die Frage „läuft es?". Nach diesem Tag stellt man zusätzlich die Frage „läuft etwas, das nicht sollte?".
Neu aufsetzen ist billiger, als es sich anfühlt. Ich habe eine halbe Stunde mit mir gerungen. Die Alternative — bereinigen und hoffen — hätte bedeutet, dass ich diesem System nie wieder vertraue. Das ist auf Dauer teurer als jeder Neuaufbau.