[HowTo]Sicherheit in PHP-Codes schaffen

12/30/2010 15:05 FreeZoNe™#1
Dieses Tutorial beschreibt, wie man häufig gemachte Fehler in puncto Sicherheit vermeidet oder ganz umgeht:

1.) Request-Variablen vor Ausgabe "entschärfen"
2.) Keine Request-Variablen in include-Anweisungen verwenden
3.) Externe Variablen in SQL-Queries vorher escapen
4.) Zugriff auf Request-Variablen nur über $_GET und $_POST


1.) Request-Variablen vor Ausgabe "entschärfen"

Man sollte immer alle Variablen aus externen Quellen - darunter auch Request-Variablen von [Only registered and activated users can see links. Click Here To Register...], [Only registered and activated users can see links. Click Here To Register...] oder [Only registered and activated users can see links. Click Here To Register...] - vor irgendeiner Ausgabe von eventuellen Schadcode befreien.

Beispielsweise Konsequenz:

Es gibt einen Artikel mit einer Kommentarfunktion. Jemand schleust jetzt aber als Kommentartext keinen normalen Text ein, sondern JavaScript. Wenn diese nicht escapt werden, also unschädlich gemacht werden, dann wird bei jedem Besuch von dieser Seite JavaScript ausgeführt, der dann z.B. Viren einschleusen kann.

Entgegenwirkung:

Je nach Art der Behandlung der Variable kann man anders vorgehen.

Wenn z.B. eine Zahl übertragen werden sollte kann man mit der Funktion [Only registered and activated users can see links. Click Here To Register...] die Variable zu einer Zahl konvertieren.

Oder wenn man die Verwendung von HTML unterdrücken will, sollte man die Funktion [Only registered and activated users can see links. Click Here To Register...] verwenden, wobei man als zweiten Parameter noch das Flag ENT_QUOTES angeben sollte, da sonst nur die doppelten Anführungsstriche umgewandelt werden (und nicht die einfachen).

Außerdem ist noch die Funktion [Only registered and activated users can see links. Click Here To Register...] (und deren "verwandte" Funktionen) zu erwähnen, die seit PHP Version 5.2 existiert.

PHP Code:
$zahl $_GET['zahl']; 
$zahl intval($zahl); // Jetzt wirklich eine Zahl! 

$text $_POST['text']; 
$text htmlspecialchars($textENT_QUOTES); // Jetzt Text ohne evtl. HTML

$text2 filter_input(INPUT_GET"text2"FILTER_SANITIZE_SPECIAL_CHARS); 
Wichtig: Auch die Variablen, die man eigens per Weiterleitung geschaffen hat, sollten überprüft werden. Denn es besteht keine Garantie, dass diese jemand verändert!

2.) Keine Request-Variablen in [Only registered and activated users can see links. Click Here To Register...]-Anweisungen verwenden

Beispielsweise Konsequenz:

Es gibt eine GET-Variablen namens "tpl", die einen Dateinamen enthält, und im PHP-Skript wird diese mittels [Only registered and activated users can see links. Click Here To Register...] eingebunden.
Jetzt verändert jemand diese Variable so, dass im PHP-Skript eine (PHP-)Datei von einem fremden Server eingebunden und ausgeführt wird.
Diese kann jetzt z.B. alle Datenbanktabellen löschen, falls eine Datenbankverbindung besteht.

Entgegenwirkung:

Ein Whitelist-Array einführen, in dem alle erlaubten Dateinamen beinhaltet sind, und diese mit der GET-Variable vergleichen:

PHP Code:
$allowed_sites = array("main.html""other.html", ...); 

// ... 
$tpl $_GET['tpl']; 
if (  !
in_array$tpl$allowed_sites )  ) // wenn Seite nicht in Whitelist vorhanden,
  
$tpl $allowed_sites[0]; // Standard nehmen 

include("templates/".$tpl); 
3.) Externe Variablen in SQL-Queries vorher escapen

Bevor man Variablen aus externen Quellen wie aus $_POST in Queries verwendet, sollte man sie vorher escapen!

Beispielsweise Konsequenz (vgl. PHP-Manual):

Es gibt einen Login und jemand meldet sich an:

Benutzername : Mister X
Passwort : ' OR ''='

Wenn der Aufbau des MySQL-Query im PHP-Skript so ausschauen würde:

PHP Code:
$query "SELECT * FROM users WHERE user='".$_POST['username']."' AND password='".$_POST['password']."'"
Dann würde folgendes Query entstehen und es zulassen, dass sich Mister X anmelden kann:

Code:
SELECT * FROM users WHERE user='aidan' AND password='' OR ''=''
Entgegenwirkung:

Bei den meisten Datenbanksystem gibt es eine Funktion dafür, z.B. bei [Only registered and activated users can see links. Click Here To Register...]

PHP Code:
$data $_GET['data']; 
$data mysql_real_escape_string($data); 

$query "...$data..."

4.) Zugriff auf Request-Variablen nur über $_GET und $_POST

Man sollte auf Request-Variablen nur über die superglobalen Arrays $_GET und $_POST zugreifen!

In älteren PHP-Versionen, wurde automatisch eine Variable mit dem Request-Namen angelegt, sofern register_globals aktiviert war.
Somit konnte man von außen den Inhalt von Variablen in gewissem Maße verändern.

Mittels dem Array $_REQUEST, das sowohl GET- als auch POST-Daten enthält, sollte man im Normalfall auch nicht auf irgendwelche Daten zugreifen, da man unter anderem sonst nicht sicherstellen kann auf welchem Wege die Daten übertragen werden. Einen Ausnahmefall stellt z.B. die Bereitstellung einer API dar.

Entgegenwirkung:

PHP Code:
$var $_GET['var']; 
$var2 $_POST['var2']; 
[Only registered and activated users can see links. Click Here To Register...] gibt es auch nützliche Tips und Ratschläge rund um PHP.

Falls Ihr Anregungen oder Kritiken habt, schreibt sie einfach als Kommentar!
12/30/2010 15:50 ATI=Readon#2
Gutes TuT.
12/30/2010 18:17 Syc0n#3
Einige richtige Ansätze sind schon genannt, aber man sollte, um eine wirklich sichere Webseite zu schreiben, auf jedenfall noch weiteres beachten.

Bei der Verwendung von mysql_real_escape sollte man beachten:
Quote:
Ist magic_quotes_gpc aktiviert, wenden Sie zuerst stripslashes() auf die Daten an. Das Bearbeiten bereits in irgend einer Form maskierter Daten durch mysql_real_escape_string führt ansonsten dazu, dass bereits Maskiertes doppelt maskiert wird.
Dann sollte man anstatt Variablen für sensible Daten, wie beispielsweise Datenbank, Name, Passwort etc., besser Konstanten benutzen.

Und man sollte mit pregmatch vorgegebene Inputs am besten schon von Anfang an festlegen.

edit: Wer will kann sich ja mal dieses pdf durchlesen, is ganz interessant: [Only registered and activated users can see links. Click Here To Register...]
01/10/2011 18:15 anarchyst#4
Gutes Tutorial =) wurden einige sachen genannt die ich bereits kenne und neue sachen!

@Sycon: auch ein guter nachtrag von dir!