sql >> Database >  >> RDS >> Mysql

Kan ik een door een PDO voorbereide instructie gebruiken om een ​​identifier (een tabel- of veldnaam) of een syntaxissleutelwoord te binden?

Kan ik een door een PDO voorbereide instructie gebruiken om een ​​identifier (een tabel- of veldnaam) of een syntaxissleutelwoord te binden?

Helaas kan een voorbereide verklaring alleen een data-letterlijk vertegenwoordigen. Een veel voorkomende valkuil is dus een zoekopdracht als deze:

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

Afhankelijk van de PDO-instellingen, zal deze zoekopdracht een fout opleveren (in het geval van gebruik van echte voorbereide instructies) of alleen een letterlijke tekenreeks 'id' in de veldset (in het geval van geëmuleerde bereidingen).

Een ontwikkelaar moet dus zelf voor identifiers zorgen - PDO biedt geen hulp voor deze kwestie.

Om een ​​dynamische identifier veilig te maken, moet men zich aan 2 strikte regels houden:

  • identificatie correct opmaken
  • om het te verifiëren aan de hand van een hardgecodeerde witte lijst .

Om een ​​identifier te formatteren, moet men deze 2 regels toepassen:

  • Identificatiecode tussen backticks insluiten.
  • Ontsnap aan backticks door ze te verdubbelen.

Na een dergelijke opmaak is het veilig om de variabele $table in de query in te voegen. Dus de code zou zijn:

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

Hoewel een dergelijke opmaak voldoende zou zijn voor gevallen zoals ORDER BY, is er voor de meeste andere gevallen een mogelijkheid voor een ander soort injectie:een gebruiker een tabel of een veld laten kiezen dat hij kan zien, kunnen we enkele onthullen gevoelige informatie, zoals wachtwoord of andere persoonlijke gegevens. Het is dus altijd beter om dynamische id's te vergelijken met een lijst met toegestane waarden. Hier is een kort voorbeeld:

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

Voor zoekwoorden zijn de regels hetzelfde, maar er is natuurlijk geen opmaak beschikbaar - dus alleen whitelisting is mogelijk en zou moeten worden gebruikt:

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

Zie ook deze door een gebruiker bijgedragen opmerking in de PHP-documentatie:Gebruikersopmerking over PDO::quote




  1. Hoe een bestand van de ene map naar de andere te verplaatsen met behulp van PL SQL

  2. Kies uit de tabel door alleen de datum zonder tijd te kennen (ORACLE)

  3. Hoe de Date()-functie werkt in SQLite

  4. Hoe vervang ik een reguliere expressie in MySQL?