Las técnicas basadas en el tiempo se utilizan a menudo para realizar pruebas cuando no hay otra forma de recuperar información del servidor de la base de datos. Este tipo de ataque inyecta un segmento SQL que contiene una función DBMS específica o una consulta pesada que genera un retraso de tiempo. Dependiendo del tiempo que tarde en obtener la respuesta del servidor, es posible deducir alguna información. Como puede adivinar, este tipo de enfoque de inferencia es particularmente útil para ataques de inyección SQL ciegos y ciegos profundos.

Inyectar un delay

Los ataques basados en el tiempo se pueden utilizar para lograr pruebas muy básicas, como determinar si existe una vulnerabilidad. Esta suele ser una excelente opción cuando el atacante se enfrenta a una inyección SQL profunda y ciega. En esta situación, solo son necesarias las funciones/procedimientos de retardo. La siguiente tabla muestra cómo se puede pausar la ejecución de la consulta en cada DBMS.

DBMSFunciónNotas
MySQLSLEEP(time)Solo disponible desde MySQL 5. Se tarda unos segundos en esperar en el parámetro. Más detalles aquí.
MySQLBENCHMARK(countexpr)Ejecuta la expresión especificada varias veces. Al usar un número grande como primer parámetro, podrá generar un retraso. Más detalles sobre la función en el sitio web de MySQL.
SQL ServerWAIT FOR DELAY ‘hh:mm:ssSuspende la ejecución durante el tiempo especificado. Para más información sobre este procedimiento consulte la documentación oficial de SQL Server.
SQL ServerWAIT FOR TIME ‘hh:mm:ssSuspende la ejecución de la consulta y la continúa cuando el tiempo del sistema es igual al parámetro. Consulte el enlace anterior para obtener más información.
OracleLos ataques basados en el tiempo son más complicados en Oracle. Consulte la sección de Oracle a continuación para obtener más información.

Nota: Siempre asegúrese de saber qué sistema de base de datos se utiliza antes de comenzar sus pruebas basadas en el tiempo. Puede intentar inyectar funciones de retardo hasta que encuentre una que genere un resultado positivo. Si nada de lo anterior genera una respuesta lenta, recurra a las técnicas enumeradas en el artículo sobre la toma de huellas dactilares de la base de datos.

La identificación de vulnerabilidades no es la única utilidad de los ataques basados en el tiempo. Cuando el retraso de tiempo se integra en una declaración condicional, el atacante podrá recuperar información de la base de datos e incluso extraer datos. Esta técnica se basa en pruebas de inferencia que se explican en este artículo. En pocas palabras, al inyectar un retraso de tiempo condicional en la consulta, el atacante puede hacer una pregunta de sí/no a la base de datos. Dependiendo de si la condición se verifica o no, se ejecutará el retardo de tiempo y la respuesta del servidor será anormalmente larga. Esto permitirá al atacante saber si la condición era verdadera o falsa. A continuación se muestra una referencia de sentencias condicionales básicas en cada sistema de base de datos.

DBMSSintaxisNotas
MySQLIF(conditionwhen_truewhen_false)Solo es válido cuando se usa en una declaración SQL. En el procedimiento almacenado, la sintaxis es idéntica a la de Oracle.
SQL ServerIF condition when_true [ELSE when_false]Solo se puede usar en un procedimiento almacenado o en una consulta apilada independiente.
OracleIF condition THEN when_true [ELSE when_falseEND IFSolo se puede usar en PL/SQL.

Como puede adivinar, los segmentos inyectados diferirán ligeramente según el propósito del ataque basado en el tiempo. Veamos ahora cómo se pueden realizar estos ataques en diferentes DBMS.

Ataque basado en el tiempo de MySQL

Inyectar un retraso de tiempo para este DBMS es bastante sencillo. Dado que SLEEP() y BENCHMARK() son funciones, pueden integrarse en cualquier instrucción SQL. El siguiente ejemplo muestra cómo un hacker podría identificar si un parámetro es vulnerable a la inyección SQL utilizando esta técnica (una respuesta lenta significaría que la aplicación utiliza una base de datos MySQL).

CONSULTA RESULTANTE (CON SLEEP MALICIOSO INYECTADO).

SELECT * FROM productos WHERE id=1-SLEEP(15)

CONSULTA RESULTANTE (CON BENCHMARK MALICIOSO INYECTADO).

SELECT * FROM productos WHERE id=1-BENCHMARK(100000000, rand())

El atacante también puede estar interesado en extraer alguna información o al menos verificar algunas suposiciones. Como se mencionó anteriormente, esto se puede hacer integrando el retraso de tiempo dentro de una declaración condicional. Una vez más, MySQL lo hace bastante fácil ya que proporciona una función IF(). El siguiente ejemplo muestra cómo es posible combinar pruebas de inferencia con técnicas basadas en el tiempo para verificar la versión de la base de datos.

CONSULTA RESULTANTE: ATAQUE BASADO EN EL TIEMPO PARA VERIFICAR LA VERSIÓN DE LA BASE DE DATOS.

SELECT * FROM productos WHERE id=1-IF(MID(VERSION(),1,1) = ‘5’, SLEEP(15), 0)

Si la respuesta del servidor tarda 15 segundos o más, podemos concluir que este servidor de base de datos ejecuta la versión 5.x de MySQL. El ejemplo presenta SLEEP(), pero podría adaptarse fácilmente para usar BENCHMARK().

Ataque a un SQL Server basado en el tiempo

Para inyectar retrasos de tiempo en una instrucción ejecutada por SQL Server, deberá utilizar consultas de pila. El proceso es en general bastante simple. Así es como un atacante podría determinar si un campo es vulnerable a la inyección SQL cuando la base de datos es SQL Server (un resultado positivo se indica mediante una respuesta lenta).

CONSULTA RESULTANTE (CON SLEEP MALICIOSO INYECTADO).

SELECT * FROM productos WHERE id=1; WAIT FOR DELAY ’00:00:15?

Mediante el uso de una declaración condicional, también sería posible extraer alguna información de la base de datos. En lugar de determinar la versión, veamos si el usuario es sa (administrador del sistema) utilizando una técnica basada en el tiempo.

CONSULTA RESULTANTE (VERIFICAR SI EL USUARIO ES SA).

SELECT * FROM products WHERE id=1; IF SYSTEM_USER=’sa’ WAIT FOR DELAY ’00:00:15?

Como nota al margen, debo mencionar que WAIT FOR TIME rara vez se usa, pero podría ayudar a eludir los filtros débiles de la lista negra solo verificando la popular instrucción WAIT FOR DELAY.

Ataque basado en el tiempo en Oracle

Con Oracle las cosas son un poco diferentes. Se puede usar la función SLEEP(), sin embargo, debe integrarse en un bloque PL/SQL:

EXECUTING SLEEP() IN ORACLE (EXECUTION SUSPENDED 15 SECONDS).

BEGIN DBMS_LOCK.SLEEP(15); END;

Dado que Oracle no admite consultas apiladas en consultas SQL dinámicas, la única forma de que la base de datos ejecute la declaración anterior sería encontrar una vulnerabilidad de inyección SQL en el código PL/SQL o en un bloque PL/SQL anónimo. Este tipo de situación es bastante rara y la mejor alternativa es inyectar una consulta pesada en lugar de llamar a la función SLEEP(). Si bien se considera la última opción en otros DBMS, es la única forma de lograr ataques de base de tiempo en consultas dinámicas en Oracle. Para obtener más información sobre este tema y ejemplos de consultas pesadas que podría usar en Oracle (o cualquier otro DBMS), consulte el artículo sobre consultas pesadas para ataques basados en el tiempo.

Ventajas y desventajas de los ataques basados en el tiempo

Una de las principales ventajas de esta técnica es que tiene poco o ningún impacto en los registros, especialmente en comparación con los ataques basados en errores. Sin embargo, en situaciones en las que se deben usar consultas pesadas o funciones intensivas de CPU como BENCHMARK() de MySQL, es muy probable que los administradores del sistema se den cuenta de que algo está pasando.

Otra cosa a considerar es la duración de la demora que inyecta. Esto es especialmente importante cuando se prueban aplicaciones web. La carga del servidor y la velocidad de la red pueden tener un gran impacto en el tiempo de respuesta. Debe pausar la consulta el tiempo suficiente para asegurarse de que estos factores inciertos no falsifiquen sus resultados. Por otro lado, desea que la demora sea lo suficientemente corta para probar la aplicación en un tiempo razonable. Esto se vuelve particularmente difícil cuando no se puede inyectar un retraso exacto.

Categorized in: