flawopen.com/SQL Injection in PHP/Doctrine ORM
Schützt Doctrine ORM vor SQL-Injection?
Ja, bei DQL mit gebundenen Parametern. Werden DQL oder natives SQL durch Verkettung gebaut, entsteht das Risiko roher Abfragen erneut.
$em->createQuery( "SELECT u FROM User u " . "WHERE u.id = $userId" );
$qb->select('u')
->from('User', 'u')
->where('u.id = :id')
->setParameter('id', $userId);
Gebundene Werte schützen nicht die Abfragestruktur
setParameter() bindet DQL-Werte, die Doctrine in getrennte SQL-Parameter umsetzt. Verkettung in createQuery() umgeht diesen Schutz. Dasselbe gilt für natives SQL: Connection::executeQuery() ist mit Platzhaltern und Parameterliste sicher, nicht aber bei interpolierter Eingabe im SQL-String.
Parameter ersetzen keine Bezeichner
Ein Platzhalter steht für einen Wert, nicht für einen DQL-Bezeichner, eine SQL-Spalte, Tabelle, einen Operator oder eine Sortierrichtung. Die ORM-Sicherheitsdoku warnt, dass Benutzereingaben in QueryBuilder-Ausdrucksmethoden weiterhin injizierbares DQL erzeugen können. Halten Sie solche Ausdrücke im vertrauenswürdigen Code und erlauben Sie Sortieroptionen nur per enger Positivliste.
$qb->orderBy(
'u.' . $request->query->get('sort'),
$request->query->get('direction')
);
$fields = [
'name' => 'u.name',
'created' => 'u.createdAt',
];
$directions = ['asc' => 'ASC', 'desc' => 'DESC'];
$key = (string) $request->query->get('sort', 'name');
$sort = $fields[$key] ?? $fields['name'];
$requestedDirection = strtolower(
(string) $request->query->get('direction', 'asc')
);
$direction = $directions[$requestedDirection] ?? 'ASC';
$qb->orderBy($sort, $direction);
- ✓Binden Sie jeden externen Wert mit setParameter() oder DBAL-Platzhaltern; nie in DQL oder SQL verketten.
- ✓Behandeln Sie QueryBuilder-Ausdrucksmethoden und DQL-Fragmente wie Code. Erlauben Sie nur freigegebene Felder, Sortierungen, Operatoren und Funktionen.
- ✓Verwenden Sie für natives SQL executeQuery($sql, $params) oder executeStatement($sql, $params) mit Platzhaltern.
- ✓Prüfen Sie Datenfluss und Abfragestruktur. Auch gebundene Werte können nicht autorisierte Datensätze offenlegen; Autorisierung separat durchsetzen.
Codebasis prüfen
rg -n -g '*.php' 'createQuery\(|orderBy\(|addOrderBy\(|executeQuery\(' .Quellen und Referenzen
- Doctrine ORM — QueryBuilder-Parameter
- Doctrine ORM — Sicherheit
- Doctrine DBAL — vorbereitete Abfragen und Parameter
- FlawOpen — SQL-Injection in PHP