1. stimmt soweit: http://php.net/manual/de/mysq…-statements.php
(siehe "Basic workflow")
Hatte selbst gedacht, dass die Platzhalter ersetzt werden, bevor die Query an den Sql-Server geht.
Muss ich selbst mal nachsehen, wie genau der Ablauf ist.
Fakt ist aber, dass bei richtiger Anwendung keine SQL-Injectons mehr möglich sind.
Bsp falsch und richtig:
<?php
// queries machen keinen sinn, sollen nur den bsp-zweck erfüllen
// FALSCH:
$sql = "select * from tbl where id = " . $id . " and id IN(" . $id1 . ", " . $id2 . ") limit " . $intStart . ", " . $intLimit . ";";
// RICHTIG:
$sql = "select * from tbl where id = :id and id IN(:id1, :id2) limit :intStart, :intLimit;"
// bind param :id, :id1 und :id2 ohne angabe des types (default string -- werte werden in '' gesetzt)
// bind param :intStart und :intLimit als integer
Alles anzeigen
(siehe types: http://php.net/manual/de/mysqli-stmt.bind-param.php)
(btw: bei PDO siehe: http://php.net/manual/de/pdo.constants.php)
Achtung: Platzhalter können (und sollen) nicht für Tabellennamen verwendet werden.
<?php
// FALSCH: (bzw nicht möglich)
$sql = "select * from :tblname;";
// RICHIG:
// tbl whitelist: using key as tbl name to be able to check if isset() (much faster than in_array())
// 0 instead of false to get a better overview for what is enabled
$tblWhiteList = array(
'tbl_1' => true,
'tbl_2' => 0,
'tbl_3' => true,
'tbl_4' => 0,
);
$tblname = $_GET['tbl']; // or where ever the tbl name comes from
$tblname = (isset($tblWhileList[$tblname]) and $tblWhileList[$tblname] === true) ? $tblWhileList[$tblname] : false;
if($tblname === false){ //
// error ...
}
else{
$sql = "select * from " . $tblname . ";"; // noch nicht ganz so ok
}
// -------------------------------
// um es übersichtlicher zu gestalten und in der query auch zu sehen, dass NICHT einfach die var angehangen wird
// sollte man eine funktion/methode nutzen:
if(isValidTableName($tblname) !== true){ //
// error ...
}
else{
$sql = "select * from " . getValidTableName($tblname) . ";";
}
Alles anzeigen
2. Weiß nicht genau, was Dein Script macht (include $_GET ... ?),
aber im Grunde würde ich hier auch auf Whitelists setzen.
if(isset($sites[$siteName])){} ...
// sicherlich das ganze in aussagekräftige funktionen setzten wie zB
if(isValidSiteName($siteName)){
$siteName = getValidSiteName($siteName);
...
} ...
EDIT: siehe auch wolf: Include
3. hast Du schon richtig gamacht. Wenn Du Dich daran hältst, dass in Klassen-Dateien nur die Klassen enthalten sind, dann kann nix passieren.
Es sei denn Du kommst einmal an den Punkt, an dem Du eine ("static")Klasse initialisierst:
<?php
// file MyClass.php
class MyClass{
public function init(){
// ...
}
}
// wenn dieses file geladen wird, auto-init sich diese klasse
MyClass::init();
// ... kann man machen, sieht man auch öfter
Im Grunde sollten include Ordner nicht von Aussen erreichbar sein (Server config).
Wenn Du auf nummer sicher gehen willst, dann kannst Du eine Konstante definieren:
- index.php ganz am Anfang: define('MAIN', 1);
- other_scripts.php ganz am Anfang: !defined('MAIN') AND exit('meldung ...');
(könntest auch nen Redirect auf index.php machen, wenn MAIN nicht definiert ist.)
Ohne die definierte Konstante geht also nix.
4. Ich hatte mal https://addons.mozilla.org/en-us/firefox/addon/xss-me/ genutzt. Ist aber lange her. Falls es jemand nutzt, dann bitte vorher prüfen/lesen, ob die Extension eine "gute" ist.
Ansonsten denke ich, dass andere Deine Fehler besser finden, als Du selbst. (BETA)
Also einfach mal paar vertauenswürdige auf Deine Seite los lassen. So nach dem Motto: "versucht es mal kaputt zu machen" 
Zum String: wenn Du Daten ausgibst, dann immer masiert.
PHP: $secure = htmlspecialchars($inSecureData);
JS: var secure = document.createTextNode(inSecureData);
5. (hab mir den Namen mal wieder nicht gemerkt, aber ich glaube es hieß) Reverse-Injections:
Stell Dir vor Du:
- bekommst eine GET var und
- schreibst sie per :platzhalter in die db
- beim Anzeigen der/einer Seite lädst Du diesen Wert wieder, um ihn anzuzeigen
Dann kann folgendes passieren:
- bei der Ausgabe vergisst Du den Wert zu maskieren:
<?php
// FALSCH:
Das hier ist der Wert, den Sie zuvor eingegeben hatten: <?php echo $dbResult['eingabe'] ?>
// das sollte niemals passieren!
// Alle geladenen Daten (aus files, db, GET, POST, SESSION, w/e) gehören maskiert ausgegeben
// wie zB
// RICHTIG
Das hier ist der Wert, den Sie zuvor eingegeben hatten: <?php echo htmlspecialchars($dbResult['eingabe']) ?>
- oder Du nutzt beim Laden von Daten den Wert aus einer Tabelle in der Query:
// queries machen keinen sinn, sollen nur den bsp-zweck erfüllen
$name = // hier eine query, um irgend einen namen aus der db zu laden
// FALSCH:
$sql = "select * from tblname where name = " . $name;
// RICHTIG:
$sql = "select * from tblname where name = :name";
// bind param :name => $name
Alles anzeigen