Zitat Zitat von Aradiv Beitrag anzeigen

Dort machen wir aus
PHP-Code:
db_query("SELECT * FROM vms_kontodaten WHERE uid=$uid"); 
einfach
PHP-Code:
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.
Das ist so oder so sehr gefährlich da mysql_real_escape_string fast gar nicht greift. In dem oben aufgeführten Ausdruck befindet sich ein ' weswegen mysql_real_escape_string greift. lassen wir das ' (der Ausdruck ist ja eine Usereingabe...) einfach weg haben wir:
123456 OR 1=1
hier greift weder mysql_real_escape_string noch vsprintf. Das Ergebnis ist also:

SELECT * FROM vms_kontodaten WHERE uid=123456 OR 1=1

Der Fehler liegt in den Fehlenden ' innerhalb der Query. Machen wir aus:
PHP-Code:
db_query("SELECT * FROM vms_kontodaten WHERE uid=$uid"); 
einfach ein
PHP-Code:
db_query("SELECT * FROM vms_kontodaten WHERE uid='$uid'"); 
greift schon mal mysql_real_escape_string und macht daraus ein:
SELECT * FROM vms_kontodaten WHERE uid=\'123456 OR 1=1\' und die Funktion gibt als $sql_tag: SELECT * FROM vms_kontodaten WHERE uid='123456 OR 1=1' zurück.

Solange man:
PHP-Code:
db_query("SELECT * FROM vms_kontodaten WHERE uid=%01d"$uid); 
nur mit dem Platzhalter: %01d (für int) verwendet ist das auch sicher. Die Rückgabe hier:
SELECT * FROM vms_kontodaten WHERE uid=123456
das "or 1=1" wird einfach weg gelassen.

Gefährlich wird es wenn man einen anderen Platzhalter verwendet z.Bsp.: %01s (für Strings).

Hier wird daraus auch wieder ein:
SELECT * FROM vms_kontodaten WHERE uid=123456 OR 1=1
Hier wird wieder alles umgangen.
Besser:
PHP-Code:
db_query("SELECT * FROM vms_kontodaten WHERE uid='%01d'"$uid); 
auch hier hab ich lediglich die beiden ' eingefügt. Schon sieht das Ergebnis im $sql_tag wieder so aus:
SELECT * FROM vms_kontodaten WHERE uid='123456 OR 1=1'
also ungefährlich.

Wie man leicht sieht, ist die richtige Schreibweise der Query an sich auch von entscheidener Bedeutung. Zudem muss man davon ausgehen das mit der Funktion nicht nur Zahlen sondern auch Text abgesichert werden soll.

Wer die beiden ' um eine Variable vergisst hebelt die Sicherungen der Funktion selber aus. Ein Umstand den ich leider bei einigen Addons, etc. gesehen habe.

Aus diesem Grund sollte man Grundsätzlich immer! am Anfang eines Script jede! Usereingabe Prüfen. Das kombiniert mit der richtigen Anwendung der Funktion db_query und man ist relativ sicher.

Wer damit mal etwas testen möchte, das geht einfach mit dem Script:

PHP-Code:
<?

// Datenbankserver
$db_host        = "localhost";                             
// Mysql User
$db_user        = "xxxxx";      // Datenbank User                              
// Mysql PW
$db_pass        = "Passwort";                                    
// Datenbank
$db_base        = "Datenbank Name";                                    
// Tabellenpräfix (wichtig wenn mehrere VMS in einer DB liegen)
$db_prefix        = "vms";                                    

function db_connect() {
global $db_host,$db_user,$db_pass,$db_base,$sql_open;
    $sql_open    = mysql_connect($db_host,$db_user,$db_pass) or die('Verbindung zum Mysql Server fehlgeschlagen!');
    $sql_base    = mysql_select_db($db_base) or die("Keine oder falsche Datenbank gewählt!");
}

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); 
          echo "<br>";
        echo "vargs[key]: ".$vargs[$key];
        echo "<br>";
    } 
    array_shift($vargs); 
    if(!empty($vargs))$sql_tag = vsprintf($sql_tag,$vargs); 
        echo "<br>";
        echo "sql_tag: ".$sql_tag;
        echo "<br>";
  } 
    if($ret = mysql_query($sql_tag)){ 
      return $ret; 
        echo "ret: ".$ret;
        echo "<br>";
    }else{ 
      return 0; 
    } 
}
$uid = "123456 OR 1=1";
//$uid = "1234";
//$uid = (int)$uid;
echo "uid: ".$uid;
echo "<br>";
db_connect();
//$sql = db_query("SELECT * FROM vms_kontodaten WHERE uid='$uid'"); 
//$sql = db_query("SELECT * FROM vms_kontodaten WHERE uid=$uid"); 
//$sql = db_query("SELECT * FROM vms_kontodaten WHERE uid=%01d", $uid);  //Zahlen
$sql = db_query("SELECT * FROM vms_kontodaten WHERE uid='%01d'", $uid);  // Zahlen
//$sql = db_query("SELECT * FROM vms_kontodaten WHERE uid=%01s", $uid);  // String
$sql = db_query("SELECT * FROM vms_kontodaten WHERE uid='%01s'", $uid);  // String
$kontoinfo = mysql_fetch_array($sql);
print_r($kontoinfo);
echo "<br>";

echo "kontoinfo".$kontoinfo['uid'];
?>
zum ändern des Aufrufs einfach die entsprechende Zeile aktivieren