Übernahme von REQUEST-Variablen
Alle REQUEST-Variablen ($_POST, $_GET, $_REQUEST, $_COOKIE usw.) werden mit folgendem Code übernommen:
|
PHP Source code
|
1
|
if (isset($_REQUEST['param'])) $param = $_REQUEST['param'];
|
Dabei ist zu beachten, das Integer werte mit intval übernommen werden und Strings mit StringUtil::trim.
|
PHP Source code
|
1
2
|
if (isset($_POST['param1'])) $param1 = StringUtil::trim($_POST['param1']);
if (isset($_GET['param2'])) $param2 = intval($_GET['param2']);
|
SQL
Ein SQL-Befehl sollte sich nicht auf eine Zeile beschränken, sondern Logisch getrennt werden. Hierfür bieten sich z.b Schlüsselwörter an, Kommas bei Insert befehlen oder Update befehlen.
Zudem sollte, wie bereits oben beschrieben werden, Variabeln nicht direkt eingebettet werden, sondern wie beschrieben eingebunden werden.
|
PHP Source code
|
1
|
$varString = "Dies ist ein '".$newString."'"; //Richtig
|
Ich gebe euch am Besten ein Beispiel für eine SELECT und INSERT Befehl.
|
PHP Source code
|
1
2
3
4
5
6
7
8
9
10
11
12
|
//SELECT
$sql = "SELECT *
FROM tabelle
WHERE id = ".$id."
AND user = ".$userID;
//insert
$sql = "INSERT INTO tabelle
(name1, name2, name3, name4, name5,
name6, name7, name8, name9, name10)
VALUES ('".$wert1."', '".$wert2."', '".$wert3."', 0, 0,
0, 1, 1, 1, 1)";
|
Wie ihr gesehen habt, ist so eine logische Gliedrung des SQL-Statements möglich. Dabei ist zu beachten, das SELECT, FROM, WHERE, ORDER BY übergeordnete Gruppen spielen und das man untergeordnete Gruppen wie LEFT JOIN, RIGHT JOIN, AND, OR, ON noch einmal um ein Tab einrückt, so dass man sofort erkennt wozu sie gehören. Ich habe extra dafür ebenso ein komplexeres Statement mir einfallen lassen.
|
PHP Source code
|
1
2
3
4
5
6
7
|
$sql = "SELECT v.*, t.*
FROM tabelle1 v
LEFT JOIN tabelle2 t
ON (t.vid = v.id)
WHERE v.id = ".intval($vID)."
AND v.name = '".escapeString($vName)."'
ORDER BY v.id ASC, t.id DESC";
|
Dies ist ein komplexeres Query, welches euch zeigen soll, wie ich es genau gemeint habe. Ihr konnt damit eine logische Gliederung in eure SQL-Befehle bringen. Eine Tabgröße von 8 sollte gewählt werden.
Sicherheit
Jedem von uns, auch Marcel, passiert es mal, dass eine Sicherheitslücke entsteht, aber sollte nicht passieren, und um das zu verhindern gibt es im WCF sehr nützliche Funktionen wie die escapeString (alias für WCF::getDB()->escapeString, Database::escapeString) und StringUtil::encodeHTML. Beide Funktionen dienen zur Sicherung gegen die beiden häufigsten Angriffspunkte in einem Skript. Der SQL-Injection und der XSS Attacke.
SQL-Injection
Ich hoffe, ich muss nicht beschreiben was eine
SQL-Injection ist, aber für den Notfall, habe ich die
Wikipediaseite verlinkt. Diese Attacke könnt ihr relativ einfach abwehren, nämlich in dem ihr für alle SQL-Statement, die Werte enthalten ein intval, oder eben escapeString anwendet. Wenn ihr euch an die Regeln für die Übergabe von REQUESt-Variablen gehalten habt, könnt ihr zumindest Sichersein, das Integerwerte, wirklich vom Typeinteger sind, und so nicht mehr behandelt werden müssen. Seid ihr dem euch nicht Sicher, wendet am besten noch mal ein intval auf diese an. Strings, Texte solltet ihr auf jedenfall, bevor ihr sie in SQL-Befehlen verwendet, per escapeString behandelt werden. Tut dies am Besten dort, wo das SQL-Statement ausgeführt wird. Damit verhindert ihr bereits die SQL-Injection.
|
PHP Source code
|
1
2
3
4
|
$sql = "SELECT *
FROM tabelle
WHERE name = '".escapeString($name)."'
AND zahl = ".intval($zahl);
|
Wenn ihr euch daran haltet, ist die Gefahr einer SQL-Injection geringer. Solltet ihr euch nicht 100% Sichersein, das die Werte eine Zahl sind, wendet lieber erneut ein intval an. Sicher ist Sicher!
XSS
XSS-Attackensind genau wie die SQL-Injections relativ einfach abzuwehren. Man muss nur entsprechende Funktionen benutzen. Diese ist StringUtil::encodeHTML, oder eben in einem Template auf das @ vor einer Variabel zu verzichten. Wendet die Funktion StringUtil::encodeHTML auf alles an, was in die Templates kommt, und was einen Text enthält. Bei Zahlenwerten könnt ihr das gerne weglassen und ein @ verwenden in einem Template.
|
PHP Source code
|
1
2
3
4
5
|
//In PHP
$var = "<b>Böses HTML</b>";
echo $var; //Dies war ein schlechter Aufruf, denn das HTML wird nicht umgewandelt!
$var = StringUtil::encodeHTML($var);
echo $var;//Dies war ein guter Aufruf
|
Da aber eher mit Templates gearbeitet wird, ist wohl folgendes eher anzutreffen.
|
PHP Source code
|
1
|
WCF::getTPL()->assign('var', '<b>Böses HTML</b>');
|
Somit ergibt sich für das Template 2 Codeformen:
|
Template source code
|
1
2
|
{@$var} <br />Dies war ein Böser aufruf, denn das HTML wurde vollständig an den Browser übergeben.
{$var} <br />Dies war ein gute Aufruf, der HTMLCode wurde umgewandelt und so verhindert.
|
Hier gilt also wie bei den SQL-Befehlen, solltet ihr euch nicht 100% sichersein, das HTML-Code aus dem Text gefiltert wurde, oder entsprechend in seine Entities (& = &, < = <, >= >) umgewandelt wurde, lasst das @ Zeichen weg!