PHP Sicherheit: Register Globals

1 | 2 Kommentare | 20878 Aufrufe
Sie können diese Wikiseite nach der Anmeldung auf Webmasterpro bearbeiten. Helfen Sie mit und verbessern Sie "PHP Sicherheit: Register Globals" mit Ihrem Wissen!

Anzeige Hier werben

Unter dem Namen "Register Globals" wurde eine Funktion in PHP eingeführt, die die Benutzung von EGPCS (Environment/Umgebung, GET, POST, Cookie, Server) Variablen steuert. Diese Funktion wurde aus sicherheitstechnischen Gesichtspunkten ein wenig unglücklich gestaltet, trotz dessen fand sie schnell eine recht weite Verbreitung und wird zum Teil noch heute von Unwissenden eingesetzt.

Funktionsweise von Register Globals

Ist register_globals = on in der php.ini gesetzt, läuft diese Funktion. Sie bewirkt, dass die o.g. EGPCS-Variablen registriert werden, was bedeutet, dass diese über den Variablennamen aufgerufen werden können. Im folgenden werden die Superglobal-Bezeichnungen verwandt um die Verbindung zu Register Globals zu demonstrieren.

Formulierung der Server-Variablen, die die IP-Adresse des Besuchers enthält, als Superglobal

 
PHP
1
$_SERVER['REMOTE_ADDR']

Mögliche Formulierung bei aktiviertem Register Globals

 
PHP
1
$REMOTE_ADDR

Dieses einfache Beispiel zeigt am bildlich die Funktionsweise von Register Globals. Die Superglobals, wie sie seit PHP 4.1.0 verfügbar sind, können mit ihrem Array-Schlüssel als Variablenname, hier $REMOTE_ADDR, aufgerufen werden.

Register Globals als Sicherheitsproblem

Zunächst erscheint die Funktion als praktisch, da sie ein paar Zeichen und somit Tipparbeit spart, leider eröffnen diese wenigen Zeichen bei aktiviertem Register Globals zum Teil große Sicherheitslücken.

Eben dadurch, dass durch Register Globals die verschiedenen Array-Schlüssel der EGPCS-Variablen als Variablenname zur Verfügung stehen, kann es zu Kollisionen und Fehlinterpretationen durch PHP kommen.

Beispielsituation:

Ein bestimmter Teil einer Website enthält sensible Daten und soll daher nur für registrierte Benutzer, die angemeldet sind, angezeigt werden. Besucher, die nicht angemeldet sind, sollen diese Teil nicht sehen können. Um zu prüfen, ob der Benutzer angemeldet ist, wird eine Cookie gesetzt, welches ihn identifiziert. Der Autor des Skriptes ist unwissend und verwendet in diesem Register Globals, was wie folgt aussehen könnte:

Beispiel unter Verwendung von Register Globals

Dieser Quelltext ist in diesem Zusammenhang als unsicher einzustufen und sollte nie verwendet werden!

 
PHP
1
2
3
4
5
6
if ($identifikation == "vertrauenswuerdig") {
    $is_logged_in = true;
}
if ($is_logged_in) {
    echo("Sensible Daten.");
}

Wie in dem Beispiel erkennbar ist, lässt sich in diesem Entwurf die Herkunft der Variablen $identifikation nicht klären. Der Autor beabsichtigt, dass diese aus dem von ihm gesetzten Cookie stammt. Aufgrund der aktivierten Funktion Register Globals ist es jedoch auch möglich, dass dieser Bereich angezeigt wird, wenn $identifikation zum Beispiel durch die Get-Variante definiert ist. Im Klartext heißt das, dass dieser vermeidlich geschützte Bereich auch gezeigt wird, wenn an die Url die Parameter identifikation=vertrauenswuerdig angehängt werden würden. Daten aus einem Post-Formular wären ebenso als Manipulation denkbar.

Gleichzeitig wird $is_logged_in benutzt um Inhalte, die nur für registrierte und eingeloggte Benutzer sichtbar sein sollen, anzuzeigen. Da diese Variable nicht initialisiert wird kann ein Angreifer sie einfach von außen setzen. Ein einfaches is_logged_in=1 als GET-Parameter würde im Beispiel ausreichen um Zugriff auf geschützte Bereiche zu erhalten. Dieses Problem hat seinen Ursprung natürlich eher an unsauberem Programmierstil. Da PHP bei nicht initialisierten Variablen normalerweise keine Warnung ausgibt (mit error_reporting() kann das geändert werden) ist das allerdings oft zu lesen.

Dies ist der Kern der Sicherheitsproblematik von Register Globals. Um dies zu vermeiden, sollten die Super-Global Arrays (Beschreibung auf PHP.net) benutzt werden, um dies zu vermeiden. Desweiteren funktioniert diese Lösung nicht auf einem Server, bei dem Register Globals deaktiviert ist. Dies kann zu einer aufwendigen Fehlersuche führen, wenn beim Erstellen des Skripts nicht auf Fehlerverarbeitung geachtet wurde.

Das folgende Beispiel zeigt, wie eine solche Manipulation vermieden werden kann.

Dasselbe Beispiel ohne Register Globals

 
PHP
1
2
3
4
5
6
7
$is_logged_in = false;
if ($_COOKIE['identifikation'] == "vertrauenswuerdig") {
    $is_logged_in = true;
}
if ($is_logged_in) {
  echo("Sensible Daten.");
}

Wie hier deutlich wird, kann, wie gewünscht, der sensible Bereich nur betreten werden, wenn die entsprechende Cookie-Variable vorliegt. Das Benutzer von Get und Post um den geschützten Bereich aufzurufen, ist zwecklos. Dies ist natürlich nur ein kleines Beispiel, was die Funktionsweise und die Gefahren von Register Globals verdeutlichen soll.

Außerdem wurde $is_logged_in hier auf einen Standardwert initialisiert. Da es mit deaktiviertem Register Globals nicht möglich wäre die Variable von außen zu ändern ist das aus Sicherheitsaspekten nicht unbedingt nötig. Allerdings muss ein Script auch auf Servern funktionieren, die Register Globals aktiviert haben und der Quelltext ist so sauberer.

Registrierte Globals entfernen

Selbst bei aktiviertem Register Globals ist dies nicht zwingend notwendig, wenn mit den Superglobals gearbeitet wird. So lange Variablen vor der ersten Benutzung sauber initialisiert werden, ist dieser Teil überflüssig, kann jedoch bei unsauberer Programmierung wirksam sein.

Dies muss ausgeführt werden, bevor mit Variablen gearbeitet wird, da diese sonst ebenfalls gelöscht werden!

 
PHP
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
function unregister_globals() {
    // Überprüfung, ob Register Globals läuft
    if(ini_get("register_globals") == "1") {
        // Erstellen einer Liste der Superglobals
        $superglobals=array("_GET", "_POST", "_REQUEST", "_ENV", "_FILES", "_SESSION", "_COOKIES", "_SERVER");
        foreach($GLOBALS as $key => $value) {
            // Überprüfung, ob die Variablen/Arrays zu den Superglobals gehören, andernfalls löschen
            if(!in_array($key, $superglobals) && $key != "GLOBALS") {
                unset($GLOBALS[$key]);
            }
        }
        return true;
    }
    else {
        // Läuft Register Globals nicht, gibt es nichts zu tun.
        return true;
    }
}
unregister_globals();

Dieser Code entfernt alle Einträge, die von Register Globals erstellt wurden.

Vergangenheit und Ausblick in die Zukunft

Ein Blick zurück

Die oben geschilderte Verwendung der Superglobals ist seit der PHP-Version 4.1.0 möglich. Da alle anderen Schreibweisen veraltet sind, wird auf diese hier nicht weiter eingegangen. Seit PHP 4.2.0 ist Register Globals standardmäßig deaktiviert, inzwischen ist es auch nur noch auf wenigen Servern überhaupt noch aktiviert.

Register Globals in der Zukunft

Da Register Globals als Sicherheitsproblem immer wieder in die Kritik geraten ist, wurde beschlossen diese oft als "Altlast" bezeichnete Funktion in PHP 6 gänzlich zu entfernen.


Wikiseite bearbeiten

Diese Seite kann von jedem registrierten Benutzer bearbeitet werden. Bisher haben 3 Personen an der Seite "PHP Sicherheit: Register Globals" mitgewirkt.

Sie haben einen Fehler entdeckt oder möchten etwas ergänzen? Dann können Sie nach der Anmeldung "PHP Sicherheit: Register Globals" hier bearbeiten.

Mitarbeiter
  • Student der Biochemie und seit einigen Jahren im Hobby-Entwicklerbereich tätig. Stärken in XHTML/CSS und PHP, alles was mit Grafik zu tun hat, gehört nicht dazu.
  • David Danier arbeitet seit mehr als neun Jahren im Bereich Web Programmierung und ist unter anderem Geschäftsführer der Webagentur Team23 sowie Webmasterpro.de.
  • hat keine Beschreibung angegeben. Eine Beschreibung kann man unter dem Punkt "Profil bearbeiten" im Kontrollzentrum eintragen.

Kommentare: PHP Sicherheit: Register Globals

Neuen Kommentar schreiben
nutzlos
Beantworten

das ganze entsensibilisiert zwar das ganze etwas, aber es kann trotzdem eine manipulation nicht vermeiden, von daher in meinen augen recht unnütz das ganze... man muss viel filtern, bevor etwas übergeben werden kann :)

trotzdem stop es so manche angreifer, aufgrund dessen, das man sich nicht die mühe machen will wenn es auf good luck angreifer sind :) aber wer denkt, der kann sich damit schützen, der liegt falsch mit seiner Denkweise...

das ganze eben meiner aktueller meinung nach :)

aioon am 08.02.2008 um 22:16
Re: nutzlos
Beantworten

das ganze entsensibilisiert zwar das ganze etwas, aber es kann trotzdem eine manipulation nicht vermeiden, von daher in meinen augen recht unnütz das ganze...

Hab den Artikel um ein einfaches Beispiel erweitert, wo das Deaktivieren von Register Globals eine Manipulation bzw. ungewünschte Rechteausweitung verhindert. Natürlich ist das Grundproblem hier nicht Register Globals selbst, dennoch hilft das Deaktivieren.
Grundsätzlich sollte man sich als Autor von PHP-Scripts dennoch nicht darauf verlassen, dass man deswegen Variablen verwenden kann, ohne sie vorher zu initialisieren, weil ja Register Globals deaktiviert ist. Das kann sich ändern und sauber ist der Quelltext dann wirklich nicht.

David Danier am 09.02.2008 um 10:36