Wordpress: Eine Studie in Scharlachrot Marc Ruef | 31.08.2009 Es gibt verschiedene Produkte, die haben sich über Jahre einen Namen in Security-Kreisen gemacht. Und zwar keinen Guten. Die erste Software mit einem zwielichtigen Titel war der wohl populärste Mail Transfer Agent aller Zeiten: Sendmail. Nicht umsonst nannte man ihn "buggiest daemon on earth". Eine hohe Anzahl an kritischen Schwachstellen wurden über die Jahre entdeckt. Rückblickend waren die meisten davon auf die Komplexität der Software zurückzuführen. Viele andere Applikationen machten Sendmail den Titel streitig. Sei dies nun Microsoft IIS als Webserver, Microsoft Internet Explorer als Webbrowser oder phpBB als Webforum. Eine Software kann um diesen Titel jedoch nur buhlen, wenn ihre Popularität sehr gross ist und sich entsprechend ein Mehr an Penetration Testern und Crackern für sie interessieren. Ähnliches ist deshalb auch Wordpress widerfahren, das gut und gerne als Blogging-Software eingesetzt wird. Schwachstellen in Wordpress tauchen alle paar Wochen (http://www.scip.ch/?vuldb.wordpress) auf. Und schaut man sich die Details zu diesen an, muss man sich oftmals an den Kopf langen, was die Entwickler denn da wieder studiert haben ... oder halt eben nicht. Als Laurent Gaffie am 11. August 2009 auf Full-Disclosure eine Denial of Service-Schwachstelle in den Versionen bis 2.8.3 publiziert (http://lists.grok.org.uk/pipermail/full-disclosure/2009-August/070137.html) hat, habe ich mir die Zeit genommen und mal wieder ein bisschen den Code von Wordpress durchgeschaut. Einmal mehr bin ich zum Schluss gekommen, dass Wordpress ein sehr gutes Beispiel für sicherheitstechnisch schlecht geschriebenen Source Code ist. Ein schönes Beispiel findet sich in der Datei wp-login.php. Diese wird verwendet, um neue Benutzer zu erstellen, sich einzuloggen/auszuloggen und ein neues Passwort zuzustellen. Hierbei ist besonders Zeile 188 (http://core.trac.wordpress.org/browser/branches/2.8/wp-login.php?rev=11798) interessant: code$key = preg_replace('/^a-z0-9/i', '', $key);/code Zu Beginn der Funktion reset_password($key) wird die Eingabe einer vermeintlichen Prüfung unterzogen. Hierzu wird die erweiterte PHP-Funktion preg_replace() (http://www.php.net/preg_replace) verwendet. Diese benutzt reguläre Ausdrücke, um Muster in einer Zeichenkette zu ersetzen. In diesem Fall werden sämtliche Zeichen, die nicht alphanummerisch sind, durch nichts ersetzt (also gelöscht) und mit dem Überbleibsel weitergearbeitet. In vielerlei Hinsicht ist dies eine äusserst unelegante, ineffiziente und unsichere Lösung: 1. Die Funktion preg_replace() (http://www.php.net/manual/en/function.preg-replace.php) ist sehr ressourcenintensiv. Man sollte stets Funktionen ohne reguläre Ausdrücke verwenden - Vor allem bei solch simplen Pattern. Dies könnte beispielsweise das weitaus performantere str_replace() sein. 2. Die unliebsamen Zeichen werden gelöscht, der Rest des Konstrukts aber weiterverwendet, indem es erneut in die Ursprungsvariable $key geschrieben wird. Sollte irgendwann vorgelagert eine Eingabeprüfung erfolgen, kann diese mit einer klassischen Splitting-Attacke umgangen werden. Der Inhalt von $input der Form "script!" würde zugelassen, dann in "script" umgewandelt und damit die Cross Site Scripting-Attacke umgesetzt werden können (sehr einfaches Beispiel): codeif(strpos($input, 'script') !== FALSE)){    die('Attack detected.'); }else{    reset_password($input); }/code 3. Im genannten Code wird für $key ein MD5-Hash aus der Datenbank erwartet. Dieser wird mit "SELECT user_activation_key FROM $wpdb->users WHERE user_login = %s" geholt. Er ist naturgemäss immer 32 Zeichen lang und besteht lediglich aus den Buchstaben a bis f und den Ziffern 0 bis 9. Entsprechend ist es fragwürdig, warum nicht zusätzlich eine striktere Prüfung des Zeichensatzes sowie zusätzlich der Länge der Eingabe erfolgt und bei Verstössen die Weiterverarbeitung unverzüglich abgebrochen wird: codeif(preg_match('/a-f0-9{32}/', $input)){    reset_password($input); }else{    die('Invalid MD5 hash detected.'); }/code Die Entwickler von Wordpress generieren sich durch ihre Art der defensiven Programmierung immerwährend neue Probleme. Es würde mich nicht verwundern, wenn in den nächsten paar Jahren die genannte Zeile 188 wieder zur Diskussion stehen würde. Im Rahmen einer Source Code Analyse (http://www.scip.ch/?dienstleistungen.sourcecodeanalysis) würde ich der besprochenen Codezeile jedenfalls die Risikostufe "High" zuweisen. Dies bedeutet, dass das Problem ohne Diskussion zeitnah gelöst werden muss. Bis dahin kann lediglich gehofft werden, dass das Kartenhaus nicht erneut an anderer Stelle zusammenbricht.