Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Kann ich eine vorbereitete PDO-Anweisung verwenden, um einen Bezeichner (einen Tabellen- oder Feldnamen) oder ein Syntaxschlüsselwort zu binden?

Kann ich eine vorbereitete PDO-Anweisung verwenden, um einen Bezeichner (einen Tabellen- oder Feldnamen) oder ein Syntaxschlüsselwort zu binden?

Leider kann eine vorbereitete Anweisung nur ein Datenliteral darstellen. Eine sehr häufige Falle ist also eine Abfrage wie diese:

$opt = "id";
$sql = "SELECT :option FROM t WHERE id=?";
$stm  = $pdo->prepare($sql);
$stm->execute(array($opt));
$data = $stm->fetchAll();

Abhängig von den PDO-Einstellungen ergibt diese Abfrage entweder einen Fehler (bei Verwendung echter vorbereiteter Anweisungen) oder nur einen Literal-String 'id' im Fieldset (bei emulierten Prepares).

Ein Entwickler muss sich also selbst um Identifier kümmern - PDO bietet keine Hilfe für diese Angelegenheit.

Um einen dynamischen Bezeichner sicher zu machen, muss man 2 strenge Regeln befolgen:

  • Bezeichner richtig formatieren
  • um es mit einer fest codierten weißen Liste zu verifizieren .

Um einen Bezeichner zu formatieren, muss man diese 2 Regeln anwenden:

  • Bezeichner in Backticks einschließen.
  • Entkomme Backticks im Inneren, indem du sie verdoppelst.

Nach einer solchen Formatierung ist es sicher, die $table-Variable in die Abfrage einzufügen. Der Code wäre also:

$field = "`".str_replace("`","``",$field)."`";
$sql   = "SELECT * FROM t ORDER BY $field";

Obwohl eine solche Formatierung für Fälle wie ORDER BY ausreichen würde, gibt es für die meisten anderen Fälle eine Möglichkeit für eine andere Art der Injektion:Lassen Sie einen Benutzer eine Tabelle oder ein Feld auswählen, das er sehen kann, wir können einige enthüllen sensible Informationen, wie Passwörter oder andere persönliche Daten. Daher ist es immer besser, dynamische Bezeichner anhand einer Liste zulässiger Werte zu überprüfen. Hier ist ein kurzes Beispiel:

$allowed = array("name","price","qty");
$key     = array_search($_GET['field'], $allowed);
$field   = $allowed[$key];
$query   = "SELECT $field FROM t"; //value is safe

Für Schlüsselwörter gelten die gleichen Regeln, aber natürlich ist keine Formatierung verfügbar - daher ist nur Whitelisting möglich und sollte verwendet werden:

$dir = $_GET['dir'] == 'DESC' ? 'DESC' : 'ASC'; 
$sql = "SELECT * FROM t ORDER BY field $dir"; //value is safe

Siehe auch diesen von Benutzern beigesteuerten Hinweis in der PHP-Dokumentation:Benutzerhinweis zu PDO::quote