ORM Injection
Last updated
Last updated
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
En esta publicación se explica cómo es posible hacer que un Django ORM sea vulnerable utilizando, por ejemplo, un código como:
Nota cómo todos los request.data (que será un json) se pasan directamente a filtrar objetos de la base de datos. Un atacante podría enviar filtros inesperados para filtrar más datos de los esperados.
Ejemplos:
Login: En un inicio de sesión simple, intenta filtrar las contraseñas de los usuarios registrados dentro de él.
Es posible realizar un ataque de fuerza bruta a la contraseña hasta que se filtre.
Filtrado relacional: Es posible recorrer relaciones para filtrar información de columnas que ni siquiera se esperaban usar en la operación. Por ejemplo, si es posible filtrar artículos creados por un usuario con estas relaciones: Article(created_by
) -[1..1]-> Author (user
) -[1..1]-> User(password
).
Es posible encontrar la contraseña de todos los usuarios que han creado un artículo
Filtrado relacional de muchos a muchos: En el ejemplo anterior no pudimos encontrar las contraseñas de los usuarios que no han creado un artículo. Sin embargo, siguiendo otras relaciones esto es posible. Por ejemplo: Article(created_by
) -[1..1]-> Author(departments
) -[0..*]-> Department(employees
) -[0..*]-> Author(user
) -[1..1]-> User(password
).
En este caso, podemos encontrar todos los usuarios en los departamentos de usuarios que han creado artículos y luego filtrar sus contraseñas (en el json anterior solo estamos filtrando los nombres de usuario, pero luego es posible filtrar las contraseñas).
Abusando de las relaciones muchos-a-muchos de Grupo y Permiso con usuarios en Django: Además, el modelo AbstractUser se utiliza para generar usuarios en Django y, por defecto, este modelo tiene algunas relaciones muchos-a-muchos con las tablas de Permiso y Grupo. Lo que básicamente es una forma predeterminada de acceder a otros usuarios desde un usuario si están en el mismo grupo o comparten el mismo permiso.
Bypass filter restrictions: La misma publicación del blog propuso eludir el uso de algunos filtros como articles = Article.objects.filter(is_secret=False, **request.data)
. Es posible volcar artículos que tienen is_secret=True porque podemos retroceder desde una relación a la tabla Article y filtrar artículos secretos de artículos no secretos porque los resultados están unidos y el campo is_secret se verifica en el artículo no secreto mientras se filtran los datos del artículo secreto.
Abusando de las relaciones, es posible eludir incluso los filtros destinados a proteger los datos mostrados.
Error/Time based via ReDoS: En los ejemplos anteriores se esperaba tener diferentes respuestas si el filtrado funcionaba o no para usar eso como oráculo. Pero podría ser posible que se realice alguna acción en la base de datos y la respuesta sea siempre la misma. En este escenario, podría ser posible provocar un error en la base de datos para obtener un nuevo oráculo.
De la misma publicación sobre este vector:
SQLite: No tiene un operador regexp por defecto (requiere cargar una extensión de terceros)
PostgreSQL: No tiene un tiempo de espera de regex por defecto y es menos propenso a retrocesos
MariaDB: No tiene un tiempo de espera de regex
Los siguientes son trucos extraídos de esta publicación.
Control total de búsqueda:
Es posible ver que todo el cuerpo de javascript se pasa a prisma para realizar consultas.
En el ejemplo de la publicación original, esto verificaría todas las publicaciones creadas por alguien (cada publicación es creada por alguien) devolviendo también la información del usuario de esa persona (nombre de usuario, contraseña...)
Control total de la cláusula where:
Veamos esto donde el ataque puede controlar la cláusula where
:
Es posible filtrar la contraseña de los usuarios directamente como:
Usando operaciones como startsWith
es posible filtrar información.
Elusión de filtrado relacional de muchos a muchos:
Es posible filtrar artículos no publicados al retroceder a las relaciones de muchos a muchos entre Category
-[*..*]-> Article
:
También es posible leak todos los usuarios abusando de algunas relaciones de muchos a muchos de bucle.
Consultas de error/temporalizadas: En la publicación original puedes leer un conjunto muy extenso de pruebas realizadas para encontrar la carga útil óptima para filtrar información con una carga útil basada en el tiempo. Esto es:
Donde {CONTAINS_LIST}
es una lista con 1000 cadenas para asegurarse de que la respuesta se retrase cuando se encuentra la fuga correcta.
Estos trucos fueron encontrados en esta publicación.
Tenga en cuenta que Ransack 4.0.0.0 ahora impone el uso de una lista de permitidos explícita para atributos y asociaciones buscables.
Ejemplo vulnerable:
Nota cómo la consulta será definida por los parámetros enviados por el atacante. Fue posible, por ejemplo, forzar el token de restablecimiento con:
Al forzar y potencialmente relacionar, fue posible filtrar más datos de una base de datos.
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)