flawopen.com/SQL Injection in PHP/mysqli vs. PDO
MySQLi vs. PDO: sichere Prepared Statements
Ein Prepared Statement hält die SQL-Anweisungen fest und sendet Werte separat – wie beschriftete Formularfelder. PDO und MySQLi können das. Die Sicherheit entsteht durch korrekt gebundene Werte, nicht durch den Bibliotheksnamen.
Dieselbe Abfrage mit beiden APIs vorbereiten
$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();
Datenbankportabilität ist der Hauptunterschied von PDO
PDO bietet eine gemeinsame Schnittstelle für mehrere Treiber; MySQLi ist auf MySQL und MariaDB ausgerichtet. PDO macht SQL nicht automatisch portabel: Dialekte, Treiber und Funktionen unterscheiden sich weiterhin.
PDO unterstützt je nach Treiber benannte Platzhalter wie :id oder positionelle ?; mische die Stile nicht. MySQLi nutzt positionelle ?. Beide binden Werte, keine Tabellen-/Spaltennamen, Schlüsselwörter oder Sortierrichtungen.
PDO-Treiber verwenden native oder emulierte Vorbereitungen. Bei MySQL steuert PDO::ATTR_EMULATE_PREPARES die Emulation, sofern verfügbar; Treiber können emulieren oder zurückfallen, wenn native Vorbereitung nicht möglich ist. Beachte die Treiberdokumentation. Diese Option schützt kein interpoliertes SQL: Halte den Text fest und binde Werte in jedem Modus.
SQL-Injection-Regeln für beide Bibliotheken
Nutze prepare() und binde jeden nicht vertrauenswürdigen Wert. Halte SQL-Syntax fest; wähle dynamische Bezeichner aus einer strikten serverseitigen Map oder aus endlichen Abfragevarianten. Ein Prepared Statement autorisiert keinen Datensatz: Begrenze Abfragen bei Bedarf auf den authentifizierten Nutzer. Bei LIKE verhindert Binding SQL-Injection, doch % und _ bleiben Wildcards, sofern sie nicht für Literalsuche escaped werden.
Zwischen PDO und MySQLi wählen
- ✓Wähle PDO für eine gemeinsame API über Treiber hinweg; prüfe bei Migration SQL-Dialekt und Treiberverhalten.
- ✓Wähle MySQLi für reine MySQL/MariaDB-Anwendungen, die die MySQL-spezifische API benötigen.
- ✓Prüfe bei beiden auf Interpolation, Verkettung und dynamische Bezeichner; binde Werte und autorisiere Datensätze separat.
Häufige Fragen
Nein. Beide binden Werte sicher, wenn die Abfrage vorbereitet und Werte gebunden werden. Namen können lesbarer sein, binden aber keine SQL-Bezeichner und ersetzen keine Autorisierung.
Nicht pauschal. Treiberunterstützung und Fallback unterscheiden sich. Prüfe Dokumentation und Anforderungen. Halte unabhängig vom Modus die SQL-Struktur fest und übergib Werte als Parameter.
Nein. Parameter stehen für Werte, nicht für SQL-Bezeichner oder Schlüsselwörter. Ordne Client-Auswahlen einer endlichen Menge vertrauenswürdiger SQL-Fragmente im Server zu.
Quellen
- PHP-Handbuch — PDO Prepared Statements
- PHP-Handbuch — MySQLi Prepared Statements
- PHP-Handbuch — PDO::setAttribute und emulierte Vorbereitungen
- FlawOpen — SQL Injection in PHP