¿Qué es la inyección de código SQL?

Mediante la inyección de código SQL, los atacantes pueden ejecutar comandos no autorizados en la base de datos SQL de la víctima.

Objetivos de aprendizaje

Después de leer este artículo podrás:

  • Definir la inyección de código SQL
  • Explicar cómo funciona la inyección de código SQL
  • Más información acerca de cómo defenderse de la inyección de código SQL
  • Explorar los ataques de SQLI compuestos

Contenido relacionado


¿Quieres saber más?

Suscríbase a theNET, el resumen mensual de Cloudflare sobre las ideas más populares de Internet.

Revisa la política de privacidad de Cloudflare para saber más sobre cómo Cloudflare gestiona tus datos personales.

Copiar enlace del artículo

¿Qué es la inyección de código SQL (SQi)?

La inyección de lenguaje de consulta estructurada (SQL*) es una técnica de inyección de código utilizada para modificar o recuperar datos de bases de datos SQL. Mediante la inserción de sentencias SQL especializadas en un campo de entrada, un atacante es capaz de ejecutar comandos que permiten la recuperación de datos de la base de datos, la destrucción de datos confidenciales u otros comportamientos manipuladores.

Con la ejecución de comandos SQL adecuada, el usuario no autorizado es capaz de suplantar la identidad de un usuario con más privilegios, convertirse a sí mismo o a otros en administradores de la base de datos, manipular los datos existentes, modificar las transacciones y los balances, y recuperar o destruir todos los datos del servidor.

En la informática moderna, la inyección de código SQL suele producirse a través de Internet mediante el envío de consultas SQL maliciosas a un punto final de la API proporcionado por un sitio web o un servicio (más información al respecto más adelante). En su forma más grave, la inyección de código SQL puede permitir que un atacante consiga acceso raíz a una máquina, lo que le da el control total.

*SQL es un lenguaje de programación usado para mantener la mayoría de las bases de datos.

¿Cómo funciona un ataque de inyección de código SQL?

Imaginemos una sala de un tribunal en la que un hombre llamado Bob está siendo juzgado y está a punto de comparecer ante el juez. Al rellenar los papeles antes del juicio, Bob escribe su nombre como "Bob es libre de irse". Cuando el juez llega a su caso y lee en voz alta "Llamamos a Bob es libre de irse", el alguacil deja ir a Bob, porque eso es lo que ha dicho el juez.

Aunque hay variedades ligeramente diferentes de SQLi, la vulnerabilidad principal es esencialmente la misma: un campo de consulta SQL que se supone que está reservado para un tipo particular de datos, como un número, se pasa en su lugar información inesperada, como un comando. El comando, cuando se ejecuta, va más allá de los límites previstos, permitiendo un comportamiento potencialmente nefasto. Un campo de consulta se suele rellenar a partir de los datos introducidos en un formulario de una página web.

Veamos una simple comparación entre las sentencias SQL normales y las maliciosas:

Consulta SQL normal:

En esta consulta SQL normal, la cadena studentId se pasa a una sentencia SQL. El objetivo es buscar un alumno en la lista de estudiantes que coincida con el studentId introducido. Una vez encontrado, se devolverá el registro de ese estudiante. En pocas palabras, el comando dice "ve a buscar a este usuario y dame sus datos".

El código podría ser algo así:

studentId = getRequestString("studentId");
lookupStudent  = "SELECT * FROM students WHERE studentId = " + studentId
   

Si un estudiante introduce una identificación de estudiante de 117 en un formulario de la página web etiquetado como "Por favor, introduce tu número de identificación de estudiante

campo de formulario normal

la consulta SQL resultante tendrá el siguiente aspecto:

SELECT * FROM students WHERE studentId = 117;

Este comando devolverá el registro del estudiante concreto con un studentId, que es lo que el desarrollador que escribió la API espera que suceda.

Consulta de inyección de código SQL:

En este ejemplo, un atacante en vez de introducir un comando SQL o una lógica condicional en el campo de entrada, introduce un número de identificación de estudiante de:

Campo de formulario de ejemplo de inyección de código SQL

Donde normalmente la consulta buscaría en la tabla de la base de datos la ID correspondiente, ahora busca una ID o comprueba si 1 es igual a 1. Como es de esperar, la sentencia es siempre verdadera para cada estudiante de la columna, y como resultado, la base de datos devolverá todos los datos de la tabla de estudiantes al atacante que realiza la consulta.

SELECT * FROM students WHERE studentId = 117 OR 1=1;
Infografía sobre la inyección de código SQL

SQLi funciona al atacar a una interfaz de programación de aplicaciones o API vulnerable. En este caso, una API es la interfaz de software a través de la cual un servidor recibe y responde a las solicitudes.

Existen herramientas de uso común que permiten que un agente malicioso busque formularios automáticamente en un sitio web, y luego intente introducir varias consultas SQL, que pueden generar una respuesta que los desarrolladores del software del sitio web no pretendían con el fin de aprovechar una vulnerabilidad en la base de datos.

Las inyecciones de código SQL son fáciles de implementar y, curiosamente, también son bastante fáciles de prevenir si se aplican las prácticas de desarrollo adecuadas. La realidad es más turbia, ya que con plazos ajustados, desarrolladores inexpertos y código heredado suelen producirse prácticas de seguridad y una calidad de código variables. Un solo campo vulnerable en cualquier formulario o punto final de la API en un sitio web que tenga acceso a una base de datos puede ser suficiente para exponer una vulnerabilidad.

¿Cómo se evita un ataque de inyección de código SQL?

Hay varios métodos para reducir el riesgo de que se produzca una fuga de datos debido a una inyección de código SQL. Como práctica recomendada, se deben utilizar varias estrategias. Exploremos algunas de las implementaciones más comunes:

  • Uso de sentencias preparadas (con consultas parametrizadas): este método de sanear las entradas de la base de datos implica obligar a los desarrolladores a definir primero todo el código SQL y, a continuación, a pasar solo parámetros específicos a la consulta SQL; los datos introducidos reciben explícitamente un alcance limitado que no pueden sobrepasar. Esto permite que la base de datos distinga entre los datos que se introducen y el código que se va a ejecutar, independientemente del tipo de datos introducidos en el campo de entrada. Algunas bibliotecas de asignación objeto-relacional (ORM) se suelen utilizar para este propósito, ya que algunas versiones sanean las entradas de la base de datos automáticamente.
  • Eludir toda la entrada suministrada por el usuario: cuando se escribe SQL, algunos caracteres o palabras específicas tienen un significado particular. Por ejemplo, el carácter '*' significa "cualquiera" y la palabra "O" es un condicional. Para evitar que los usuarios introduzcan estos caracteres de forma accidental o malintencionada en una solicitud de la API a la base de datos, se puede eludir la entrada suministrada por el usuario. Eludir un carácter es la forma de decirle a la base de datos que no lo analice como un comando o condicional, sino que lo trate como una entrada literal.
  • Uso de procedimientos almacenados: aunque no es una estrategia de seguridad robusta por sí misma, los procedimientos almacenados pueden ayudar a limitar el riesgo asociado a la inyección de código SQL. Al limitar adecuadamente los permisos de la cuenta de la base de datos que ejecuta las consultas SQL, incluso el código de aplicación no robusto que es vulnerable a la inyección SQL carecerá de los permisos necesarios para manipular tablas de la base de datos no relacionadas. Los procedimientos almacenados también pueden comprobar el tipo de los parámetros de entrada, impidiendo que se introduzcan datos que incumplan el tipo que el campo está diseñado para recibir. En los casos en que las consultas estáticas sean insuficientes, los procedimientos almacenados suelen evitarse.
  • Aplicar el mínimo privilegio: como regla general, en todos los casos en los que un sitio web necesite utilizar SQL dinámico, es importante reducir la exposición a la inyección de código SQL limitando los permisos al ámbito más estrecho necesario para ejecutar la consulta pertinente. En su forma más obvia, esto significa que una cuenta administrativa no debería, en ningún caso, ejecutar comandos SQL como resultado de una llamada a la API de una solicitud no autorizada. Aunque los procedimientos almacenados se utilizan mejor para las consultas estáticas, la aplicación de los privilegios mínimos puede ayudar a reducir los riesgos de las consultas SQL dinámicas.

¿Qué es un ataque de inyección de código SQL compuesto?

Para evadir las medidas de seguridad, los atacantes más astutos a veces implementan ataques multivectoriales contra un sitio web objetivo. Aunque un solo ataque puede ser mitigado, también puede convertirse en el centro de atención de los administradores de bases de datos y de los equipos de seguridad de la información. Los ataques DDoS, el secuestro de DNS y otros métodos de interrupción se utilizan a veces como distracción para implementar ataques de inyección de código SQL de gran alcance. Por ello, una estrategia integral de mitigación de amenazas proporciona la más amplia protección. El firewall de aplicaciones web de Cloudflare, la mitigación de DDoS y la seguridad de DNS constan de elementos básicos de una estrategia de seguridad holística.