Top 5 - Sicherheitslücken in Webseiten

Top 5 - Sicherheitslücken in Webseiten
Von Lars Ebert am 22.07.10, 21:40
Kategorien: Programmieren and Tipps

Es gibt Sicherheitslücken, mit denen hält man Hackern die Tür geradezu sperrangelweit auf. Ich möchte hier die fünf Sicherheitslücken aufgreifen, die am häufigsten vorhanden sind.

Platz 5 - Fehlende Authentifizierung

Diese Sicherheitslücke ist erschreckend oft vorhanden. Ich werde sie hier am Beispiel eines einfachen Gästebuchs erläutern. Zwei Dateien sind dabei wichtig: Die Datei "show.php" und die Datei "delete.php".

In der Datei "show.php" wird zunächst irgendwie überprüft, ob der Besucher ein Admin ist beziehungsweise die Rechte zum Löschen eines Beitrages hat. Wenn ja, wird ein Link zu "delete.php?id=1" mit der id des entsprechenden Beitrages augegeben.

In der Datei "delete.php" wird der Beitrag mit der übergebenen ID gelöscht, ohne zu prüfen, ob der Nutzer die nötigen Rechte hat. Wozu auch? Der Link wird ja nur angezeigt, wenn die Rechte vorhanden sind. Und genau hier liegt der Fehler.

Man stelle sich vor, ein Hacker besucht das Gästebuch und gibt einfach mal "delete.php" in die Adressleiste ein. Dann rät er einfach mal ins Blaue und hängt an die URL noch "?id=1" an. Und schon kann er jeden beliebigen Beitrag löschen.

Mein Tipp:

Man sollte sich niemals darauf verlassen, dass nur der Admin einen Link aufruft. Prinzipiell kann jeder alles in die Adressleiste eingeben! Besser ist es, auch auf der Seite "delete.php" noch einmal die Rechte zu prüfen. Dann kann wirklich nur Beiträge löschen, wer die Rechte hat.

Platz 4 - Passwörter im Klartext im Script

Eine einfache Authentifizierung:


if($name = "Admin" && $passwort = "geheim")
{
 echo "GEHEIM...";
}

Wenn man vorher die Benutereingaben in die Variablen $name und $passwort schreibt, klappt das auch wunderbar. Nun kann es aber vorkommen, dass, zum Beispiel bei einer Serverneueinrichtung oder einem PHP-Update, PHP kurzzeitig falsch konfiguriert ist oder gar nicht funktioniert.

Wenn in diesem Moment jemand die Authentifizierungsseite aufruft, sieht er das PHP-Script und damit auch Benutzername und Passwort im Klartext und kann sich, sobald PHP wieder läuft, als Admin anmelden. Unerfreulich, oder?

Mein Tipp:

Passwörter sollten niemals im Klartext im PHP-Script stehen. Eine Möglichkeit ist es, das Passwort verschlüsselt zu speichern, zum Beispiel per md5. Der angepasste PHP-Code sähe dann so aus:


if($name = "Admin" && md5($passwort) = "e8636ea013e682faf61f56ce1cb1ab5c")
{
    echo "GEHEIM...";
}

Schon steht das Passwort nicht mehr im Klartext im Script.

Noch besser ist es, wenn man Name und Passwort in einer Datei in einem per .htaccess geschützten Unterordner speichert und diese Datei included:


<?php
 $user_pass = "e8636ea013e682faf61f56ce1cb1ab5c";
 $user_name = "Admin";
?>

Nun sieht der Code folgendermaßen aus:


require_once("secure/pass.php");
if($name = $user_name && md5($passwort) = $user_pass)
{
 echo "GEHEIM...";
}

Platz 3 - Verwendung ungeprüfter Benutzereingaben

In einem Formular soll einem Bild ein Name gegeben werden. Dieser wird dann, zusammen mit anderen Informationen, in einer Datenbank gespeichert. Das Feld, in das der Name gespeichert wird, hat die Eigenschaft NOT NULL und muss somit gefüllt werden. Wenn nun ein Benutzer keinen Name eingibt, führt dies zu einem mySQL-Fehler.

Mein Tipp:

Benutzereingaben darf niemals blind vertraut werden. Sie müssen unter allen Umständen überprüft werden. Dazu gehört zum vor allem die Verhinderung von leeren Feldern. Mit if($feld == "") oder besser if(trim($feld) == "") kann schnell und einfach geprüft werden, ob der Nutzer eine Eingabe getätigt hat.

Es gilt: Alles, was einen Fehler verursachen könnte oder nicht wünschenswert ist muss von Anfang an ausgeschlossen werden.

Platz 2 - Ungefilterte Benutzereingaben

Per Formular wird ein Text eingegeben, der dann ausgegeben wird. Das Script dazu sieht folgendermaßen aus:


if(isset($_POST['submit']))
{
 echo "Ihre Eingabe: " . $_POST['text'];
}
else
{
 echo '<form action="foo.php" method="POST">
 <input type="text" name="text">
 <input type="submit" name="submit" value="Senden">
 </form>';
}

Über diesen Weg kann nun ein Nutzer HTML und JavaScript auf der Seite ausgeben lassen.

Noch schlimmer ist es, wenn solche Eingaben ungefiltert gespeichert und zum Beispiel in einem Gästebuch ausgegeben werden. So gelänge es einem Angreifer, den Benutzern dieser Seite ein JavaScript unterzuschieben.

Mein Tipp:

JavaScript und HTML muss in Benutzereingaben grundsätzlich entwertet werden. Dies kann zum Beispiel durch die PHP-Funktion htmlspecialchars() geschehen. Diese Funktion ersetzt die Zeichen <, >, &, ' und " durch Entities, sodass das HTML und JavaScript als normaler Text ausgegeben werden.

Platz 1 - $_SERVER['PHP_SELF']

Auf irgendeiner Seite wird ein Codeschnipsel angeboten, der ein Formular beinhaltet. Damit der Pfad im action-Attribut nicht angepasst werden muss, wird er per $_SERVER['PHP_SELF'] ausgegeben. Da dies in so vielen Codeschnipseln, die im Internet angeboten werden, benutzt wird, ist diese Methode extrem weit verbreitet.

Das Problem ist allerdings, dass bei einem Aufruf der Seite http://www.example.com/index.php/foo/bar genau das auch in der Variable $_SERVER['PHP_SELF'] steht, das tatsächlich ausgeführte Script ist allerdings http://www.example.com/index.php

Wenn in dieser Datei nun ein solches Script steht:


<form action="<?php echo $_SERVER['PHP_SELF']; ?>">
</form>

Und folgende URL aufgerufen wird: http://www.example.com/index.php/"><script type="text/javascript">alert("Hallo Welt")</script><form action="bah.php

Wird auf der Seite dieser Code ausgegeben:


<form action="http://www.example.com/index.php/"><script type="text/javascript">alert("Hallo Welt")</script><form action="bah.php"></form>

Das in der URL übergebene JavaScript wird ausgeführt und dem Angreifer ist es gelungen, fremden Code auf der Seite auszugeben.

Mein Tipp:

Statt $_SERVER['PHP_SELF'] sollte $_SERVER['SCRIPT_NAME'] verwendet werden. In dieser Variable wird wirklich nur die Adresse des aktuellen Scripts gespeichert. Auf diese Weise kann, zumindest auf diesem Weg, kein Code eingeschleust werden.

Ich hoffe, dass, wenn die oben genannten Sicherheitshinweise berücksichtigt werden, das Internet ein kleines Stück sicherer wird.