flawopen.com/SQL Injection en PHP/mysqli vs PDO
MySQLi vs PDO: prepared statements seguros
Una prepared statement mantiene fijas las instrucciones SQL y envía los valores por separado, como rellenar casillas etiquetadas. PDO y MySQLi permiten hacerlo. La seguridad depende de enlazar bien los valores, no del nombre de la biblioteca.
La misma consulta preparada con ambas API
$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);
// 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 portabilidad de bases de datos es la principal diferencia de PDO
PDO ofrece una interfaz común para varios drivers; MySQLi se limita a MySQL y MariaDB. PDO no vuelve portable el SQL por sí mismo: los dialectos, drivers y funciones siguen variando.
PDO admite placeholders con nombre, como :id, o posicionales ?, según el driver; no mezcles estilos. MySQLi usa ?. Ambos enlazan valores, no nombres de tablas o columnas, palabras clave ni ordenaciones.
Los drivers PDO pueden usar preparaciones nativas o emuladas. En MySQL, PDO::ATTR_EMULATE_PREPARES controla la emulación cuando está disponible; algunos drivers emulan o recurren a ella si no pueden preparar de forma nativa. Sigue la documentación del driver. Esta opción no protege SQL interpolado: fija el texto y enlaza valores en cualquier modo.
Reglas contra SQL injection para ambas bibliotecas
Usa prepare() y enlaza cada valor no confiable. Mantén fija la sintaxis SQL; elige identificadores dinámicos de un mapa estricto del servidor o usa variantes finitas. Una prepared statement no autoriza el acceso a filas: limita la consulta al usuario autenticado cuando corresponda. En LIKE, enlazar evita la inyección SQL, pero % y _ siguen siendo comodines salvo que se escapen para buscar literalmente.
Elegir entre PDO y MySQLi
- ✓Elige PDO si necesitas una API común entre drivers; comprueba el dialecto y el comportamiento del driver al migrar.
- ✓Elige MySQLi en aplicaciones solo MySQL/MariaDB que necesiten su API específica.
- ✓Con cualquiera, revisa interpolación, concatenación e identificadores dinámicos; enlaza valores y autoriza registros por separado.
Preguntas frecuentes
No. Ambos enlazan valores de forma segura si la consulta se prepara y los valores se vinculan. Los nombres pueden facilitar la lectura, pero no enlazan identificadores ni reemplazan la autorización.
No como regla general. El soporte y el fallback varían por driver. Consulta su documentación y los requisitos de la aplicación. Mantén fija la estructura SQL y pasa valores como parámetros en cualquier modo.
No. Los parámetros representan valores, no identificadores ni palabras clave SQL. Mapea la elección del cliente a fragmentos confiables y finitos en el servidor.
Referencias
- Manual de PHP — prepared statements de PDO
- Manual de PHP — prepared statements de MySQLi
- Manual de PHP — PDO::setAttribute y preparaciones emuladas
- FlawOpen — SQL Injection en PHP