FlawOpen

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

MySQLi vs. PDO: sichere Prepared Statements

Referenzseite
Kurzantwort

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

UNSICHER — SQL mit Request-Daten
$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);
SICHER — Werte in beiden APIs binden
// 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

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.

Die Platzhalterarten unterscheiden sich

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.

Der PDO-Vorbereitungsmodus hängt vom Treiber ab

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

Häufige Fragen

Sind PDO-Namensplatzhalter sicherer als MySQLi-Fragezeichen?

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.

Sollte ich emulierte PDO-Vorbereitungen immer deaktivieren?

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.

Kann ein Prepared Statement einen Tabellen- oder Spaltennamen binden?

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

Siehe auch SQL-Injection (CWE-89): Funktionsweise und Schutz in jeder Sprache — flawopen.com Schützt NHibernate vor SQL-Injection? MongoDB NoSQL Injection: sichere Abfragefilter Können auch numerische IDs SQL Injection verursachen? Was ist eine parametrisierte Abfrage? Ist Prisma $queryRaw vor SQL-Injection sicher? Ist String-Interpolation in Rails where() sicher?