FlawOpen

flawopen.com/SQL Injection en PHP/mysqli vs PDO

MySQLi vs PDO : prepared statements sûres

Page de référence
Réponse courte

Une prepared statement garde le SQL fixe et transmet les valeurs séparément, comme des cases étiquetées à remplir. PDO et MySQLi le permettent. La sécurité vient du binding correct, pas du nom de la bibliothèque.

La même requête préparée avec chaque API

DANGEREUX — SQL avec données de requête
$userId = $_GET['id'];
$sql = "SELECT id, email FROM users WHERE id = " . $userId;

// Both calls execute the already-built SQL string:
$rows = $mysqli->query($sql);
$rows = $pdo->query($sql);
SÛR — lier les valeurs dans les deux API
// PDO
$stmt = $pdo->prepare(
    "SELECT id, email FROM users WHERE id = :id"
);
$stmt->execute(["id" => $userId]);

// MySQLi
$stmt = $mysqli->prepare(
    "SELECT id, email FROM users WHERE id = ?"
);
$stmt->bind_param("i", $userId);
$stmt->execute();

La portabilité entre bases est la principale différence de PDO

La portabilité entre bases est la principale différence de PDO

PDO fournit une interface commune à plusieurs drivers ; MySQLi cible MySQL et MariaDB. PDO ne rend pas le SQL portable à lui seul : dialectes, drivers et fonctions varient.

Les styles de placeholder diffèrent

PDO accepte des placeholders nommés comme :id ou positionnels ?, selon le driver ; ne mélangez pas les styles. MySQLi utilise ?. Les deux lient des valeurs, pas les noms de table/colonne, mots-clés ou tris.

Le mode de préparation PDO dépend du driver

Les drivers PDO peuvent utiliser des préparations natives ou émulées. Avec MySQL, PDO::ATTR_EMULATE_PREPARES règle l’émulation lorsqu’elle est disponible ; certains drivers l’émulent ou y reviennent si la préparation native échoue. Suivez la documentation du driver. Ce réglage ne sécurise pas le SQL interpolé : gardez le texte fixe et liez les valeurs.

Règles anti-SQL Injection pour les deux bibliothèques

Utilisez prepare() et liez chaque valeur non fiable. Gardez la syntaxe SQL fixe ; sélectionnez les identifiants dynamiques via une map stricte côté serveur ou un ensemble fini de requêtes. Une prepared statement n’autorise pas l’accès à une ligne : limitez la requête à l’utilisateur authentifié si nécessaire. Avec LIKE, le binding prévient l’injection SQL, mais % et _ restent des jokers sans échappement pour une recherche littérale.

Choisir entre PDO et MySQLi

Questions fréquentes

Les placeholders nommés PDO sont-ils plus sûrs que les ? de MySQLi ?

Non. Les deux peuvent lier les valeurs si la requête est préparée et les paramètres transmis. Les noms améliorent parfois la lisibilité, mais ne lient pas les identifiants et ne remplacent pas l’autorisation.

Faut-il toujours désactiver les préparations émulées PDO ?

Pas systématiquement. Le support et le fallback varient selon le driver. Consultez sa documentation et les exigences de l’application. Gardez la structure SQL fixe et transmettez les valeurs comme paramètres dans tous les modes.

Une prepared statement peut-elle lier un nom de table ou de colonne ?

Non. Les paramètres représentent des valeurs, pas des identifiants ou mots-clés SQL. Associez le choix client à un ensemble fini de fragments fiables côté serveur.

Références

À voir aussi Injection SQL (CWE-89) : fonctionnement et prévention dans chaque langage — flawopen.com NHibernate protège-t-il contre les injections SQL ? Injection NoSQL MongoDB : filtres sûrs Un ID numérique peut-il aussi provoquer une injection SQL ? Qu'est-ce qu'une requête paramétrée ? Prisma $queryRaw protège-t-il contre les injections SQL ? L’interpolation dans where() de Rails est-elle sûre ?