Aradiv
22.12.2009, 11:38
Das VMS hat eine schöne Queryfunktion die wenn man sie richtig anwendet alle Variablen mit mysql_real_escape_string für SQL Injections unbrauchbar macht. Leider wird diese Funktion NIRGENDS im VMS wirklich verwendet.
Nehmen wir erstmal die db_query funktion auseinander
dies ist die gesamte funktion
function db_query($sql_tag){
global $count_query;
$count_query ++;
$fargs = func_get_args();
if (!empty($fargs)){
$vargs = array();
foreach($fargs as $key => $arg){
$vargs[$key] = mysql_real_escape_string($arg);
}
array_shift($vargs);
if(!empty($vargs))$sql_tag = vsprintf($sql_tag,$vargs);
}
if($ret = mysql_query($sql_tag)){
return $ret;
}else{
return 0;
}
}Zu erst betrachten wir mal die Variablen die zur verfügung stehen oder erzeugt werden.
function db_query($sql_tag){
global $count_query;
$count_query ++;
$fargs = func_get_args();
$sql_tag ist unser Query String die vorerst einzige Variable die an die Funktion db_query übergeben werden kann.
$count_query zählt die querys bei einem Aufruf der Seite (ist für uns unintressant)
$fargs ist ein array mit allen Variablen die an die Funktion db_query übergeben werden.
also dann weiter mit der Logik
Moment "alle Variablen"?
Ja richtig alle Variablen mit func_get_args wurde aus der funktion db_query mit 1 Variablen eine funktion mit beliebig vielen Variablen also können wir db_query auch so aufrufen
db_query($sql_tag, $var1, $var2, $var3, $var4, $var5, $var6, $var7 ...)Ok jetzt aber wirklich zur Logik
if (!empty($fargs)){
$vargs = array();
foreach($fargs as $key => $arg){
$vargs[$key] = mysql_real_escape_string($arg);
}
array_shift($vargs);
if(!empty($vargs))$sql_tag = vsprintf($sql_tag,$vargs);
} Zu erst wird überprüft ob $fargs leer ist. (kann eigentlich nicht sein den db_query leer aufzurufen also nur db_query() macht wenig Sinn
ok danach erzeugen wir ein leeres Array $vargs;
jetzt wird jede Variable aus $fargs einzeln genommen mit mysql_real_escape string behandelt und unter dem selben key (nummer von 1 bis x) in $vargs abgelegt.
array_shift nimmt das erste Element von $vargs gibt es zurück und löscht es aus dem Array $vargs
jetzt wird noch überprüft ob $vargs nach dem löschen des einen Elemnts leer ist und danach wird $sql_tag mit vsprintf erzeugt.
Was passiert bei vsprintf?
vsprintf gibt einen Formatierten strung zurück und nimmt als 2. Parameter ein Array mit den ersetzungen entgegen.
heißt aus
vsprintf("%d-%d", array(7, 3)) wird eine 7-3
aus vsprinf("Hallo %s", User) wird Hallo User
usw
Danach wird nurnoch das Query ausgeführt mit mysql_query.
So was bringt uns unser wissen jetzt?
Nehmen wir mal an wir haben folgende abfrage
db_query("SELECT * FROM vms_kontodaten WHERE uid=$uid");1. wenn man $uid maniplieren kann dann wären sql injections tür und tor geöffnet
2. was steht den in $uid wahrscheinlich eine Zahl aber sicher?
um das abzusichern könnte man jetzt $uid mit intval($uid) behandeln oder bei der zuweißung ein int casten aber ist das beim einsetzen in die db_query funktion immernoch eine Zahl oder hat sich das inzwichen verändert? Sicher weiß man das so nicht.
Also was tuen?
Nochmal mit intval, eregi und anderen prüfen?
Nein warum denn wir haben doch unsere db_query methode
Dort machen wir aus
db_query("SELECT * FROM vms_kontodaten WHERE uid=$uid");einfach
db_query("SELECT * FROM vms_kontodaten WHERE uid=%01d", $uid);So was passiert jetzt?
der platzhalter %01d wird mit der ZAHL %uid ersetzt und wenn $uid keine Zahl ist wird eine 0 eingesetzt und vorher mit mysql_real_escape_string behandelt
heißt ausdrücke wie "123456' OR 1=1" werden unbrauchbar gemacht.
So jetzt das erschreckende bzw Fragwürdige.
Warum gibt es diese Funktion im VMS wenn sie nie genutzt wird?
mfg
Aradiv
Nehmen wir erstmal die db_query funktion auseinander
dies ist die gesamte funktion
function db_query($sql_tag){
global $count_query;
$count_query ++;
$fargs = func_get_args();
if (!empty($fargs)){
$vargs = array();
foreach($fargs as $key => $arg){
$vargs[$key] = mysql_real_escape_string($arg);
}
array_shift($vargs);
if(!empty($vargs))$sql_tag = vsprintf($sql_tag,$vargs);
}
if($ret = mysql_query($sql_tag)){
return $ret;
}else{
return 0;
}
}Zu erst betrachten wir mal die Variablen die zur verfügung stehen oder erzeugt werden.
function db_query($sql_tag){
global $count_query;
$count_query ++;
$fargs = func_get_args();
$sql_tag ist unser Query String die vorerst einzige Variable die an die Funktion db_query übergeben werden kann.
$count_query zählt die querys bei einem Aufruf der Seite (ist für uns unintressant)
$fargs ist ein array mit allen Variablen die an die Funktion db_query übergeben werden.
also dann weiter mit der Logik
Moment "alle Variablen"?
Ja richtig alle Variablen mit func_get_args wurde aus der funktion db_query mit 1 Variablen eine funktion mit beliebig vielen Variablen also können wir db_query auch so aufrufen
db_query($sql_tag, $var1, $var2, $var3, $var4, $var5, $var6, $var7 ...)Ok jetzt aber wirklich zur Logik
if (!empty($fargs)){
$vargs = array();
foreach($fargs as $key => $arg){
$vargs[$key] = mysql_real_escape_string($arg);
}
array_shift($vargs);
if(!empty($vargs))$sql_tag = vsprintf($sql_tag,$vargs);
} Zu erst wird überprüft ob $fargs leer ist. (kann eigentlich nicht sein den db_query leer aufzurufen also nur db_query() macht wenig Sinn
ok danach erzeugen wir ein leeres Array $vargs;
jetzt wird jede Variable aus $fargs einzeln genommen mit mysql_real_escape string behandelt und unter dem selben key (nummer von 1 bis x) in $vargs abgelegt.
array_shift nimmt das erste Element von $vargs gibt es zurück und löscht es aus dem Array $vargs
jetzt wird noch überprüft ob $vargs nach dem löschen des einen Elemnts leer ist und danach wird $sql_tag mit vsprintf erzeugt.
Was passiert bei vsprintf?
vsprintf gibt einen Formatierten strung zurück und nimmt als 2. Parameter ein Array mit den ersetzungen entgegen.
heißt aus
vsprintf("%d-%d", array(7, 3)) wird eine 7-3
aus vsprinf("Hallo %s", User) wird Hallo User
usw
Danach wird nurnoch das Query ausgeführt mit mysql_query.
So was bringt uns unser wissen jetzt?
Nehmen wir mal an wir haben folgende abfrage
db_query("SELECT * FROM vms_kontodaten WHERE uid=$uid");1. wenn man $uid maniplieren kann dann wären sql injections tür und tor geöffnet
2. was steht den in $uid wahrscheinlich eine Zahl aber sicher?
um das abzusichern könnte man jetzt $uid mit intval($uid) behandeln oder bei der zuweißung ein int casten aber ist das beim einsetzen in die db_query funktion immernoch eine Zahl oder hat sich das inzwichen verändert? Sicher weiß man das so nicht.
Also was tuen?
Nochmal mit intval, eregi und anderen prüfen?
Nein warum denn wir haben doch unsere db_query methode
Dort machen wir aus
db_query("SELECT * FROM vms_kontodaten WHERE uid=$uid");einfach
db_query("SELECT * FROM vms_kontodaten WHERE uid=%01d", $uid);So was passiert jetzt?
der platzhalter %01d wird mit der ZAHL %uid ersetzt und wenn $uid keine Zahl ist wird eine 0 eingesetzt und vorher mit mysql_real_escape_string behandelt
heißt ausdrücke wie "123456' OR 1=1" werden unbrauchbar gemacht.
So jetzt das erschreckende bzw Fragwürdige.
Warum gibt es diese Funktion im VMS wenn sie nie genutzt wird?
mfg
Aradiv