Monat der WordPress-Sicherheit ist beendet

In den letzten Wochen habe ich einige Artikel zur Sicherheit ausgewählter WordPress-Plugins geschrieben. Nun wollte ich abschließend noch einmal ein Fazit ziehen.

Begonnen hatte alles damit, dass auf Golem.de im Abstand von wenigen Wochen über zwei weit verbreitete Plugins mit leicht auffindbaren und dennoch schwerwiegenden Fehlern berichtet wurde. Es hatte mich daher interessiert, wie schlecht es wirklich um die Codequalität bei weit verbreiteten Plugins bestellt ist.

Also begab ich mich zur Liste der beliebtesten Plugins und begann, mir Plugins anzusehen. Dabei habe ich mich auf halbwegs aktuelle Plugins konzentriert, die mindestens 25.000 Downloads hatten. Außerdem sollte die Analyse schnell gehen: Es ging mir nicht darum, Fehler in der Ablauflogik der Plugins zu finden, sondern ich wollte die groben Schnitzer finden - also die Fehler, die einem sofort ins Auge springen. Glücklicherweise verfügt jedes Plugin über ein eigenes Trac-Repository, sodass man direkt online in den Quelltext gucken kann. Damit entfällt das langwierige downloaden, entpacken und im Editor öffnen. So kann man relativ schnell einzelne Plugins abarbeiten.

Ich habe mir etwa 100 Plugins angesehen, die sich vom Namen oder von der versprochenen Funktionalität spannend anhörten. Dabei sind die 12 unten aufgelisteten Plugins aufgefallen, die solche nennenswerten Löcher enthielten (wobei 2 davon Beifang sind - hatte ich ein Plugin mit einer Lücke gefunden, habe ich mir auch die anderen Plugins des gleichen Autors angesehen).

Plugin Angriff Anzahl
WP RSS Aggregator XSS 141.960*
WP CSV Information Leakage 31.675*
WP Advanced Importer Unprivileged File Upload 12.041*
WP Ultimate CSV Importer Unprivileged File Upload 112.793*
Simplr Registration Form Plus+ Information Leakage 105.325*
Form Builder Unprivileged File Upload 88.218*
WordPress File Upload XSS 25.060*
WP Modal Login Privilege Escalation 34.763*
Quick Chat SQL Injection 207,488**
Quick Count SQL Injection 14,268**
Login With Ajax Privilege Escalation 273.635**
FormGet Contact Form XSS 159.545**
Total: 1.206.771
(*Stand vom 16.08.2014)
(**Stand vom 26.08.2014)

Bei der Durchsicht der Plugins sind mir mehrere Dinge aufgefallen:

  1. Viele Plugins sind offenbar eher zufällig "sicher" und nicht etwa, weil der Programmierer das geplant hätte. Oft scheitert ein Angriff nur daran, dass vor einem anfälligen Code eine WordPress-eigene Funktion aufgerufen wird, die (aufgrund ihres Fehlens) zu einer Exception führt, wodurch die Programmausführung beendet wird. Würden solche Aufrufe in eigene Funktion gekapselt werden, wären viel mehr Angriffe möglich.
  2. Nur wenige Plugins schützen sich gegen Cross-Site-Request-Forgeries ab. Sie enthalten derzeit eventuell keine Lücken, sollten diese jedoch durch eine Codeänderung eingeführt werden, ließen sie sich dadurch wesentlich leichter ausnutzen.
  3. Die Punkte 1.) und 2.) rühren oftmals daher, dass die Entwickler sich nicht darum sorgen, ob ihre PHP-Scripte direkt aufgerufen werden dürfen. Vielen Entwicklern ist offenbar nicht bewusst, dass sie ihre Entrypoints und Codepfade kennen und absichern sollten. Dies war die häufigste Fehlerkorrektur, die von mir angeschriebene Plugin-Entwickler umgesetzt haben.
  4. Viele Plugin-Entwicklern verlassen sich darauf, dass eingeloggte Nutzer gutartig sind. Während sie den Eingaben von nicht-eingeloggten Besuchern meist gänzlich misstrauen, werden Eingaben von eingeloggten Nutzern häufig weniger oder gar nicht geprüft. Daher sollte man sich beim Einsatz von Plugins gut überlegen, ob man "Subscriber" in seiner WordPress-Installation zulässt.
  5. WordPress bietet Entwicklern viele fertige Funktionen an, mit denen sie ihre Plugins sicherer machen können - das reicht bis zu fertigen Referer- und Nonce-Prüfungen gegen XSRF-Angriffe. Mir ist jedoch auch aufgefallen, dass WordPress-Nonces relativ lange gültig sind, sich nur an der Zeit orientieren, statt an nutzergebundenen Werten und damit potentiell mehrfach und von verschiedenen Nutzern verwendet werden könnten (was dazu führt, dass ein Angreifer sich regelmäßig einen neuen Nonce holen und diesen für laufende Attacken verwenden könnte).

Die Kommunikation mit den einzelnen Plugin-Entwicklern war bisher durchweg positiv. Viele haben sich gefreut, dass sich jemand tiefer mit ihren Plugins auseinandersetzt und sie über die Probleme informiert. Die meisten haben in weniger als einer Woche das Problem behoben, bei anderen Plugins warte ich darauf hingegen immernoch - dort wurde ein Fix lediglich in Aussicht gestellt. Überrascht hat mich die Reaktion eines Entwicklers, der sein Plugin aufgrund von Zeitmangel aus dem Plugin-Repository entfernt hat. Ich fand, dass dies ein mutiger Schritt war.

Ich fand es spannend, mich in die verschiedenen Programmierstile der einzelnen Plugin-Entwickler einzuarbeiten. Ich habe mich deshalb dazu entschlossen, solche Aktionen in den nächsten Monaten mit den Plugins anderer Content-Management-Systeme zu wiederholen.

Für Leute und Firmen, die WordPress professionell einsetzen, kann ich aufgrund der Ergebnisse eigentlich nur den Rat geben: Wenn Fremdplugins eingesetzt werden, empfiehlt es sich, wenigstens kurz in deren Quelltext zu blicken. Guckt euch an, ob sichergestellt wird, dass die PHP-Scripte nicht direkt aufgerufen werden können. Damit ist bereits viel gewonnen, da der Plugin-Entwickler so viel mehr Kontrolle über den Programmablauf hat.

WordPress-Grüße, Kenny

Bug in FormGet Contact Form Plugin erlaubt Persistive XSS

Heute habe ich noch etwas spannendes für euch: eine Persistive-XSS-Lücke. Das bedeutet, dass man nicht jedem Benutzer den manipulierten Seiteninhalt unterschieben muss, sondern dass diese permanent gespeichert wird und so bei jedem Aufruf der Originalwebseite aktiv wird. Gefunden habe ich diesen Fehler im FormGet Contact Form Plugin.

Dieses besteht nur aus der Datei "index.php" und bietet einen AJAX-Endpunkt in der Funktion "cf_text_ajax_process_request()". Dort werden einfach ungeprüft POST-Parameter in die Plugin-Konfiguration übernommen. Besonders spannend ist die Option "fg_embed_code", die über den POST-Parameter "value" gesetzt wird. Dabei handelt es sich um Code, der später über die Funktion "embeded_code()" in jeder Seite des WordPress-Blogs eingebunden wird: Jackpot!

Die Einbringung von eigenem Code funktioniert relativ einfach über ein HTML-Formular, das ein Angreifer einmalig benutzen muss:

1
2
3
4
5
6
7
<form action="http://example.com/wp-admin/admin-ajax.php" method="POST">
  <input type="hidden" name="action" value="request_response" />
  <input type="hidden" name="value" value="<script>alert('XSS.');//sideBar</script>" />
  <input type="hidden" name="value_hide" value="" />
  <input type="hidden" name="page_id" value="" />
  <input type="submit" />
</form>

Ich stand mit den Entwicklern in Kontakt, die mir auch mitgeteilt hatten, etwas auf der Serverseite gefixt zu haben. Auf meine Anmerkung hin, dass der Fehler im Plugin sei und nicht in ihrer Serveranwendung, erhielt ich jedoch keine Antwort mehr. Solange kein Patch verfügbar ist, kann der Rat deshalb nur lauten, das Plugin umgehend zu deaktivieren.

Persistente Grüße, Kenny

Bug in Login With Ajax Plugin erstellt Nutzeraccounts

Anfang dieser Woche hatte ich über ein Plugin informiert, mit dem ein Angreifer ungefragt neue Nutzer anlegen kann. Damit ist das vorgestellte Plugin leider nicht allein. Denn auch das Login With Ajax Plugin hat diese unschöne Sonderfunktion.

In der Datei "login-with-ajax.php" befindet sich die Klasse "LoginWithAjax", die man mit einem präparierten Formular dazu bringen kann, neue Accounts anzulegen - selbst dann, wenn die Registrierung neuer Nutzer eigentlich in der WordPress-Konfiguration ausgeschaltet wurde:

1
2
3
4
5
6
7
<form action="http://example.com/" method="POST">
  <input type="hidden" name="lwa" value="true" />
  <input type="hidden" name="login-with-ajax" value="register" />
  <input type="hidden" name="user_login" value="exploit" />
  <input type="hidden" name="user_email" value="exploit@example.com" />
  <input type="submit" />
</form>

Ich bekam vor mehreren Wochen von den Entwicklern die Aussage, dass sie das Problem ASAP beheben würden. Seitdem ist jedoch nichts mehr geschehen. Der Tipp an dieser Stelle kann deshalb nur lauten, dass Plugin zu deaktivieren, bis es ein Update gegeben hat. Viele andere Plugins prüfen häufig lediglich, ob ein Nutzer eingeloggt ist, bevor sie ihre Funktionalität bereitstellen - diese Absicherung kann derzeit umgangen werden.

Update:
In der Version 3.1.3 wurde dieser Fehler nun endlich behoben.

Nochmal registrierende Grüße, Kenny

Bug in Quick Chat Plugin erlaubt SQL-Injection

In dem WordPress-Plugin Quick Chat befinden sich Bugs, die es einem Angreifer ermöglichen, SQL-Injections durchzuführen. Das Plugin ist dafür gedacht, einen einfachen Chat im eigenen Blog bereitzustellen.

Das Problem beginnt im Constructor der Klasse "Quick_Chat", der sich in der Datei "quick-chat.php" befindet: Dort wird versucht, die IP-Adresse des Clients in Erfahrung zu bringen. Dabei wird auch der HTTP-Header "X-Forward-For" mit berücksichtigt.

Dieser Wert wird dann (ungeprüft) in der Methode "new_message_ajax_handler()" in einem INSERT-Statement verwendet - also immer dann, wenn ein Nutzer eine neue Nachricht schreibt. Auch in der Methode "update_users_ajax_handler()" kommt dieser Wert ungeprüft zum Einsatz - also regelmäßig, wenn der Status der Clients aktualisiert wird. Ausnutzen kann man das ganze, indem man einfach den "X-Forward-For"-Header mit seinem SQL-Injection-Code versieht. Das ganze kann dann zum Beispiel so aussehen:

Quick Chat Injection

Quick Chat Injection

Hier habe ich das Tool Charles verwendet, um einen präparierten Header einzufügen. Dieser bewirkt, dass nicht der vom Nutzer geschriebene Text im Chatraum erscheint, sondern das (gehashte) Passwort vom WordPress-User mit der ID "1".

Auch das Plugin Quick Count verwendet in der Datei "quick-counter.php" einen ähnlichen Code in der Methode "report()" und sollte dadurch mit ähnlichen Problemen zu kämpfen haben.

Der Rat an dieser Stelle: Die Plugins sofort deaktivieren und warten, bis es ein Update gibt.

Injizierende Grüße, Kenny

Bug in WP Modal Login Plugin erstellt Nutzeraccounts

Heute mal ein spannender Bug: Das WP Modal Login bietet einem die Möglichkeit, überall auf der Seite einen Login-Screen aufzurufen. Dafür richtet man an der entsprechenden Stelle einfach einen Shortcode ein - das Login-Formular wird dann einfach als Overlay angezeigt:

1
[wp-modal-login login_text="Login" logout_text="Logout"]

Leider hat das ganze einen kleinen Schönheitsfehler, denn die Klasse "./includes/class-wp-modal.php" enthält nicht nur die Funktion, sich einzuloggen, sondern sie kann auch neue Nutzer anlegen. Das funktioniert sogar dann, wenn die Registrierung neuer Nutzer in der WordPress-Konfiguration deaktiviert wurde. Die Funktion wird zwar nicht über das Login-Formular bereitgestellt, aber es verarbeitet trotzdem entsprechende Anfragen.

Exploit mit Charles Proxy

Exploit mit Charles Proxy

Das ist sehr unglücklich, denn viele andere Plugins verlassen sich darauf, dass ein Angreifer keinen Account für die Webseite hat. Oft bestehen Sicherheitsabfragen nur daraus, zu prüfen, ob ein Nutzer eingeloggt ist oder nicht.

Da der Entwickler laut der Projekt-Webseite keine Zeit mehr für die Pflege des Plugins hat, kann der Rat nur lauten, das Plugin so schnell wie möglich zu deaktivieren. Der Entwickler hat sich - nach Rücksprache mit mir - jedenfalls dazu entschlossen, das Plugin aus dem Plugin-Repository zu entfernen.

Registrierende Grüße, Kenny

Seite 1 von 81123...Letzte »