Kan jeg bruge en PDO-forberedt sætning til at binde en identifikator (et tabel- eller feltnavn) eller et syntaksnøgleord?
Desværre kan udarbejdet erklæring kun repræsentere en bogstavelig data. Så en meget almindelig faldgrube er en forespørgsel som denne:
$opt = "id";
$sql = "SELECT :option FROM t WHERE id=?";
$stm = $pdo->prepare($sql);
$stm->execute(array($opt));
$data = $stm->fetchAll();
Afhænger af PDO-indstillingerne, vil denne forespørgsel resultere i enten fejl (i tilfælde af brug af rigtige forberedte sætninger) eller blot en bogstavelig streng 'id'
i feltsættet (i tilfælde af emulerede forberedelser).
Så en udvikler skal selv sørge for identifikatorer - PDO tilbyder ingen hjælp for denne sag.
For at gøre en dynamisk identifikator sikker, skal man følge 2 strenge regler:
- for at formatere identifikator korrekt
- for at verificere det mod en hardkodet hvidliste .
For at formatere en identifikator skal man anvende disse 2 regler:
- Indsæt identifikator i backticks.
- Undgå tilbageslag indeni ved at fordoble dem.
Efter en sådan formatering er det sikkert at indsætte $table-variablen i forespørgslen. Så koden ville være:
$field = "`".str_replace("`","``",$field)."`";
$sql = "SELECT * FROM t ORDER BY $field";
Men selvom en sådan formatering ville være nok til sager som ORDER BY, er der i de fleste andre tilfælde mulighed for en anden form for injektion:at lade en bruger vælge en tabel eller et felt, de kan se, kan vi afsløre nogle følsomme oplysninger, såsom adgangskode eller andre personlige data. Så det er altid bedre at kontrollere dynamiske identifikatorer mod en liste over tilladte værdier. Her er et kort eksempel:
$allowed = array("name","price","qty");
$key = array_search($_GET['field'], $allowed);
$field = $allowed[$key];
$query = "SELECT $field FROM t"; //value is safe
For søgeord er reglerne de samme, men der er selvfølgelig ingen formatering tilgængelig - derfor er kun hvidliste mulig og bør bruges:
$dir = $_GET['dir'] == 'DESC' ? 'DESC' : 'ASC';
$sql = "SELECT * FROM t ORDER BY field $dir"; //value is safe
Se også denne brugerbidragende note i PHP-dokumentationen:Brugernote om PDO::quote