FlawOpen

flawopen.com/SQL Injection in PHP/Doctrine ORM

Doctrine ORM protège-t-il contre l’injection SQL ?

Reference page
Réponse courte

Oui pour le DQL avec des paramètres liés. Concaténer des données dans du DQL ou du SQL natif réintroduit le risque des requêtes brutes.

DANGEREUX — l’entrée devient une syntaxe DQL
$em->createQuery(
  "SELECT u FROM User u "
  . "WHERE u.id = $userId"
);
SÛR — expressions de confiance uniquement
$qb->select('u')
  ->from('User', 'u')
  ->where('u.id = :id')
  ->setParameter('id', $userId);

Les valeurs liées ne protègent pas la structure de la requête

setParameter() lie une valeur DQL que Doctrine convertit en paramètre SQL, séparé du texte de la requête. La concaténer dans createQuery() contourne cette protection. Même règle pour le SQL natif : Connection::executeQuery() est sûr avec des marqueurs et un tableau de paramètres, pas si l’entrée est interpolée dans la chaîne SQL.

Un paramètre ne remplace pas un identifiant

Un marqueur représente une valeur, pas un identifiant DQL, une colonne SQL, une table, un opérateur ni un sens de tri. La documentation de sécurité de l’ORM avertit que l’entrée utilisateur dans les méthodes d’expression de QueryBuilder peut encore former du DQL injectable. Gardez ces expressions dans le code de confiance et choisissez les options de tri depuis une liste fermée.

DANGEREUX — l’entrée devient une syntaxe DQL
$qb->orderBy(
  'u.' . $request->query->get('sort'),
  $request->query->get('direction')
);
SÛR — expressions de confiance uniquement
$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);

Auditer votre base de code

rg -n -g '*.php' 'createQuery\(|orderBy\(|addOrderBy\(|executeQuery\(' .
Examinez chaque résultat pour repérer concaténation/interpolation, entrée utilisateur dans les API d’expression et identifiants hors liste fixe. Les résultats orientent la revue sans prouver l’exploitabilité.

Sources et références

À voir aussi Injection SQL (CWE-89) : fonctionnement et prévention dans chaque langage — flawopen.com EF Core FromSqlRaw : SQL paramétré sûr FastAPI et SQL Injection : limites de Pydantic GORM Raw SQL : éviter l’injection SQL en Go Échapper les guillemets suffit-il contre SQL Injection ? Utiliser un ORM suffit-il à prévenir l'injection SQL ? Knex.js protège-t-il contre les injections SQL ?