Union inj loginbypass

De ICEnetX Docs

El SQL UNION Injection es un método alternativo de inyección SQL útil para saltarse sistemas de autentificación en ciertas circunstancias.

Tabla de contenidos

Nota

Se asume que el lector tiene conocimientos básicos de PHP, ASP y SQL. Y que conoce el principio de la inyección SQL. Referencias:

Introducción

Ya hace un tiempo mientras jugaba con unas aplicaciones se me ocurrió un método de salto de autentificación con inyección SQL del que nunca había leído ni escuchado. En la mayoría de los textos sobre SQL Injection se explica el famoso método de ' OR 1=1 -- para saltarse campos de login, es muy conocido, pero jamás he visto referencia alguna al método que voy a explicar en este texto. Es una técnica poco común pero útil bajo circunstancias en las que los métodos tradicionales no son funcionales.

Es una pequeña idea que se me ocurrió, no sé si sea completamente original, pero como no la he visto documentada en ninguna parte el objetivo de este texto es dar a conocer el método.

Método

El método tradicional para saltarse campos de login por medio de SQL Injection es muy conocido, aún así daré una breve explicación de como funciona el ataque. Más que nada es para diferenciar este método del que voy a presentar después, será una introducción muy superficial y cualquiera que no conosca SQL o SQL Injection debería de estudiarlo para comprender completamente.

Este es el código más común que se suele usar en ASP para hacer un sistema de login. La página recibe desde un formulario el "user" y "password", luego arma una consulta a la base de datos para ver si el usuario y la contraseña concuerdan con los datos registrados. De ser así el usuario iniciará sesión.

' Definimos variables y les damos los valores recibidos por el formulario de login
Dim user = Request.Form("user"), pass = Request.Form("password")

' Conectamos con la base de datos
set oConn=Server.CreateObject("ADODB.Connection")
oConn.Open ...

' Armamos la consulta y la ejecutamos
SQL = " SELECT user,pass FROM usuarios WHERE user = '" & user & "' AND password = '" & pass "' "
set rs = oConn.Execute(SQL)

' Si la consulta no regresa ningún resultado entonces...
If (RS.EOF = true) then
     ' Login incorrect
     ' ...
Else
     ' Login correcto
End If

Como podemos ver los parámetros user y passowrd recibidos desde el formulario no son validados, eso nos permite poder hacer una inyección para saltarnos el login. Si de user y password ingresamos el valor ' OR '1'='1 la consulta a la base de datos quedaría así:

SELECT user,pass FROM usuarios WHERE user = ' ' OR '1'='1' AND passord = ' ' OR '1'='1'

Entonces la consulta tomaría el primer registro en la tabla e iniciaríamos sesión con la cuenta del primer usuario registrado.

De todos modos, hay un montón de "programadores" que para querer evitarse esto, modifican la consulta y la forma del programa un poco (esto lo haré en PHP):

// Recibimos variables del formulario
$user = $_POST["user"];
$pass = $_POST["pass"];

// Armamos la consulta y luego la ejecutamos por medio de una función no definida aquí
$SQL = "SELECT pass FROM usuarios WHERE user = '$user';"
$Resultado = mssql_fetch_array( ejecutar_consulta($SQL) );

// Por medio de un if, compramos el resultado obtenido por la consulta y el password que proporcionó el usuario:
if ($Resutlado["pass"] == $pass ) {
      echo "autentificado"
} else {
      echo "no autentificado"}

Con este método el ' or '1'='1 no funcionaría, porque lo que se hace es tomar de la tabla el password del nombre de usuario proporcionado, y luego comparar ese password con el que ingresó el usuario en el formulario. Cuando mucha gente ve esto ya da por perdido el bypass y comienzan a hacer inyecciones extrañas, pero se puede hacer un bypass muy sencillo de la siguiente manera.

Como las variables no se validan ni se filtran, la inyección se pude realizar. Con esto provocaremos que la consulta no de ningún resultado, pero que regrese un valor de 1, y también vamos a ingresar "1" como contraseña. De este modo cuando el resultado de la consulta se compare con el password, dará un resultado verdadero y el usuario se autentificará.

El formulario de login quedaría de la siguiente manera:

user: asfsdf' UNION SELECT 1 as pass FROM usuarios --
pass: 1

UNION nos da la capacidad de poder realizar dos consultas en una misma sentencia; las filas recuperadas por la segunda sentencia son anexadas a las filas recuperadas por la primera sentencia.

Cuando la consulta se arme y se ejecute va a quedar así:

SELECT pass FROM usuarios WHERE user='asfsdf' UNION SELECT 1 as pass FROM usuarios --'

Como el usuario asfsdf no existe, esa primera parte no regresará ningun valor, luego se ejecutará el UNION donde se le asigna el valor 1 al campo pass. De esa manera el resultado de la consulta será igual a 1, y si ingresamos "1" de password entonces la condición será verdadera y nos veeremos autentificados. ¿Sencillo no?

Conclusion

Ya les mostré la idea básica de usar UNION para que las consultas regresen los resultados que nosotros queramos, para que después en sentencias IF y cosas por el estilo podamos obtener resultados verdaderos. No es muy conocido el método, pero sin embargo es útil e ingenioso. Espero que el texto les haya servido.

Herramientas personales