WordPress Security: Von Menschen und Maschinen

Obwohl grundsätzlich recht sicher, kann auch Wordpress vielen potentieller Bedrohungen ausgesetzt sein. Welche (Gegen-)Maßnahmen können sinnvoll sein?

WordPress ist das meistverwendete Content Management System (CMS) weltweit. Im Rahmen eines Kundenprojekts, das in der Vergangenheit leider mehrfach Ziel von Hackangriffen war, musste ich mich neulich mit der Frage auseinandersetzen:

Wie kann man eine WordPress-Installation bestmöglich absichern?

Zu allererst, die schlechte Nachricht: Bei jedem Gerät, jeder Website und jedem Dienst, den man direkt oder indirekt mit dem Internet verbindet oder über das Internet bereitstellt, muss man sich im Klaren darüber sein, dass es nie einen 100%-igen Schutz gegen Hacker und Eindringlinge geben wird. Egal ob Open Source-Anwendungen oder proprietäre (Closed-Source-)Lösungen, potentielle Sicherheitslücken oder, schlichtweg, Versäumnisse bei der Entwicklung von Softwarelösungen wird es immer geben. Auch wenn man tendenziell meinen sollte, dass potentielle Sicherheitslücken innerhalb einer aktiven Open Source Community schneller identifiziert und ggf. geschlossen werden, gibt es sicher auch immer Individuen, die es gerade wegen der Quelloffenheit auf derartige Systeme abgesehen haben.

Nun die gute Nachricht: Achtet man darauf möglichst mit der aktuellsten Version des WordPress-Cores zu arbeiten, nur vertrauenswürdige Plugins und sichere Themes zu installieren – und auch diese auf dem aktuellsten Softwarestand zu halten -, ist WordPress auch eines der sichersten CM-Systeme.

Was sind nun aber die häufigsten oder wahrscheinlichsten Probleme, mit denen man sich im Alltagsbetrieb konfrontiert sehen könnte?

Identitätsdiebstahl/ Ausspähen von Nutzerdaten

Ähnlich wie am heimischen PC, ist auch der Admin-Bereich von WordPress standardmäßig mit einer Kombination aus Nutzername und Passwort gesichert. Zwar wird sich vermutlich kein Hacker die Mühe einer Phishing-Kampagne zum Ausspähen der Zugangsdaten zu einer WordPress-Installation machen, jedoch kommen sogenannte Brut-Force-Angriffe verhältnismäßig häufig bei. Bei dieser Art des Hackings werden verschiedene Nutzer-Passwort-Kombinationen so lange ausprobiert bis eine gültige Kombination gefunden wurde, so dass sich der Angreifer anschließend in die Website einloggen und Änderungen durchführen kann.

Eine häufig gefundene Empfehlung zur Vorbeugung dieses Problems lautet die Login-Seite zu verstecken, indem man die Standard-Anmelde-URL verändert. Zwar kann dies u.U. sinnvoll sein, jedoch sollte man sich nicht der falschen Sicherheit hingeben, dass dadurch das zugrundeliegende Problem gelöst würde. Vielmehr sollte man:

  • möglichst schwer zu erratende Nutzernamen und möglichst sichere Passworte verwenden
  • eine zusätzliche Sicherheitsüberprüfung mittels Multi-Faktor-Authentifizierung einrichten
  • die Zahl der möglichen Login-Versuche, mithilfe entsprechende Plugins, begrenzen. Dies kann entweder dadurch erreicht werden, dass der zugehörige Nutzeraccount gesperrt wird oder es wird die IP-Adresse eines potentiellen Angreifers als Risiko eingestuft und zu einer sogenannten Blacklist hinzugefügt.

Ein ausführlicher Artikel zum Thema „Sicherheit von Kennwörtern“ findet sich auch in der aktuellen Ausgabe der Zeitschrift Spektrum der Wissenschaft.

Distributed Denial of Service

Als Distributed Denial of Service (DDoS)-Attacke wird ein Angriff bezeichnet, bei dem so viele Anfragen an eine Website gesendet werden, dass diese überlastet wird und der zugehörige Service nicht mehr zur Verfügung steht. Ein Angriff entsprechend der zuvor beschriebenen Brute-Force-Attacke kann u.a. auch zu einem Denial of Service führen, z.B. wenn zu viele Versuche parallele Versuche unternommen werden die Zugangsdaten zu ermitteln.

Bei Verwendung eines Shared Hosters zur Bereistellung einer Website, hat dieser meist ein eigenes Interesse daran ihre Systeme vor einem DDoS-Angriff zu schützen. Auf Installationsebene lässt sich dies aber z.B. durch eine Web Application Firewall unterstützen, bei der die Anzahl der erlaubten Anfragen pro Zeitfenster für eine IP-Adresse begrenzt werden. Dadurch soll verhindert werden, dass einzelne Computersysteme eine Website derart belasten.

Man-in-the-Middle

Bei einem Man-in-the-Middle-Angriff versucht ein potentieller Angreifer die zwischen zwei Computersystemen ausgetauschten Datenpakete abzufangen und deren Inhalt auszulesen.

Gerade beim Versand vertraulicher oder personenbezogener Daten ist es wichtig zu verhindern, dass ein potentieller Eindringling in der Lage ist etwas Sinnvolles mit den Datenpaketen anzufangen. Dies kann daruch erreicht werden, dass die Website mittels SSL/ TLS abgesichert wird. Dabei werden die Datenpakete vor dem Austausch mithilfe eines Zertifikats bzw. kryptographischen Schlüsseln so verschlüsselt, das es nur dem Empfänger möglich ist die Datenpakete wieder lesbar zu machen.

Das Projekt Let’s Encrypt hat sich z.B. der Bereitstellung kostenloser Zertifikate auch für private Webprojekte verschrieben.

Schadcode und -Software

Wie bei nahezu jeder anderen Software bzw. Infrastruktur auch, kann auch eine WordPress-Installation mit Schadsoftware infiziert werden:

SQL-Injection

Als einer der Klassiker für fast jede (Web-)Software, die Textfelder z.B. für die Nutzerregistrierung bereitstellt und Inhalte in einer Datenbank abspeichert, führt eine SQL-Injection dazu, dass z.B. über ein öffentliches Eingabefeld schädlicher Code in die Datenbank eingeschleußt wird. Im einfachsten Fall handelt es sich um JAVA Script-Code, der bei jedem Aufruf der Seite mit ausgeführt wird und z.B. das Ranking einer anderen Website für eine Suchmaschine verbessert; Im schlechtesten Fall, sorgt der der Code z.B. dafür, dass Nutzerdaten ausgelesen werden können oder die zugehörige Datenbank unbrauchbar gemacht wird.

Ein Effektiver Schutz gegen diese Art der Attacken besteht nur darin, dass vor dem Absenden einer Eingabe, diese auch auf Gültigkeit geprüft und ggf. zurückgewiesen wird.

Malicious Redirects und Cross-Site-Scripting

Wurde z.B. der FTP-Account, der üblicherweise zum Hochladen und Aktualisieren von Dateien verwendet wird, korrumpiert oder Code-Dateien – wie z.B. hochgeladene PHP-Skripte – ausgeführt, die eigentlich hätten blockiert werden sollen, kann ein Angreifer z.B. die .htaccess-Datei, die im Hauptverzeichnis jeder WordPress-Installation zu finden ist, so manipulieren, dass ein Aufruf ihrer Seite zu einer Weiterleitung auf eine andere Seite führt.

Ein Artikel wie derartige Angriffe bestmöglich verhindert werden können ist im zugehörigen Artikel auf wordfence.com zu finden.

Plugins

Augen auf bei der Plugin-Installation! Auch wenn ich davon überzeugt bin, dass die Mehrheit der Plugin-Entwickler diese mit der größtmöglichen Sorgfalt und nach bestem Wissen und Gewissen entwickelt, führen gerade Plugins von Drittanbietern dazu, dass man sich (potentielle) Sicherheitslücken in sein System aktiv hineininstalliert.

Um dies zu verhindern, empfiehlt es sich vor jeder Installation eine kurze Recherche zu dem jeweiligen Addon durchzuführen und dieses nur dann zu installieren, wenn man zumindest eine Idee von der Funktionsweise und den potentiellen Risiken hat.

Ähnlich wie die Liste möglicher Schadanwendungen für Desktop- und Mobile-Devices täglich zunimmt, könnte ich auch die Liste der möglichen Schadsoftware für Ihr WordPress-System z.B. noch um Cookie Stealthing, Enumeration-Angriffe und viele Weitere Angriffstypen erweitern. Wer wirklich mal eine unruhige Nacht haben möchte, dem sei die Seite hackertarget.com ans Herz gelegt.

Eine generelle Sicherheitsmaßnahme zum Schutz vor unbeabsichtigten oder unberechtigten Änderungen sollte immer auch einen Backup-und-Wiederherstellungsplan beinhalten. D.h. unabhängig von allen anti-Viren-Anwendungen, die es auch WordPress gibt, schützt u.U. nichts so gut wie eine regelmäßige Sicherung mit ggf. entsprechend langen Aufbewahrungsfristen der Sicherungsdateien. Natürlich wird es weh tun ggf. Inhalte und Weiterentwicklungen eines längeren Zeitraums zu verlieren, aber nichts wird so wehtun als die komplette Website von vorn anlegen zu müssen.

Der Mensch

Zuletzt noch ein paar philosophische Gedanken: In der Summe betrachtet, kann man sich als Administrator (einer WordPress-Site) noch so viel Gedanken um die technische Absicherung machen, wenn der oder die Anwender – z.B. aufgrund fehlender Awareness oder Verständnis – Unvorsichtigkeit walten lassen.

Das soll nicht heißen, dass meine Empfehlung lautet, dass niemand anderer als den Admin selbst mit dem System arbeiten soll, denn auch dieser hat bessere und schlechtere Tage. Es soll bedeuten, dass jedes IT-System nur in dem Maße als sicher angesehen werden kann, in dem der Mensch vor dem Computer Vorsicht und Achtsamkeit walten lässt. Es wird immer Personen mit zweifelhaften Absichten geben und im Zweifelsfall rennt man, beim Versuch das Riko potentieller Bedrohungen auf die eigene Website zu eleminieren, Angreifern immer hinterher.

Nichts zu tun und zu hoffen, dass es das eigene System nicht treffen wird, ist tendenziell aber immer falsch – und bereits mit teilweise recht kleinen Maßnahmen kann man beim Thema „Sicherheit“ große Erfolge erzielen.

Gesucht, gefunden:
Ein wiederverwendbarer Extensions-Manager für .net

Das Managed Extensibility Framework – richtig eingesetzt, eine leichtgewichtige Alternative zu Bibliotheken wie Prism & Co.

Die Zeiten, in denen neue Anwendungen in Form monolither Softwaremonster entwickelt worden sind, sind (hoffentlich) inzwischen überall vorbei. Während gerade bei komplexen und/ oder über viele Dienste verteilten Anwendungen häufig eine Microservice-Architektur zum Einsatz kommt, profitieren häufig aber auch zunächst nur für den lokalen Einsatz konzipierte Anwendungen von einem gewissen Grad der Modularisierung:

  • Neue Funktionen können auch ohne ein komplettes Refactoring hinzugefügt werden; häufig auch solche, die im Rahmen eines ersten Konzepts noch gar nicht vorgesehen waren
  • Der Wartungsaufwand bzw. die Fehlersuche kann deutlich reduziert werden indem die Gesamtanwendung in kleine, gut wartbare Codeabschnitte zerlegt wird
  • Mehrere Programmierer oder Teams können parallel an der Entwicklung der Software arbeiten, z.B. indem ein Team sich auf den Anwendungskern und die Schnittstellen konzentriert, während sich andere Entwickler mit der Implementierung der (Fach-)Funktionen befassen

Kernstück dieses Design-Konzepts ist die lose Kopplung der Plugins, wobei eine Hostanwendung die notwendige Schnittstellen und Basis-Datentypen bereitstellt und sich anschließend um das Auffinden und Instanzieren der verschiedenen Schnitstellenimplementierungen kümmert. Sie sorgt ebenfalls dafür, dass die verschiedenen Erweiterungen (engl. Extensions) bei Bedarf auch gut miteinander kommunizieren können.

Häufig kommen zum Aufbau einer solchen Architektur spezielle Bibliotheken von Drittanbietern zum Einsatz. Eine davon ist Prism. Nicht selten ist es dabei notwendig ganz bestimmte Design-Muster oder Namenskonventionen im Quellcode einzuhalten. Dies gilt zwar auch für das Managed Extensibility Framework (MEF), dafür ist dieses aber ohne zusätzliche Installationen, Lizenzen oder Abhängigeiten nutzbare, da es – als Bestandteil des .net-Frameworks (auch .net Core) – standardmäßig mitinstalliert wird.

Ein komplettes MEF-Tutorial würde wohl den Rahmen dieses Beitrags sprengen. Zudem gibt es bereits gute Artikel zu diesem Thema, so viel aber trotzdem dazu: MEF basiert auf Reflection, was bedeutet, dass, basierend auf einer Liste von Assemblies oder Datei- und Verzeichnispfaden, ein Katalog von Schnittstellenimplementierungen erstellt wird, der als Auflistung von Lazy-Objekten zur Verfügung steht. Mithilfe von Metadaten können die Erweiterungen beschrieben werden, so dass z.B. ein bestimmtes Plugin gefunden und ausgeführt werden kann. Stefan Henneken hat in dieses Konzept in einem entsprechenden Artikel ausführlich beschrieben.

Auch wenn MEF-Features mit wenigen Zeilen Code genutzt werden können, empfiehltsich die Erstellung einer wiederverwendbaren Bibliothek, um ggf. zusätzliche Funktionen nutzen oder bereitstellen zu können. In der von mir öffentlich bereitgestellten BYTES.NET-Bibliothek findet sich eine derartige Manager-Klasse.

ExtensionsManager stellt eine Update-Funktion zur Verfügung, die, basierend auf einem Array von Dateisystempfaden, die Plugins enumeriert und als Extensions-Eigenschaft bereitstellt. Um die Klasse möglichst flexibel zu halten, wurde sie mit generischen Typen dekoriert, so dass sie z.B. wie folgt instanziiert werden kann:

Dim _manager as ExtensionsManager(of MyInterface, MyMetadata) = new ExtensionsManager(of MyInterface, MyMetadata)

Damit dies möglich ist, musste die private Variable _allExtensions, die das Ergebnis der MEF-Katalogerstellung beinhaltet, mit ImportMany ohne Angabe eines einschränkenden Datentyps dekoriert werden. Leider unterstützt MEF aktuell keine generischen Datentypen.

<ImportMany()>
Private _allExtensions As ObservableCollection(Of Lazy(Of TInterface, TMetadata)) = New ObservableCollection(Of Lazy(Of TInterface, TMetadata))

Das bedeutet aber auch, dass MEF zunächst alle gefundenen Plugins, unabhängig vom jeweiligen Datentyp/ Interface, zurückgibt. Solange die Anwendung lediglich über eine einzelne Schnittstellendefinition verfügt, ist dies unproblematisch. Schwieriger wird es bei mehreren Interfaces.

Um dennoch auch mit multi-Interface-Anwendungen kompatibel zu sein, wurde Update mit dem Aufruf der ValidateExtensions-Methode erweitert:

Private Sub ValidateExtensions()
    _validExtensions = New ObservableCollection(Of Lazy(Of TInterface, TMetadata))

        For Each extension In _allExtensions
            Try
                If ImplementsInterface(extension) Then
                    _validExtensions.Add(extension)
                End If
             Catch ex As Exception
             End Try
         Next

End Sub

Diese Methode durchläuft alle gefunden Extensions und prüft ob das als (generischer) Datentyp definierte Interface implementiert wird. Ist dies der Fall, wird das Plugin zur Liste valider Plugins (für diesen Manager) hinzugefügt.

Neben dem (Standard-)ExtensionsManager, enthält die BYTES.NET auch noch eine ExtendedExtensionsManager-Klasse, die es ermöglicht Plugins über Pfade zu finden, die mithilfe von Wildcards definiert wurden bzw. Erweiterung mithilfe einer ID in die Ausgabeliste hinzuzunehmen oder davon auszuschließen. Ein entsprechendes Beispiel ist in der Beispiel-Anwendung im zugehörigen Github-Repository zu finden.