Volver |

SQL Injection

Introducción

La inyección de código consiste en aprovechar un bug que ocurre cuando una aplicación envía datos sin validar a un intérprete.

SQL Injection o Inyección de SQL en particular se refiere a un ataque de inyección en el cual un atacante puede ejecutar código SQL en el servidor de base de datos de una aplicación web.

Como este ataque puede realizarse sobre cualquier aplicación que tenga una base de datos SQL, esta vulnerabilidad es una de las más viejas y peligrosas conocidas.

De hecho según OWASP la vulnerabilidad a inyección de SQL (SQLi) es la más común en las aplicaciones web como se puede ver en https://www.owasp.org/images/f/f8/OWASP_Top_10_-_2013.pdf y en https://www.owasp.org/images/b/b0/OWASP_Top_10_2017_RC2_Final.pdf en donde aparece como una explotación fácil pero de impacto severo.

A pesar que su prevención es súper conocida siguen ocurriendo casos en que las aplicaciones siguen siendo vulnerables.

 

Funcionamiento

El atacante envía ataques con cadenas simples de texto, de las cuales explotan la sintaxis del intérprete a vulnerar.

Para ejecutar consultas maliciosas en el servidor de la base de datos, el atacante primero debe encontrar una entrada de datos en la aplicación web que sea incluido dentro de una consulta SQL.

Si luego, la página web incluye el input del usuario directamente en una consulta SQL que va a ser ejecutada por el motor de base de datos, un atacante podría incluir código SQL en ese input y explotar la vulnerabilidad.

 

A continuación se brinda un ejemplo para lograr una mayor comprensión. 

 

Hagamos de cuenta que estamos encargados de desarrollar el login de una aplicación web. Entonces en primer lugar, obtenemos los datos del usuario y de la contraseña que nos pasan.

$user = $_POST['username'];

$pass = $_POST['password'];

 

Imaginemos que la consulta SQL que valida al usuario es de la siguiente manera

$consulta = "SELECT id, nombre FROM usuarios WHERE nombre='" . $user . "' AND password='" . $pass . "'";

Por último ejecutamos la consulta.

bd.ejecutar($consulta);

El código propuesto va a funcionar y en condiciones normales no tendría problemas. Pero si lo analizamos desde el punto de vista de la seguridad, el mismo es vulnerable ya que en ningún momento se filtran las entradas y un atancante podría alterar la sentencia SQL que ejecuta el servidor de base de datos.

Ahora pensemos como atancante un input simple que nos permita alterar la sentencia. Podríamos poner en la contraseña lo siguiente:

pass' OR '1'='1

Este parámetro producitía que la consulta ejecutara contra la base de datos quede:

SELECT id, nombre FROM usuarios WHERE nombre='user' AND password='pass' OR '1'='1'

Analicemos esto lógicamente, suongamos que el motor de base de datos, está analizando el usuario con nombre 'user' y que la contraseña no es 'pass', entonces la condición del WHERE nos va a queda: 

TRUE AND FALSE OR TRUE 

Resolviendo lógicamente (primero resolviendo los AND y luego los OR), esto es igual a TRUE. 

Entonces, esta sentencia, una vez ejecutada en el servidor, producirá un bypass en la autenticación, permitiendo al atacante loguearse como (probablemente) el primer usuario de la tabla usuarios, el cual usualmente es un usuario administrador.

Defensa

Para defender nuestro sistema de un ataque de inyección, en general la solución comienza en saber validar cualquier posible vía de entrada de datos y termina en limitar el acceso a los recursos de nuestro sistema.

En el caso de SQL Injection la forma de defendernos es validar todo aquello que forma parte (o podría formar parte) de una consulta SQL que será ejecutada por el motor de base de datos y a su vez limitar las posibles acciones que un usuario puede hacer en la base de datos (el recurso que deseamos proteger).

Validar la entrada de datos

Significa: asegurar de que todo lo que vaya a formar parte de una consulta a ser ejecutada por el motor de base de datos sea lo esperado: filtrar caracteres inválidos, llamadas a funciones o procedimientos almacenados, etc.

Limitar acceso a los recursos

Es posible que un usuario administrador del motor de base de datos sea necesario para tener el control absoluto de todo el sistema que conforma el motor y de todas las bases de datos. Sin embargo, para un sistema web no es necesaria que el usuario vaya a necesitar ejecutar cosas más complicadas que consultas de selección, inserción o actualización, e incluso es posible que sólo lo haga en ciertas tablas de una base de datos.

Por esto, es necesario crear un usuario dedicado que sólo pueda acceder a una única base de datos y que sobre la misma sólo pueda ejecutar las consultas que en condiciones normales le corresponde, a su vez, que sólo pueda trabajar sobre las tablas que le competen de acuerdo a su rol.

Recomendaciones y buenas prácticas

  • Validar datos tanto en el cliente (recomendable) como en el servidor (obligatorio).

  • No mostrar mensajes de error que puedan dar información de la implementación ni de tecnología utilizada.

  • Impedir accesos a recursos privados.

  • Filtrar caracteres especiales en formularios (impedir Script Injection).

  • Crear usuarios en la base de datos (no usar “root”).

  • Escapar caracteres especiales en consultas de base de datos o hacer uso de sentencias preparadas.

  • Almacenamiento cifrado de información sensible.

  • Crear vistas y limitar acciones de los usuarios de la base de datos.

  • Evitar la posibilidad de ejecutar múltiples consultas en una consulta a base de datos.

  • Hacer backups (ningún sistema es totalmente seguro).

  • Mantener en logs todas las acciones de los usuarios.

  • Habilitar sólo dominios conocidos al ofrecer servicios (tener en cuenta “cross-domain access policy”).

  • Nunca usar configuración por defecto (de servidor, de base de datos, etc.).

Enlaces

Concatenar String en diferentes motores de bases de datos

SQLite ||

Oracle CONCAT(string1, string2) or ||

MySQL CONCAT(string1, string2, string3...) or || if PIPES_AS_CONCAT enabled

Postgres CONCAT(string1, string2, string3...) or ||

Microsoft SQL Server 2012+ CONCAT(string1, string2, string3...) or +

Microsoft Access +

 

Fuente: https://stackoverflow.com/a/37811056/5258711

Herramienta para automatizar ataques

SQLmap

Para descargar: https://github.com/sqlmapproject/sqlmap

Parar usar: python3 sqlmap.py -u "url" --batch

En este artículo participaron: