¿Qué es y cómo opera una inyección SQL (SQLi)?

31/01/2023

Resumen

Al publicar una aplicación web sin tener presente las distintas medidas de seguridad que deben implementarse para su protección, ésta se encuentra expuesta a los usuarios maliciosos que buscarán aprovechar la brecha de seguridad generada por error u omisión con distintos objetivos: obtener información, instalar software malicioso, tomar el control del servidor para hacer uso de sus recursos, para distribuir software malicioso o como punto de entrada a la red de la organización que lo gestiona.

Uno de los elementos que más se descuidan por parte del equipo de desarrollo se encuentra relacionado con la ausencia o fallo en la validación de entradas proporcionadas por los usuarios, ya que involucra a las consultas realizadas hacia la base de datos, permitiendo ejecutar sentencias fuera de la funcionalidad implementada para la aplicación web. Lo anterior, se conoce como inyección SQL y representa una brecha de seguridad ya que los usuarios maliciosos pueden aprovechar para insertar o consultar datos que de entrada no debería poder realizarse.

Las inyecciones SQL son un problema recurrente en las aplicaciones web y se encuentra entre los elementos de fallo más reportados, ocupando junto con otros tipos de inyección, uno de los primeros lugares de manera recurrente en el Top Ten de OWASP.

Palabras clave: SQL, query, inyección, seguridad, validación, sanitización.

¿Qué es la inyección SQL?

Un ataque de inyección SQL consiste en la inserción o “inyección” de una consulta SQL a través de los datos de entrada del cliente a la aplicación, por ejemplo, los campos de un formulario. La inyección sucede porque estas entradas que el usuario debe proporcionar, no son validadas ni sanitizadas correctamente, es decir, se confía en que el usuario proporcionará datos en el dominio de lo que se considera válido para la aplicación web.

Si la inyección de la sentencia SQL es exitosa, se podrán consultar registros, insertar datos, modificar datos existentes, dar de alta usuarios o incluso hacer llamadas a sistema operativo para ejecutar comandos con los privilegios del usuario que en ese momento se encuentra conectado al Sistema Manejador de Bases de Datos.

Las inyecciones SQL no requieren que un usuario malicioso envíe un correo o publique un enlace en una aplicación web, ni convencer al usuario para dar clic en el enlace, este ataque puede llevarse a cabo directamente en contra de la aplicación web.

Un ejemplo de inyección SQL es el siguiente: en una aplicación web se tiene un formulario de consulta de los productos en existencia que no valida adecuadamente los datos proporcionados por los usuarios. Cuando la consulta es exitosa, se muestra un mensaje con los datos proporcionados.

El problema de la inyección ocurre de esta manera: si los datos proporcionados por el usuario no son adecuadamente validados y sanitizados, entonces los campos del formulario son susceptibles de sufrir una inyección SQL. De esta manera, un usuario malicioso puede comenzar a realizar pruebas sobre las posibles sentencias que se podrían ejecutar proporcionando una salida satisfactoria.

Así, la consulta inicial para la aplicación web es la siguiente:

SELECT * FROM productos where nombre like ’entrada_del_usuario’

El usuario malicioso buscará provocar que la aplicación web muestre un mensaje de error indicando algunas características como: línea de código en la que sucede el error, nombre del manejador de bases de datos, nombre del o los campos que se ven afectados por la inyección, datos almacenados entre otros valores.

Una consulta válida, sería la siguiente:

SELECT * FROM productos where nombre like ’playera’

Cuando el usuario malicioso modifica la consulta, se modifican los resultados mostrados, por ejemplo, en lugar de la palabra “playera”, se usará “ ‘ or 1=1 --”, lo que altera el comportamiento de la consulta:

SELECT * FROM productos where nombre like ’’ or 1=1 --’

La modificación anterior no está consultando un nombre en específico, sino que busca obtener todos los registros de la columna nombre de la tabla productos para ser mostrado como parte de los resultados de la consulta.

Esta información, proporcionada de manera no intencional por parte de la aplicación, es de utilidad para los usuarios maliciosos, ya que pueden orientar sus esfuerzos a intentar y refinar la ejecución de sentencias SQL hasta que una de ellas sea exitosa y obtenga el resultado deseado. O bien, si no se despliega en pantalla el resultado esperado, buscará otra manera de corroborar que la ejecución de sentencias se está llevando a cabo.

Este problema cobra mayor importancia debido a que la situación anterior hoy en día puede automatizarse con el uso de distintas herramientas que permiten automatizar el número de intentos y combinaciones para las sentencias SQL, lo que reduce drásticamente el tiempo dedicado a esta actividad.

Métodos para realizar el ataque

Según el portal de Imperva, los ataques de inyección SQL pueden categorizarse en tres métodos distintos que son empleados para acceder a los datos almacenados, así como el daño potencial que pueden provocar:

  • SQLi en banda (clásico)

En este tipo de inyección, el usuario malicioso emplea el mismo canal de comunicación para ejecutar el ataque y recibir los resultados. Es el más simple y eficiente. Aquí se presentan dos variantes: el basado en errores y el basado en unión.

Para el caso de la inyección basada en errores, el usuario malicioso realiza diferentes acciones para desplegar errores y así poder obtener información sobre la estructura de la base de datos.

Mientras que la inyección basada en unión hace uso del operador UNION del lenguaje SQL, buscando concatenar varias sentencias SQL para obtener el resultado deseado.

  • SQLi inferencial (blind)

El usuario malicioso envía distintas sentencias SQL y observa la respuesta y el comportamiento del servidor, sobre todo porque a diferencia del SQLi en banda, la respuesta no se despliega directamente en pantalla. Este tipo se subdivide a su vez en dos variantes: booleano y basado en tiempo.

Para el caso de la inyección booleana, se solicita que se realice una sentencia SQL, la respuesta de la aplicación depende de si la sentencia es verdadera o falsa, así la información en la respuesta de la petición HTTP realizada se modificará o permanecerá sin cambios.

Para la inyección basada en tiempo, la sentencia proporcionada implica que el manejador de bases de datos espera cierta cantidad de tiempo antes de continuar con la ejecución. Así el usuario malicioso podrá determinar si la respuesta HTTP tarda la cantidad de tiempo solicitada en responder o no.

  • SQLi fuera de banda

Sucede cuando el usuario malicioso no puede emplear el mismo canal de comunicación para lanzar el ataque y recibir los resultados, o cuando un servidor es demasiado lento o inestable para realizar estas acciones. Se hace uso de la capacidad del servidor para crear solicitudes DNS o HTTP para transferir los datos.

Mitigación

Existen distintas medidas que se pueden implementar para evitar que la inyección SQL afecte el funcionamiento y seguridad de las aplicaciones web y resultan más efectivas si se emplean en conjunto.

Se puede comenzar por lo más sencillo: revisar cómo falla la aplicación. Es necesario pensar en el fallo seguro, de tal manera que si se produce un error, éste exponga la menor cantidad posible de información a los usuarios maliciosos. Esto no evitará la inyección, pero sí volverá más complicada la realización de una inyección exitosa, aumentando el tiempo que debe dedicarse a ella.

Siempre es buena idea realizar pruebas antes de liberar la aplicación en el entorno productivo. Existen distintos tipos de pruebas: unitarias, de carga, de usabilidad, entre otras, sin embargo, en este caso es importante realizar aquellas relativas a la seguridad: tanto de caja negra como de caja blanca (en la medida de lo posible). Las pruebas pueden ser manuales o automatizadas y seguir una metodología.

Para el caso de las herramientas automatizadas, se puede hacer uso de herramientas que busquen vulnerabilidades específicamente en aplicaciones web, las cuales también proporcionan recomendaciones de remediación, así como ejemplos de implementación.

La mayoría de los lenguajes de programación, así como los frameworks para el desarrollo de aplicaciones que existen, cuentan con bibliotecas propias o de terceros que permiten implementar medidas como la validación y sanitización de las entradas proporcionadas, buscando facilitar esta tarea para el equipo de desarrollo. Por ejemplo, para el caso del lenguaje PHP existe un apartado completo de su documentación oficial dedicado al filtrado.

Otro de los recursos más sencillos de implementar es la parametrización de consultas, lo que permite establecer valores predefinidos que serán aceptados por la aplicación para la realización de consultas SQL hacia el manejador de bases de datos. También puede hacerse uso de procedimientos almacenados, lo que permite restringir las acciones que se realizan en el manejador de bases de datos.

Un elemento importante que debe tenerse presente, es la correcta asignación e implementación de usuarios y privilegios, empleando el principio del menor privilegio, lo que restringirá las acciones que se pueden realizar en el manejador de bases de datos, el sistema operativo y la aplicación web.

Una medida adicional de seguridad que se puede implementar, es el uso de un firewall de aplicaciones web (WAF, por sus siglas en inglés), el cual cuenta con una serie de reglas de filtrado específicas para los ataques que buscan llevar a cabo inyección de consultas SQL. Es importante notar que la implementación de este tipo de soluciones no elimina la necesidad de que el código fuente de la aplicación web lleve a cabo la validación y sanitización adecuada de las entradas proporcionadas.

Conclusión

Es importante mantenerse actualizado sobre los peligros a los que se enfrentan las aplicaciones web. También es necesario identificar las herramientas que existen para ayudar a encontrarlos y así poder mejorar el nivel de seguridad.

Siempre es mejor que los posibles fallos de seguridad sean encontrados por el mismo equipo de trabajo responsable de la implementación de la aplicación, de manera que se puedan llevar a cabo medidas correctivas, que por uno o varios usuarios maliciosos que puedan abusar de ella, sobre todo cuando la aplicación ya se encuentra en el entorno productivo.

No hay que dejar de lado otros componentes que también se ven involucrados en el funcionamiento de la aplicación, como el servidor de aplicaciones, módulos y bibliotecas de terceros de los que se hace uso, así como otros elementos como los dispositivos y navegadores empleados por los usuarios para visitar y hacer uso de ella.

Finalmente, es una buena práctica documentar las implementaciones de seguridad realizadas, así como los posibles problemas que se presenten, ya que serán de ayuda para la mejora constante en el mantenimiento y actualización de la aplicación.

 

Referencias

 

Anónimo. (s.f.). Data filtering. Obtenido de: https://www.php.net/manual/en/book.filter.php

Anónimo. (s.f.). SQL Injection Prevention Cheat Sheet. Obtenido de:https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html

Anónimo. (s.f.). SQL (Structured query language) Injection. Obtenido de: https://www.imperva.com/learn/application-security/sql-injection-sqli/

Kingthorin. (s.f.). SQL Injection. Obtenido de: https://owasp.org/www-community/attacks/SQL_Injection

Kuhn, A. (2004). Vulnerability Testing Techniques for Web Application Programmers. Obtenido de: https://www.giac.org/paper/gsec/4177/vulnerability-testing-techniques-web-application-programmers/106695

 

La Coordinación de Seguridad de la Información/UNAM-CERT agradece el apoyo en la elaboración y revisión de este documento a:

Ing. Angie Aguilar Domínguez (angie dot aguilar at cert dot unam dot mx)

Para mayor información acerca de este documento contactar a:

UNAM-CERT: Equipo de Respuesta a Incidentes UNAM

Coordinación de Seguridad de la Información

Dirección General de Cómputo y Tecnologías de Información y Comunicación

Universidad Nacional Autónoma de México