FlawOpen

flawopen.com/SQL Injection in PHP/Doctrine ORM

Schützt Doctrine ORM vor SQL-Injection?

Reference page
Kurzantwort

Ja, bei DQL mit gebundenen Parametern. Werden DQL oder natives SQL durch Verkettung gebaut, entsteht das Risiko roher Abfragen erneut.

UNSICHER — Eingabe wird zu DQL-Syntax
$em->createQuery(
  "SELECT u FROM User u "
  . "WHERE u.id = $userId"
);
SICHER — nur vertrauenswürdige Ausdrücke
$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.

UNSICHER — Eingabe wird zu DQL-Syntax
$qb->orderBy(
  'u.' . $request->query->get('sort'),
  $request->query->get('direction')
);
SICHER — nur vertrauenswürdige Ausdrücke
$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);

Codebasis prüfen

rg -n -g '*.php' 'createQuery\(|orderBy\(|addOrderBy\(|executeQuery\(' .
Prüfen Sie Treffer auf Verkettung/Interpolation, Benutzereingaben in Ausdrucks-APIs und Bezeichner außerhalb einer festen Positivliste. Treffer sind Prüfkandidaten, kein Exploitnachweis.

Quellen und Referenzen

Siehe auch SQL-Injection (CWE-89): Funktionsweise und Schutz in jeder Sprache — flawopen.com EF Core FromSqlRaw: Sicheres SQL mit Parametern FastAPI SQL Injection: Was Pydantic verhindert GORM Raw SQL: SQL-Injection in Go verhindern Reicht das Escapen von Anführungszeichen gegen SQL Injection? Reicht ein ORM aus, um SQL-Injection zu verhindern? Ist Knex.js vor SQL-Injection geschützt?