Mysql
 sql >> Database >  >> RDS >> Mysql

Posso utilizzare un'istruzione preparata PDO per associare un identificatore (una tabella o un nome di campo) o una parola chiave di sintassi?

Posso utilizzare un'istruzione preparata PDO per associare un identificatore (una tabella o un nome di campo) o una parola chiave di sintassi?

Sfortunatamente, l'istruzione preparata può rappresentare solo un valore letterale di dati. Quindi, una trappola molto comune è una query come questa:

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

Dipende dalle impostazioni PDO, questa query risulterà con un errore (in caso di utilizzo di istruzioni preparate reali) o solo una stringa letterale 'id' nel fieldset (in caso di preparazioni emulate).

Quindi, uno sviluppatore deve occuparsi personalmente degli identificatori:PDO non offre nessun aiuto per questo.

Per rendere sicuro un identificatore dinamico, devi seguire 2 regole rigide:

  • per formattare correttamente l'identificatore
  • per verificarlo rispetto a una lista bianca hardcoded .

Per formattare un identificatore, è necessario applicare queste 2 regole:

  • Raccogli l'identificatore nei backtick.
  • Sfuggi ai backtick all'interno raddoppiandoli.

Dopo tale formattazione, è possibile inserire la variabile $table nella query. Quindi, il codice sarebbe:

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

Tuttavia, sebbene una tale formattazione sarebbe sufficiente per casi come ORDER BY, per la maggior parte degli altri casi esiste la possibilità di un diverso tipo di iniezione:lasciando che un utente scelga una tabella o un campo che può vedere, potremmo rivelare alcuni informazioni sensibili, come password o altri dati personali. Quindi, è sempre meglio controllare gli identificatori dinamici rispetto a un elenco di valori consentiti. Ecco un breve esempio:

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

Per le parole chiave le regole sono le stesse, ma ovviamente non è disponibile alcuna formattazione, quindi è possibile e dovrebbe essere utilizzata solo la whitelist:

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

Vedi anche la nota che ha contribuito all'utente nella documentazione PHP:Nota utente su PDO::quote