PHPGangsta - Der praktische PHP Blog

PHP Blog von PHPGangsta


HashDoS Angriff legt (unter anderem) PHP lahm

with 9 comments

Ich bin leider die letzten 2 Tage nur wenige Stunden dazu gekommen die Live-Streams vom 28. Chaos Communication Congress (28C3) zu schauen, aber bzgl. PHP ist heute Nachmittag ein interessanter Talk gehalten worden mit dem Thema Effective Denial of Service attacks against web application platforms dem ich hier einen kurzen Artikel widmen werde.

Es geht darum wie PHP (und die anderen anfälligen Sprachen auch) Hash-Tabellen erstellen und verwalten. Die hier interessante Hash-Tabelle ist das $_POST Array, das man von außen füllen kann, und das anfällig ist wenn man nur genügend „passende“ Datensätze reinfüllt. Der Algorithmus der die Hash-Tabelle befüllt wird nämlich langsamer sobald Kollisionen der Keys auftreten. Schickt man also beispielsweise 300KB POST-Daten an ein PHP-Script ist eine schnelle CPU damit ca. 30 Sekunden unter Volllast. Bei 8MB (dem Standard-Maximum für POST-Daten in der php.ini) wären es immerhin schon 5 Stunden, die die CPU benötigt um die Hash-Table zu füllen. Man kann also mit einer relativ kleinen DSL-Leitung einigen Schaden anrichten. Mit einer Gigabit-Leitung kann man so 10.000 CPU-Kerne dauerhaft beschäftigen.

Etwas Abhilfe schaffen da die Einstellungen max_input_time und max_execution_time, die je nach Distribution 30 Sekunden, 60 Sekunden bzw. nicht beschränkt sind. Man müßte also mehrere kleine Anfragen schicken und kann nicht die 8MB ausnutzen. mit ca. 500KB kann man einen CPU-Kern dann etwa eine Minute beschäftigen.

Das Problem ist wohl seit 2003 bekannt, Perl hat es damals behoben indem in die Generierung des Hash-Index auch Zufall mit einfließt, und nicht nur der Key die Hash-Position bestimmt. Neben PHP sind übrigens auch Java, Apache Tomcat, Apache Geronimo, Jetty, Oracle Glassfish, ASP.NET, Python, Plone, CRuby 1.8, JRuby, Rubinius und v8 (Node.JS) betroffen (Details zu betroffenen und gefixten Versionen).

Abhilfe schafft beispielsweise die PHP-Extension Suhosin, mit der die Anzahl an POST-Variablen beschränkt werden kann (Standard ist 200). Seit 3 Wochen gibt es auch einen Patch für PHP der eine neue php.ini Variable max_input_vars (Standard 1000) einführt, dieser Patch wird enthalten sein in PHP >=5.3.9 und >=5.4.0 RC4

Ein sehr hilfreicher Artikel bei cryptanalysis.eu erklärt noch einige Details. Natürlich empfiehlt es sich auch das aufgezeichnete Video des Talks zu schauen. Aktuell ist es ein PreRelease, das finale Video wird wahrscheinlich erst morgen oder übermorgen erscheinen nehme ich an.

Aktuell werden wohl noch keine großflächigen Angriffe beobachtet, aber wer auf der sicheren Seite sein will installiert sich Suhosin falls nicht eh schon geschehen. Aber Achtung, einige Restriktionen sind zu streng und könnten die Benutzung der Applikation beeinflussen die auf hohe Werte einiger Einstellungen angewiesen ist, also bitte vorher testen. Oder noch etwas gedulden und bald auf PHP 5.3.9 bzw. PHP 5.4.0 updaten.

EDIT: php.net ist langsam bzw. zeitweise nicht erreichbar…

EDIT: Der torrent zum offiziellen Release des Videos.

EDIT: Demo-Webseite incl. Quelltext

Written by Michael Kliewe

Dezember 29th, 2011 at 12:32 am

Posted in PHP

Tagged with , , ,

9 Responses to 'HashDoS Angriff legt (unter anderem) PHP lahm'

Subscribe to comments with RSS or TrackBack to 'HashDoS Angriff legt (unter anderem) PHP lahm'.

  1. Ne kurze Erklärung wie das in PHP funktioniert gibts auch hier nochmal: http://nikic.github.com/2011/12/28/Supercolliding-a-PHP-array.html

    Edorian

    29 Dez 11 at 00:58

  2. Ein Grund mehr PHP nie ohne Suhosin zu betrieben, und damit auf dem Betriebssystem wofür beide gemacht worden sind. 😉

    Es ist aber schon erschreckend, wie lasch die PHP-Entwickler (immer noch) mit solchen Meldungen umgehen.

    Sascha Ahlers

    29 Dez 11 at 01:01

  3. PHP kann man auch ohne Suhosin betreiben??

    Oliver

    29 Dez 11 at 01:34

  4. Besten Dank für die Zusammenfassung! 🙂

    Phil

    29 Dez 11 at 09:56

  5. Mit DoS-Attacken habe ich mich selten richtig beschäftigt. Was genau meinst du mit „Kollisionen der Array Keys“? Jeder Key existiert doch ohnehin nur einmal, so dass ein weiterer gleichnamiger überschrieben würde.

    Reicht es nicht, vor dem Absenden eines Formulares einen Session-Eintrag zu setzen und diesen bei der Auswertung von $_POST zu prüfen? DoS Attacken können die Session ja nicht „faken“ – oder verstehe ich was falsch?

    Daniel S

    29 Dez 11 at 11:48

  6. @Daniel S: Das Problem ist dass das $_POST-Array intern in C als Hash-Tabelle abgebildet wird. Dazu wird eine Hash-Funktion auf die Keys angewendet. Wenn dann diese gehashten Keys kollidieren wird eine Liste in der Hash-Tabelle erstellt. Sieht dann ungefähr so aus:

    Das Problem ist dass nun bei einem weiteren Eintrag und einer Kollision der neue Key mit jedem vorhandenen Eintrag der Liste verglichen wird. Sind also bereits 1000 Einträge in der Liste und wird ein weiterer hinzugefügt sind 1000 String-Vergleiche nötig. Und das bedeutet eben bei 100.000 Einträgen die alle kollidieren 10.000.000.000 String-Vergleiche.
    Bei weiteren Fragen unbedingt den cryptanalysis.eu Artikel lesen oder direkt das Video schauen.

    Michael Kliewe

    29 Dez 11 at 14:24

  7. Okay, danke dafür. Ist es denn so realistisch das nach einem Hash in C eine Kollision auftritt?

    Daniel S

    29 Dez 11 at 14:38

  8. @Daniel S: Da der Hash-Algorithmus bekannt ist kann man eine solche Liste mit Kollisionen errechnen. Hier sind einige Listen mit unterschiedlich vielen Einträgen:
    https://github.com/koto/blog-kotowicz-net-examples/tree/master/hashcollision

    Und hier eine einfache Demo:
    http://koto.github.com/blog-kotowicz-net-examples/hashcollision/kill.html

    Michael Kliewe

    29 Dez 11 at 15:03

  9. Beeindruckend! Müsste ja rein theoretisch auch bei GET gehen, wenn die Spezifikation nicht eine Maximale Stringlenge dafür vorsähe.

    Daniel S

    30 Dez 11 at 01:25

Leave a Reply

You can add images to your comment by clicking here.