…I'll walk into a bar and drink fifteen pints of beer

Wordpress: Sicherheitslücke in 2.8.3

Durch einen Bug in der aktuellen Wordpress-Version ist es möglich, das Passwort eines Benutzers bzw. des Admins zu ändern. Wie auch caschy schreibt, hält sich der mögliche Schaden in Grenzen, solange der Angreifer keinen Zugriff auf das Mailkonto des Admins hat, denn der Angreifer kann dass Passwort nicht auf einen beliebigen Wert setzen. Es wird lediglich die Passwort-Reset-Funktion von Wordpress durchgeführt, ohne dass der betroffene User davon erfährt. Nach einem erneuten Passwort-Reset durch den User kann dieser sein Konto ganz normal benutzen.

Um diese Sicherheitslücke zu schließen, reicht es, in der wp-login.php einige Zeichen einzufügen. So muss die Zeile 190 von

if ( empty( $key ) )

in

if ( empty( $key ) || is_array( $key ) )

geändert werden.

Der Hintergrund dieser Lücke ist, dass der reset_password-Funktion ein Parameter $key übergeben wird, der den Hashwert zum bestätigen der Passwortänderung darstellt. Ist dieser Wert leer, gibt Wordpress in Zeile 190/191 einen Fehler aus

	if ( empty( $key ) )
		return new WP_Error('invalid_key', __('Invalid key'));

Bevor aber geprüft wird, ob $key leer ist, wird ein preg_replace auf den key ausgeführt (Zeile 188)

$key = preg_replace('/[^a-z0-9]/i', '', $key);

Tatsächlich ist mir der Sinn dieser Zeile nicht ganz eindeutig klar; auf jeden Fall gibt preg_replace in diesem Falle einen leeren String zurück, wenn $key nur aus Kombinationen kleiner Buchstaben und Zahlen besteht. Falls jedoch $key ein Array ist, gibt auch preg_replace ein Array zurück. So schließt sich der Kreis zu Zeile 190: Wenn man es schafft, die $key-Variable als Array zu übergeben, wird das Passwort des Users geändert, ohne dass dieser eine Mailbenachrichtigung bekommt, da die Funktion empty($variable) so mit Arrays nicht funktioniert (und für ein nicht-leeres Array false zurückgibt).
Der Angreifer muss es also nur schaffen, den Key als Array zu übergeben. Wie das funktioniert, werde ich hier nicht verraten – wer sich aber für weitere Details der Lücke interessiert, sollte mal hier vorbeischauen.

Es ist sehr leicht, diese Lücke auszunutzen und im Allgemeinen sollte daraus kein großer Schaden entstehen. Ich bitte trotzdem all diejenigen, die im Stande sind, den Exploit anzuwenden, dies nicht zu tun.

Update:
Eine bessere Lösung, statt is_array in Zeile 190:

if ( empty( $key ) || !is_string( $key ) )

16 comments

1 Blubb { 08.11.09 at 12:13 }

“Ich bitte trotzdem all diejenigen, die im Stande sind, den Exploit anzuwenden, dies nicht zu tun.”

Diejenigen die es tun wollen werden es tun – egal was du hier schreibst :-)

2 Sicherheitslücke in WordPress 2.8.X – Admin password reset exploit | Perrys Blog { 08.11.09 at 12:41 }

[...] Erklärung, weshalb dieses Verhalten auftritt, könnt ihr bei filzo [...]

3 Philipp { 08.11.09 at 12:44 }

@Blubb: bitten kann ich sie trotzdem :)

4 Helge { 08.11.09 at 13:08 }

Ich will ja nicht klugscheißen, aber war es nicht die wp-login.php in der das geändert werden muss? Bei Dir steht was von wp-admin.php (diese Datei gibt es auch im Übrigen gar nicht!)

just my 2 cents.

5 ocean90 { 08.11.09 at 13:58 }

@Helge
Richtig, ist wohl ein Tippfehler.
Es sollte aber nicht der oben genannte Fix getätigt werden, sondern eher diesen.

6 Philipp { 08.11.09 at 14:07 }

Hab den Eintrag entsprechend angepasst.

7 » Der Wordpress-Bug des Tages: Einfach mal den Blo … Nachtwächter-Blah { 08.11.09 at 14:21 }

[...] Wordpress-Bug des Tages: Einfach mal den Blogger aus seinem eigenen Blog aussperren, indem man ihn das Passwort ändert. Gut, der kriegt das neue Passwort per Mail, aber wenn er aus bestimmten Gründen keine aktive [...]

8 WP 2.8.x Admin reset exploit - Lighty mod_auth | Total Verfriemelt { 08.11.09 at 16:10 }

[...] | Linux, Total Verfriemelt, Verfriemelungen Bei Caschy gerade drüber gestolpert und bei Filzo gibt es den technischen [...]

9 Gabriel { 08.11.09 at 16:19 }

Die Zeile
$key = preg_replace(‘/[^a-z0-9]/i’, ”, $key);
macht, dass in $key nur Kleinbuchstaben und Ziffern stehen.
Alles andere (daher “^a-z0-9″) wird entfernt (Ersetzung durch ”)

10 Philipp { 08.11.09 at 16:35 }

Und was ist der Sinn dahinter? :) Der blieb mir bisher verborgen.

11 WordPress: 2.8.4 – Sicherheitsrelease > Sicherheitslücke, Update, WordPress > splash ;) { 08.12.09 at 7:45 }

[...] es nun ein Sicherheitsupdate, das unbedingt eingespielt werden sollte (insbesondere, da die “erste Lösung” wohl keinen wirklichen Schutz [...]

12 Wordpress 2.8.4: Bitte updaten! — filzo.de { 08.12.09 at 9:22 }

[...] Wordpress wurde nun auf die gestern auch hier veröffentlichte Sicherheitslücke reagiert, und ein Security Relase mit der Versionsnummer 2.8.4 [...]

13 Kiddie-Exploit: Wordpress 2.8.3 Admin abssperren. | 1337blog { 08.12.09 at 13:00 }

[...] Meldung einer Sicherheitslücke in Wordpress hat gestern schon die Runde gemacht. Es macht mir Angst wie die Programmierer der Blogsoftware arbeiten. Es ist super, dass sie [...]

14 WordPress 2.8.4 veröffentlicht | Roman Harcke { 08.12.09 at 13:42 }

[...] Filzo’s Blog KeyWords: >> neue Version, WordPress, WordPress Update [...]

15 Matu { 08.12.09 at 22:17 }
$key = preg_replace('/[^a-z0-9]/i', '', $key);

Tatsächlich ist mir der Sinn dieser Zeile nicht ganz eindeutig klar; auf jeden Fall gibt preg_replace in diesem Falle einen leeren String zurück, wenn $key nur aus Kombinationen kleiner Buchstaben und Zahlen besteht.

Auf jeden Fall ist das Blödsinn!
Wenn in der Variablen $key ein Passwort gespeichert/enthalten ist, dieses aber nicht (^ = Negation) aus Buchstaben oder Zahlen besteht, wird der Inhalt der Variablen $key durch einen Leerstring ersetzt.
Dadurch greift die nächste Zeile “if ( empty( $key ) …” und generiert einen Error. Durch diese Maßnahme wird das “Einschleusen” von Code oder sonstigen Zeichen unterbunden = Sicherheitsmaßnahme, die hier etwas schluderhaft umgesetzt wurde.
Übrigens bemerkenswert, wie viele Leute/ Blogbetreiber darüber herziehen, die 0 Ahnung von der Materie haben … ich verzeihe dem Programmierer (lehrt es mich doch selber wieder, Eingaben penibler zu überprüfen).
Das kleine ‘i’ im regulären Ausdruck macht diesen übrigens ‘Case-Insensitivity’, d.h. Groß- und Kleinschreibung wird nicht beachtet. Statt dessen könnte man auch ‘/[^a-zA-Z0-9]/’ schreiben.

16 Philipp { 08.14.09 at 0:54 }

Danke für die Erklärung – was reguläre Ausdrücke angeht, bin ich nicht gerade sonderlich fit :)

Leave a Comment