7

Ich verstehe, dass die vorbereiteten Anweisungen der ultimative Weg ist, Schutz gegen die SQL-Injektion suchen. Sie bieten jedoch eine begrenzte Abdeckung; Zum Beispiel in Fällen, in denen ich den Benutzer zu entscheiden, wie die Reihenfolge von Operation zu sein (d. h. ist es ASC oder DESC? etc), bekomme ich keine Berichterstattung dort mit den vorbereiteten Anweisungen.PHP: mit vorbereiteten Anweisungen und Schutz vor SQL-Injektion vs Escape

Ich verstehe, dass ich die Benutzereingabe für eine vordefinierte Whitelist zuordnen kann. Dies ist jedoch nur möglich, wenn zuvor eine Whitelist erstellt oder erraten werden kann.

Zum Beispiel, in den Fällen, die ich oben erwähne (der ASC oder DESC), kann dies leicht zugeordnet und verifiziert werden gegen eine Liste von akzeptierten Werten. Aber gibt es nicht eine Situation, in der der Teil der SQL-Anweisung nicht gegen eine Whitelist verifiziert werden kann?

Wenn eine solche Situation besteht, was ist der empfohlene Ansatz?

Wenn ich die user_input mit dem integrierten Escape-Dienstprogramm der zugrunde liegenden Datenbank (wie mysqL_real_escape_string für mysql) auf der ganzen Linie zu entkommen, wo würde ich scheitern?

ich diese Frage mit der Annahme bin gefragt, dass ich immer meine SQL-Anweisungen mit angegebenen Werte konstruieren - auch für ganze Zahlen ...

Schauen wir uns das folgende Beispiel einen Blick darauf werfen und reflektieren es ..

select {$fields} from {$table} where Age='{$age}' order by {$orderby_pref} 

Angenommen, alle Vars werden vom Benutzer bereitgestellt.

Wenn ich zu mysql_real_escape_string alle Variablen in der oben genannten SQL (im Gegensatz zur Verwendung vorbereiteter Aussagen, die mich nur in der Hälfte der Weg zwingt mich zu weißen Listen für die andere Hälfte kommen, dass es nicht helfen kann), wäre es nicht gleichermaßen sicher (und einfacher zu codieren)? Wenn nicht, in welchem ​​Eingabeszenario würde das Escape-Dienstprogramm fehlschlagen?

$fields  = mysql_escape($fields); 
$table  = mysql_escape($table); 
$age   = mysql_escape($age); 
$orderby_pref = mysql_escape($orderby_pref); 

select {$fields} from {$table} where Age='{$age}' order by {$orderby_pref} 
+2

Upvoted, weil Sie wissen, und kümmern sich um SQL-Injektionen (im Gegensatz zu den meisten Menschen Fragen hier im PHP-Tag) – Mahn

+0

Es gibt einen Unterschied zwischen dynamischen SQL und Hinzufügen von Werten in Abfragen. Beide gebundenen Parameter oder String-Verkettung (plus Escaping) können zum Hinzufügen von Werten verwendet werden. Dynamisches SQL erfordert eine Positivliste für die Positivliste. Verwenden Sie also entweder eine Regex-, eine Map- oder eine switch-Anweisung, um 'DESC' oder' ORDER' und andere Qualifier hinzuzufügen. Gespeicherte Verfahren wären jedoch eine langatmige Alternative. – mario

Antwort

3

Sie müssen immer weiße Listen für Dinge wie Tabellen- oder Spaltennamen verwenden, ob Sie vorbereitete Anweisungen oder die mysql Escape-Funktionen verwenden.

Das Problem ist, dass Tabellennamen und Spaltennamen nicht in einfachen oder doppelten Anführungszeichen zitiert werden. Wenn Sie also eine Funktion verwenden, die diese Zeichen (und noch einige weitere) angibt, wird dies nichts für Sie tun Tabellenname.

Betrachten Sie den Tabellennamen my_table; DELETE * FROM mysql; SELECT * FROM my_table. Nichts in dieser Zeichenkette wird durch die Escape-Funktionen von mysql maskiert, aber es ist definitiv eine Zeichenkette, die Sie anhand einer Whitelist überprüfen möchten.

Abgesehen davon haben die Escape-Funktionen mysql ein Problem mit Zeichensätzen, die sie nutzlos machen können, so dass Sie immer besser mit vorbereiteten Anweisungen sind.

+2

IHR BEISPIEL VON 'my_table; DELETE * FROM mysql; SELECT * FROM my_table' NAGELN ES SEHR GUT ZU, WARUM DER MYSQL_ESCAPE-ANSATZ SCHLECHT WERDEN WÜRDE .... Also, im einfachen und einfachen Gespräch, die einzige Alternative für den SQL-Injection-Schutz (für die Teile, wo die vorbereiteten Anweisungen oder die db's Escape-Dienstprogramm hilft nicht), ist die Whitelist-Ansatz zu verwenden. Ist diese Schlussfolgerung richtig? –

+0

@Average Joe Das ist richtig. – jeroen

+0

+1 für das Vorschlagen eines Whitelist-Ansatzes – Mahn

3

Sie PDO und Ihr Leben nutzen könnte erhalten einfacher ...:

# Order 
    switch(strtoupper($Order)){ 
     default: 
     case 'ASC': 
      $Order = 'ASC'; 
      break; 

     case 'DESC': 
      $Order = 'DESC'; 
      break; 
    } 

    # ID 
    $ID = 39; 
    $Username = 'David'; 

    # Query 
    $Query = $this->DB->Main->prepare('SELECT * FROM Table WHERE ID = :ID AND Username = :Username ORDER BY HellBob '.$Order); 
    $Query->bindValue(':ID', $ID, PDO::PARAM_INT); 
    $Query->bindValue(':Username', $Username, PDO::PARAM_STR); 

    # All good ? 
    if(!$Query->execute()){ 
     exit('Error'); 
    } 

    // Results 
    $Row = $Query->fetch(PDO::FETCH_ASSOC); 

Sie müssen über Angebote oder SQL-Injektionen keine Sorge. Sie können eine einfache "Whitelist" verwenden, um Variablen in Ihre Abfrage zu übernehmen.

+1

Sie haben das Bestellfeld vergessen ;-) – Waygood

+0

@Waygood Oups. Vielen Dank. Habe das Update gemacht! –

+1

Dies beantwortet die Frage nicht wirklich, da Sie den Tabellennamen, die Spaltennamen und die Sortierreihenfolge-Spalte in der Abfrage fest codiert haben. – jeroen

Verwandte Themen