7 Möglichkeiten um deinen PHP Code zu hacken

Wer eine Website ins Netz stellt, sollte sich auch immer Gedanken um die Sicherheit machen. Man hört immer wieder von großen Datendiebstählen und anderen schlimmen Dingen. Wenn es einen selbst trifft, ist die Laune am Boden.

Doch, um einen sicheren PHP Code zu schreiben sollte man die Fallstricke kennen und vermeiden. Aus diesem Grund möchte ich euch heute mal eine kleine Sammlung bekannterer oder auch weniger bekannter Hacks vorstellen, die ihr am besten auf eurer Seite mal ausprobiert.
ACHTUNG: Wer solche Tricks ohne Erlaubnis des Eigentümers auf fremden Websites anwendet, riskiert rechtliche Folgen!

Ich werde erst einmal die klassischen Tricks vorstellen und später zu den vielleicht nicht ganz so Bekannten kommen.

1. SQL Injection

Mit das schlimmste, was euch passieren kann, ist wenn jemand Zugriff auf eure Datenbank bekommt. Dies kann zum Beispiel durch eine SQL Injection passieren. Dabei wird eine reguläre Abfrage durch manipulierte Eingaben so abgeändert, dass man beliebige SQL-Statements ausführen kann.

Beispiel:

<?PHP
    mysql_query("SELECT * "
               ."FROM users "
               ."WHERE nickname = '".$_GET['nickname']."'");
?>

Hier wird einfach mit MySQL nach einem Benutzernamen gesucht. Bei ganz normalen Nicknames wird das auch klappen. Nun kann man aber zum Beispiel folgendes aufrufen:

?nickname=’+or+1+=+1

Dann wird aus dem SQL-Statement folgendes:

SELECT *
FROM users
WHERE nickname = ''
or 1 = 1

Und schon hat der Angreifer Zugriff auf alle Benutzerdaten. Um dies zu vermeiden, muss man die Eingabe escapen, also die Sonderzeichen so umschreiben, dass sie richtig in die Datenbank geschrieben werden können. Dies geht in dem Beispiel über mysql_real_escape_string:

<?PHP
    mysql_query("SELECT * "
               ."FROM users "
               ."WHERE nickname = '".mysql_real_escape_string($_GET['nickname'])."'");
?>

Wenn man ein anderes Datenbanksystem benutzt, sollte man auch dessen escape-Funktion nehmen. Ich empfehle das Escapen immer direkt im Query zu machen. Egal, ob der Wert an anderer Stelle validiert wurde oder nicht. So ist man auf jeden Fall auf der sicheren Seite.

2. XSS – Cross Site Scripting

Es gibt viele Sachen, die auf eine Domain beschränkt sind. So kann man zum Beispiel keine Cookies von fremden Seiten auslesen. Denn das hätte fatale Folgen! Denn dadurch kann man sich zum Beispiel Session-IDs klauen und hat vollen Zugriff auf den jeweiligen Account.

Beim Cross-Site-Scripting geht es darum, Quellcode auf fremden Seiten zu platzieren und somit die Rechte der geschädigten Seite zu bekommen. Kleines Beispiel:

<?PHP
    echo "Hello".$_GET['nickname'];
?>

Hier kann man über den Get-Parameter nickname den Namen übergeben und wird gegrüßt. Nun ja, man kann aber auch Javascripts übergeben. Zum Beispiel: ?nickname=%3Cscript%3Ealert(‚XSS!‘)%3B%3C/script%3E .Wer nun die Seite besucht, wird mit einem Javascript-alert begrüßt. Online werden dort aber eher schlimmere Dinge als nur ein Alert stehen!

Der Ausweg sieht so aus:

<?PHP
    echo "Hello".htmlentities($_GET['nickname']);
?>

Nun bekommt man einfach ein script-Tag zusehen, es wird aber nicht ausgeführt. Auch das htmlentities sollte am besten direkt bei der HTML-Ausgabe stehen.

3. Verändern von Variablenwerten – register_globals sei Dank!

Wäre es nicht cool, einfach mal die Werte von Variablen zu ändern? Also das $admin auf true setzen, und schon hat man alle Rechte? Kein Problem, ist register_globals angeschaltet, kann man das ganz einfach machen:

<PHP
    if($user->is_admin()){
        $admin=true;
    }
    if($admin){
        echo"Ich bin hier Chef!";
    }
?>

Ist register_globals eingeschaltet, kann man jetzt einfach „?admin=true“ an die Url hängen und wird zum Admin. Gott sei Dank, ist register_globals mittlerweile fast überall deaktiviert und auch bei PHP als DEPRECATED markiert.

Dennoch sollte man Variablen vor der Verwendung initialisieren. Das geht zum Beispiel so:

<?PHP
    $admin=false;
    if($user->is_admin()){
        $admin=true;
    }
    if($admin){
        echo"Ich bin hier Chef!";
    }
?>

Jetzt ist egal, was vorher im $admin steht, er wird vorher auf false gesetzt. Außerdem sollte man (auch der übersichtshalber) auf globale Variablen verzichten und objektorientiert arbeiten. So gelten die Variablen so oder so nur in ihrer Funktion.

4. Session Hijacking

Grade in der letzten Zeit ist hiervon vermehrt die Rede. Ähnlich wie eben beim Cross-Site-Scripting, kann man hiermit Sessions klauen. Sessions braucht man zum Beispiel um Authentifizierung zu ermöglichen. Es wird ein Cookie gesetzt, in dem eine eindeutige ID ist. Diese wird bei jeder Anfrage übermittelt und an der können wir den Benutzer wieder erkennen.

Das Problem dabei: Kommt jemand fremdes an diese ID (z.B. über schlecht gesichertes WLAN), kann er sich einfach die SESSION des ausspionierten Users schnappen.

Doch wie verhindert man das? Schließlich ist es eher ein Problem des Anwenders, oder? Aber genau dieser wird sich bei dir melden, wenn plötzlich sein Account nicht mehr ihm gehört.

Am besten umgeht man das Problem, in dem man HTTPS benutzt. Hierbei handelt es sich um eine verschlüsselte Verbindung, bei der man die Session-ID nicht mehr auslesen kann. HTTPS ist nur leider mit weiteren Kosten verbunden.

Wem das zu teuer ist, der kann einfach überprüfen, ob sich die IP oder auch der Browser geändert haben. Somit ist man zumindest etwas sicherer.

5. relative Pfade

Der include-Befehl wird oft genutzt um Unterseiten zu laden. Hierbei sollte man immer Prüfen, ob der Pfad auch ok ist. Übergibt man zum Beispiel ../ als GET-Parameter, so kann man einfach in ein übergeordnetes Verzeichnis springen!

6. Zahlen in Exponentialdarstellung

Ein häufig gemachter Fehler ist es, Zahlen nicht richtig zu überprüfen. Folgendes Beispiel:

<?PHP
    if(is_numeric($_GET['id']))
    {
        $sql="SELECT * "
              ."FROM user "
              ."WHERE id = ".$_GET['id'];
    }
?>

Jetzt sind nur Zahlen erlaubt, oder? Klar. Aber auch 2e5 ist eine Zahl. Nur in andere Schreibweise. Da diese Schreibweise von MySQL nicht unterstützt wird, kann man hier mit einem SQL-Fehler rechnen. In Falle einer ID sollte man hier mit is_integer arbeiten. Wer Kommazahlen benötigt, sollte prüfen, dass auch kein e in der Zahl vorkommt.

7. GET-Parameter als Array

Eine schöne Funktion von PHP ist es, dass man GET-Parameter auch als Array übergeben kann. So wird aus ?ids[]=1&ids[]=2 folgendes: array(1,2). Jetzt schaut euch mal folgenden Code an und überlegt, was das Problem sein könnte:

<?PHP
    echostrlen($_GET['name']);
?>

Gibt man als GET-Parameter nun ?name[]=test an, bekommt man folgende Warning:

Warning: strlen() expects parameter 1 to be string, array given in test.php on line 2

Aus diesem Grund, sollte man mit is_string vorher prüfen, ob es wirklich ein String ist. Auch ein Weglassen des Parameters würde in diesem Fall eine Warnung verursachen.

Allgemeine Tipps für mehr PHP-Sicherheit

In den Beispielen seht ihr, dass es einiges gibt, auf das man achten sollte. Aus diesem Grund möchte ich nochmal ein paar Allgemeine Tipps nennen, wie man viele Probleme umgehen kann.

Error: No site found with the domain 'test.basti1012.bplaced.net' (Learn more)