Ataques
Cómo evadir manualmente los filtros de SQLi

Analista de seguridad
Updated
8 min
Entre las vulnerabilidades más recurrentes están las fallas de inyección, no en vano ocupan el primer lugar en la lista OWASP Top Ten. Este tipo de vulnerabilidad puede afectar toda tu seguridad e infraestructura; casi cualquier entrada puede ser un vector de inyección y todas deben controlarse. Aquí, la SQL injection juega un papel importante, no solo por el riesgo de filtración de información, sino también porque puede derivar en ejecución remota de comandos o en acceso a la red interna.
Esta vulnerabilidad ocurre cuando un atacante inyecta código en las consultas que la aplicación hace a la base de datos, interfiriendo con su funcionamiento normal. Esto sucede porque los desarrolladores no validaron correctamente la entrada de datos ni aplicaron las mejores prácticas para recuperar datos de la base de datos. Te doy un ejemplo; imagina este fragmento de código:
Código común vulnerable a SQLi.
Aquí creé el código típico de una página de inicio de sesión que verifica el usuario y la contraseña. Las variables se introducen mediante una solicitud POST y no hay validación de entrada. Un atacante podría simplemente usar el conocido payload de SQLi 1' or '1'='1y burlar el formulario de inicio de sesión. Pero si filtro algunos caracteres como la OR keyword o la single quote, ¿estaría todo bien? No tanto.
Laboratorio de bypass de SQLi
Para configurar nuestro laboratorio, vamos a usar Vagrant de Hashicorp’s; los archivos fuente están abajo. Crea una carpeta llamadaSQLiy guarda ahí el Vagrantfile.
Configurando el laboratorio
Vagrantfile
Luego, ejecuta el entorno usando
vagrant up
Esto creará una máquina Linux conLAMP instalado y configurado. En este punto, ya tenemos todo lo necesario y estamos listos para lanzar un ataque.
Ahora podemos configurar nuestra máquina atacante. Aquí usamos Kali Linux también con Vagrant, pero puedes usar el sistema operativo que prefieras.
Estas son las herramientas que vamos a usar:
Si usas Kali, todo esto ya viene instalado por defecto.
Ya estamos listos para empezar.
Enumerando nuestro servidor
Primero, necesitamos revisar los puertos del servidor. Podemos usar nmap o ncat para hacerlo.
Escaneo de puertos
Salida de nmap
Nc
Nuestro servidor corre Apache en el puerto 80. Luego, usando Dirbuster, podemos buscar directorios en el servidor web.
Dirbuster
Como podemos ver, hay un sitio de administración al que no tenemos acceso y un sitio normal donde están nuestros casos de prueba.
Ataques de bypass de SQLi
Hay tres casos de prueba; el primero es el más simple. Filtra las palabras clave OR|AND y también el carácter de espacio.
Primer filtro de SQLi
El nombre de usuario no es inyectable porque usa una declaración preparada (esto se hizo así para mostrar la forma correcta de hacer consultas). Si introducimos cualquiera de esos caracteres en la consulta, debería responder con una alerta Wrong
Para evadir esto, necesitamos sustituir esas palabras clave: la palabra clave ORpor el carácter de doble barra vertical ||, y la palabra clave AAND por el carácter de doble ampersand &&. En este caso, debemos codificarlo en URL debido al tipo de contenido de la aplicación web, lo que da como resultado %26%26. Finalmente, el carácter de espacio puede evadirse usando varias sustituciones, como las siguientes:
El comentario de bloque
/**/El carácter ascii %09 de tabulación horizontal
El carácter ascii %0a de nueva línea
El carácter ascii %0b de tabulación vertical
El carácter ascii %0c de salto de página
El carácter ascii %0d de retorno de carro
Así, nuestro conocido payload de SQLi cambiará a algo como '/**/||/**/1=1#
Primer bypass
El siguiente caso de prueba es un poco más complicado: filtra los mismos caracteres que antes más la comilla simple. Además, elimina el uso de la declaración preparada en la variable de usuario, pero también valida la comilla simple.
Second SQLi filter
Entonces, ¿qué podemos hacer para evadir esto? El carácter de barra invertida \ es un carácter de escape especial usado para indicar otros caracteres especiales dentro de cadenas de texto. Esto nos resulta útil porque, si inyectamos ese carácter en el campo de usuario, la comilla simple que le sigue actuará como un carácter literal, y la cadena del nombre de usuario terminará justo al lado del campo de contraseña:
Ejemplo de barra invertida
Es solo cuestión de inyectar nuestro código ahí; el payload en el usuario será \, y en el campo de contraseña será /**/||/**/1=1/**/--
Segundo bypass
El último ejemplo combina todo lo anterior y agrega más filtros al código; se trata de un tipo distinto de vulnerabilidad, porque vamos a evadir el filtro dentro de una palabra clave ORDER BY.
Tercer filtro SQLi
Aquí casi no podemos usar palabras clave ni funciones, y el union select tampoco funcionará. Para recolectar datos de la base de datos a partir de una palabra clave ORDER BY, necesitamos usar una SQLi basada en errores o una basada en tiempo.
Entonces, la primera inyección servirá para probar la vulnerabilidad; inyectemos una SQLi simple basada en errores donde, si es verdadera, ordenará los elementos usando el id, y si es falsa, los ordenará usando el name:
?by=if(false,id,name)?by=if(true,id,name)
Ahora, agreguemos otra capa. Queremos extraer información de esto, y para lograrlo necesitamos hacer algunas consultas. En este ejemplo, obtendremos la contraseña del usuario guest(si quieres obtener la contraseña de admin, deberías intentarlo tú mismo). Como los caracteres =, comilla simple y comilla doble están filtrados, necesitamos otra forma de obtener la información del usuario que queremos. Aquí tenemos el operadorIN y la funciónCHAR. El operadorIN nos permite especificar múltiples valores en una cláusula WHERE, aunque también podemos usar uno solo si queremos, y la función CHAR devuelve el carácter ASCII correspondiente a un número. Usando ambos elementos, una consulta para la contraseña de guest sería algo así:
Consulta de la contraseña de guest
Aquí, la cadena guestes la combinación de los caracteres ASCII 103,117,101,115,116. Ahora, la función MID nos ayudará a extraer caracteres de esa consulta y obtener la contraseña carácter por carácter. Esta consulta obtendrá el primer carácter de la contraseña:
Caracter de la contraseña de guest
Luego, necesitamos compararlo con otro carácter; aquí volveremos a usar IN y CHAR.
Comparación de la contraseña de guest
Finalmente, colocamos nuestra consulta dentro de la función IF anterior y reemplazamos los espacios con el comentario de bloque:
Con esto, podemos obtener la contraseña de guest usando la función ORDER BY. Hacer esto manualmente tomaría bastante tiempo, así que automaticémoslo con Python. Lo primero que necesitamos es una función que haga nuestras consultas y devuelva la respuesta:
Función para hacer la solicitud
Luego, necesitamos iterar por cada elemento de la contraseña y por cada carácter ASCII:
Consulta iterativa
Y finalmente, consultamos si la lista está ordenada por id:
Eso es todo: crea el exploit, ejecútalo y espera el resultado. Esto podría hacerse con cualquier otra consulta, por ejemplo, para obtener el hash de la contraseña de un usuario de MySQL.
Solución
Lo primero que debe hacer alguien con este problema es implementar declaraciones preparadas; no hay forma de evitarlo. Las inyecciones pueden ocurrir en casi cualquier proveedor de bases de datos (si no en todos). Con estas declaraciones, el software tendrá consultas de datos más robustas y se descartará el uso de consultas dinámicas.
El siguiente paso es aplicar listas blancas para validar la entrada del usuario. Cuando los desarrolladores usan filtrado por lista negra, como en los ejemplos anteriores, existe el riesgo de pasar por alto algún parámetro que permita la inyección. Las listas blancas son un mejor enfoque porque solo permiten lo que está en ellas y nada más.
Finalmente, está la implementación del principio de mínimo privilegio. Me he encontrado con varias bases de datos que ejecutan consultas usando el usuario root; es mejor usar usuarios limitados en nuestras aplicaciones, porque esto limita el rango de acción de los atacantes que, en el peor de los casos, logran acceder a la base de datos.
Si quieres más información sobre las protecciones contra SQLi, puedes consultar OWASP o nuestra base de datos.
Empieza ya con la solución de ASPM de Fluid Attacks
Suscríbete a nuestro boletín
Mantente al día sobre nuestros próximos eventos y los últimos blog posts, advisories y otros recursos interesantes.
Otros posts


























