flawopen.com/SQL Injection in PHP/Doctrine ORM
¿Doctrine ORM es seguro frente a la inyección SQL?
Sí para DQL con parámetros vinculados. Construir DQL o SQL nativo concatenando texto vuelve a introducir el riesgo de cualquier consulta sin parametrizar.
$em->createQuery( "SELECT u FROM User u " . "WHERE u.id = $userId" );
$qb->select('u')
->from('User', 'u')
->where('u.id = :id')
->setParameter('id', $userId);
Los valores vinculados no protegen la estructura de la consulta
setParameter() vincula valores DQL, que Doctrine traduce a parámetros SQL separados del texto de consulta. Concatenar datos en createQuery() elude esa protección. La misma regla se aplica a SQL nativo: Connection::executeQuery() es seguro con marcadores y una lista de parámetros, pero no si interpolas la entrada en la cadena SQL.
Los parámetros no sustituyen identificadores
Un marcador representa un valor, no un identificador DQL, columna SQL, tabla, operador ni dirección de ordenación. La guía de seguridad del ORM advierte que la entrada en métodos de expresión de QueryBuilder aún puede crear DQL inyectable. Mantén esas expresiones en código confiable y asigna las opciones de ordenación a una lista estricta de valores permitidos.
$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);
- ✓Vincula cada valor externo con setParameter() o marcadores DBAL; no lo concatentes en DQL ni SQL.
- ✓Trata los métodos de expresión de QueryBuilder y los fragmentos DQL como código. Permite solo campos, direcciones, operadores y funciones aprobados.
- ✓Para SQL nativo, usa executeQuery($sql, $params) o executeStatement($sql, $params) con marcadores.
- ✓Revisa el flujo de datos y la estructura de la consulta. Un valor parametrizado aún puede exponer registros no autorizados; aplica autorización aparte.
Cómo revisar tu código
rg -n -g '*.php' 'createQuery\(|orderBy\(|addOrderBy\(|executeQuery\(' .Fuentes y referencias
- Doctrine ORM — parámetros de QueryBuilder
- Doctrine ORM — seguridad
- Doctrine DBAL — consultas preparadas y parámetros
- FlawOpen — inyección SQL en PHP