In den letzten Monaten liest man ständig von erfolgreichen Angriffen auf die Netze von Firmen. Viel zu häufig dringen die Angreifer dabei unter Ausnutzung von seit langem bekannten Lücken in Standard-Software ein. Ein beliebtes Ziel: Content Management System (CMS) wie Drupal, Typo3 oder WordPress. Doch das muss nicht sein!
Der folgende Artikel beschäftigt sich vor allem mit WordPress. Das liegt nicht daran, dass die Software per se schlechter ist als der Rest! WordPress ist schlichtweg sehr weit verbreitet und gut untersucht. Außerdem kenne ich mich ganz gut damit aus ;-) Die beschriebenen Probleme lassen sich leider analog auf einen großen Teil der Dienste und Seiten im World Wide Web übertragen.
Zu beschreiben, wie so ein Angriff im Detail abläuft, würde den Rahmen dieses Artikel sprengen; umso mehr da es eine Vielzahl unterschiedlichster Varianten gibt.
Ein Angriff auf ein CMS kann sehr unterschiedliche Ziele haben.
Ein Angreifer kann schlicht versuchen, das System zu beschädigen oder (temporär) außer Gefecht zu setzen. Im einfachsten Fall wird das System überlastet z.B. durch sogenanntes “SYN flooding”. Wird der Angriff von mehreren Punkten gleichzeitig ausgeführt spricht man von DDoS; distributed denial of service. Diese Form von Angriff hat mit der Art der attackierten Software allerdings nichts zu tun und lässt sich nur durch entsprechende Infrastrukturmaßnahmen erschweren.
Der Angreifer kann versuchen, sich im System weiterreichende Zugriffsrechte zu verschaffen um Daten abzugreifen oder zu manipulieren. Der Jackpot bei einer solchen Attacke sind natürlich Administratorrechte. Mit diesen Rechten kann der Angreifer innerhalb des CMS schalten und walten wie es ihm beliebt.
Alternativ kann der Angreifer auch versuchen, das Rollen-Rechte-System des CMS ganz zu umgehen um direkt auf die Daten zuzugreifen. Dabei werden der Software von Außen eigene Anfragen an die dem CMS zu Grunde liegende Datenbank injiziert. Je nachdem, wie unsicher der Zugriff auf die Datenbank konfiguriert ist, kann der Angreifer hierbei die Grenzen der Anwendung verlassen und auch Daten anderer Anwendungen auslesen.
Bei einer Code Injection Attacke versucht der Angreifer, dem CMS Schadcode unterzuschieben der wiederum die Besucher der Seite attackiert. Dafür kann es schon ausreichen, wenn Besucher des CMS beliebige Kommentare schreiben können, in denen Steuerzeichen erlaubt sind.
Statt das CMS selbst anzugreifen kann der Angreifer auch versuchen, beliebige Befehle direkt auf dem Host - dem Rechner, auf dem das CMS läuft - auszuführen. Im schlimmsten Fall kann es dem Angreifer sogar gelingen diesen ganz unter seine Kontrolle zu bringen. Ein solcher Brückenkopf kann dann allzu häufig genutzt werden um von dort aus tiefer in das Netzwerk des Opfers vorzudringen.
Ich habe eine live demo gesehen, bei der einem verwundbaren System von außen ein vollwertiges CLI (Command Line Interface; zu Deutsch: Eingabeaufforderung) injiziert wurde. Wenn der Webserver dann auch noch als priviligierter Nutzer unterwegs ist, gehört der Rechner dem Angreifer.
Leider handelt es sich hierbei nicht um ein exotisches Problem. Laut einer Studie aus dem Dezember 2014 waren zum damaligen Zeitpunkt mehr als 70% aller untersuchten WordPress-Installationen angreifbar. Untersucht wurden dabei zudem nur Installationen innerhalb der 1.000.000 am häufigsten besuchten Websites. Das bedeutet, dass hier tendenziell professionelle Administratoren im Hintergrund tätig sind, welche die Software eigentlich im Auge haben sollten. Wie kann es dann sein, dass trotzdem fast 3/4 der Seiten angreifbar sind?
Hierfür gibt es eine ganze Reihe von Ursachen.
Aber der Reihe nach.
Wie ein sehr großer Anteil der Anwendungen im Web setzt WordPress auf dem AMP stack auf: dem Webserver Apache, der Datenbank MySQL und der Programmiersprache PHP. Um eine Seite anzuzeigen, führt der Webserver das PHP Programm aus. Eine Besonderheit von PHP ist, dass die Software nicht als fertiges ausführbares Programm vorliegt. Statt dessen werden alle für den aktuellen Aufruf notwendigen Dateien geladen und zusammengefügt. Dann werden die Dateien in Maschinensprache übersetzt und das Ergebnis ausgeführt. Das erzeugte Programm greift nach Bedarf auf die Datenbank zu und lädt die benötigten Informationen. Abschließend wird aus dem PHP heraus HTML erzeugt, das der Webserver an den Browser ausliefert. Vorbehaltlich einiger Optimierungen wie Caching wird am Ende alles wieder verworfen.
Der Vorteil hiervon ist, dass Änderungen am PHP Code sofort sichtbar sind. Zudem ist PHP relativ einfach zu lernen und ungewöhnlich fehlertolerant. Auch MySQL ist eine relativ einfach zu handhabende Datenbank. Sie lässt sich schnell in Betrieb nehmen und liefert nach kurzer Einarbeitungszeit zufriedenstellende Ergebnisse. Und auch Apache ist ein recht gutmütiger Webserver mit dem sich ohne viel zu konfigurieren auch dynamische Webseiten wie eben WordPress betreiben lassen. Der Preis für diese Einfachheit ist allzu oft geringe Sicherheit, weil erstmal fast alles erlaubt ist.
Vieles, was für die Entwicklung einer Seite vorteilhaft ist, erweist sich als Einfallstor für Angriffe. So ist es zum Beispiel meistens möglich, die Dateien aus denen WordPress besteht innerhalb von WordPress selbst zu bearbeiten. Vor allem bei virtuellen Servern, die man für ein paar Euro im Monat mieten kann, bietet das eine bequeme Möglichkeit um die Seite schnell anzupassen. Im Gegenzug kann ein Angreifer über die gleiche Schnittstelle Schadcode einbringen und diesen ohne weitere Verzögerung auszuführen.
In dem oben genannten Report geht es allerdings gar nicht um Lücken durch fehlerhafte Konfiguration sondern darum, dass Website-Betreiber Versionen von WordPress mit allgemein bekannten Sicherheitslücken betreiben. Natürlich sind die Entwickler von WordPress stetig dabei bekannte Lücken, die durch Fehler im Code entstehen, zu schließen. Man sollte also erwarten, dass die Verantwortlichen ihre Installation immer auf dem neuesten Stand halten. Das ist leider nicht immer einfach so möglich. Viele Sicherheitsprobleme entstehen nicht durch ein paar Zeilen fehlerhaften code sondern durch das unglückliche Zusammenspiel unterschiedlicher Komponenten. Solche Lücken zu schließen ohne das Gesamtsystem in Mitleidenschaft zu ziehen ist häufig kompliziert.
Wie schon geschrieben gibt es über 46000 Module um WordPress zu erweitern. Viele davon sind von professionellen Entwicklern programmiert worden und kosten zum Teil Lizenzgebühren. Durch den Einsatz von Modulen kann man aus WordPress die unterschiedlichsten Plattformen bauen; vom Blog über die Jobbörse bis hin zum Social Network mit Chat und allem Pipapo.
Die Module haben leider ein paar negative Konsequenzen. Zum einen kann ein Modul wie jedes komplexere Stück Software Fehler enthalten. Nicht selten ist eine WordPress-Installation nicht durch Fehler im Kern sondern über ein defektes Modul angreifbar. Insbesondere wenn hinter dem Add-On keine Firma oder Community sondern ein einzelner Hobby-Entwickler steht ist es durchaus wahrscheinlich, dass der Fehler gar nicht behoben wird.
Andererseits kann es passieren, dass durch Änderungen am Code von WordPress ein Modul nicht mehr oder nur noch eingeschränkt funktioniert. Der Betreiber einer Website, der auf die entsprechende Funktionalität angewiesen ist, mag sich dann dazu entscheiden, seine Installation nicht zu aktualisieren. Wird schon gut gehen…
Ein ganz ähnliches Problem ergibt sich durch die Verwendung von Themes. Diese ändern teilweise das Aussehen von WordPress ganz erheblich und greifen an vielen Stellen in die Abläufe bei der Erzeugung der Seite ein. Dementsprechend kann ein Theme natürlich ebenfalls Bugs enthalten. Zudem sind sie oft noch viel mehr als die Add-Ons auf bestimmte Einstiegspunkte angewiesen und reagieren empfindlich auf Änderungen. Dementsprechend müssen Themes in der Regel an jede neue Version von WordPress angepasst werden.
PHP ist, wie gesagt, eine einfache und fehlertolerante Programmiersprache. Was liegt also näher, als kleine Änderungen am Aussehen der Seite selbst umzusetzen? Viele (Hobby-)Entwickler fügen Änderungen direkt in die Dateien von WordPress ein; gerne auch per Copy & Paste ohne genau zu wissen, was sie tun. Mit fatalen Folgen: Die mühsam programmierten “Verbesserungen” gehen natürlich verloren, sobald des entsprechende Add-On bzw. Theme oder WordPress selbst aktualisiert werden…
WordPress bietet in der Tat ein paar Möglichkeiten, um vor allem Themes sicher zu verändern ohne sofort auf einer defekten Version festgenagelt zu bleiben. Weil das Arbeiten mit Child Themes und Add Ons komplizierter ist als mal eben ein paar Zeilen Code einzufügen nutzen viele Entwickler und vor allem Laien diese leider nicht.
Und so kommt es, dass - trotz der Möglichkeit eine WordPress-Installation automatisch zu aktualisieren - so viele veraltete, verwundbare Instanzen anzutreffen sind.
Das Ganze liest sich bisher ein bissche wie eine dystopische Horrorstory… Alles kaputt, alles unsicher und überall böse Angreifer. Die schlecht Nachricht: So isses. Die gute Nachricht: Das muss nicht so sein.
Was PHP als Sprache und darauf aufsetzende CMS wie WordPress so attraktiv macht ist die große Flexibilität. Es ist vergleichsweise leicht Änderungen vorzunehmen und diese sofort verfügbar. Gleichzeitig macht es die Plattform wie beschrieben aber auch leicht angreifbar.
Bei einem CMS wie WordPress kommt erschwerend hinzu, dass es als Monolith implementiert ist, der alle notwendige Funktionalität zur Verfügung stellt. Die selbe Plattform dient dazu
Wenn nur eine dieser Funktionen erfolgreich angegriffen wird zieht das in aller Regel das komplette System in Mitleidenschaft. Vor allem aber muss natürlich eine vollwertige Programmiersprache inklusive Laufzeitumgebung vorhanden und öffentlich verfügbar sein, um auch nur eine einzige Web-Seite darzustellen. Damit bietet WordPress nicht nur ein vergleichsweise großes sondern auch ein lohnendes Ziel.
Einen gänzlich anderen Weg gehen wir mit unserem Blog. Der Wise Sensei wird mit Hilfe eines Static Page Generators betrieben. Dabei handelt es sich um ein Programm, dass aus Textdateien fertige, statische Webseiten generiert. Alle Übersichtsseiten, Tags, Vor- und Zurück-Buttons usw. werden einmalig berechnet und dann in einer Ordnerstruktur gespeichert. Abschließend müssen diese Seite nur noch von einem Webserver ausgeliefert werden. Dafür reicht ein Leichtgewicht wie nginx oder sogar der SimpleHTTPServer von Python. Diese Seiten anzugreifen ist - vorbehaltlich einem bösen Bug in nginx selbst - praktisch unmöglich.
Dynamische Inhalte wie Kommentare sind mit so einem System natürlich nicht möglich. Aus diesem Grund binden wir mit Disqus einen Microservice ein, der die Kommentarfunktion zur Verfügung stellt. Sollte Disqus erfolgreich angegriffen werden, verlieren wir im schlimmsten Fall die Kommentarfunktion.
Analog können wir bei Bedarf andere Dienste einbinden, die dann ebenfalls als isolierte Microservices laufen. Durch die klare Abgrenzung der verschiedenen Komponenten lassen sich Korrekturen in der Regel sehr viel leichter vornehmen, weil Seiteneffekte kaum auftreten können.
Wir gehen zudem noch einen Schritt weiter und trennen die Erzeugung der Seiten vollständig von der Anzeige. Der Blog läuft in einem sehr minimalen Docker-Container in der Cloud. Außer dem Webserver, einem rudimentären Betriebssystem und den fertigen Seiten enthält der Container nichts. Sollte es einem Angreifer irgendwie gelingen erfolgreich in den Container einzudringen und ihn vollständig unter Kontrolle zu bringen steht er in einer Sackgasse. Er könnte die HTML-Seiten verändern - aber dann starten wir den Container einfach neu.
Neugierig geworden? Dann schaut wieder rein wenn ich detaillierter erkläre, wie wir mit Hugo, Git, Jenkins, Docker und der Cloud unseren Blog betreiben!
25 Aug 2016 #Injection #Penetration #Exploit #Hugo #CMS #WordPress #Vulnurability #Blog #Microservice #Container #Docker #Cloud