DataSunrise está patrocinando AWS re:Invent 2024 en Las Vegas, por favor visítenos en el stand #2158 de DataSunrise

How DataSunrise Security protects from SQL Injections-01

DataSunrise previene SQLI

En este artículo, te demostramos cómo DataSunrise previene las inyecciones SQL, que es uno de los instrumentos más populares de los hackers para violar aplicaciones web. Para mostrarte exactamente qué sucede cuando DataSunrise intercepta una consulta maliciosa, realizamos un test de penetración con un software dedicado.

Sqlmap

Aunque existen muchas aplicaciones diversas dedicadas a realizar evaluaciones automáticas de vulnerabilidad, utilizamos la utilidad Sqlmap en nuestro experimento actual. Este programa gratuito y de código abierto está escrito en lenguaje Python y es fácil de usar gracias a su interfaz de línea de comandos.

Según la descripción oficial, Sqlmap puede utilizar las siguientes técnicas de inyección SQL para pruebas de penetración:

Inyección ciega basada en booleanos

Sqlmap agrega al parámetro vulnerable en la consulta HTTP una cláusula SQL sintácticamente válida, que contiene una subconsulta SELECT o cualquier otra declaración SQL utilizada para recuperar la salida de la base de datos. Luego, Sqlmap compara cada respuesta HTTP con la solicitud original y obtiene la salida de la declaración inyectada, carácter por carácter.

Inyección ciega basada en tiempo

Sqlmap agrega al parámetro vulnerable una declaración sintácticamente válida que contiene una consulta que causa un retraso en el servidor de la base de datos por un cierto número de segundos. Luego la utilidad realiza una comparación entre el tiempo de respuesta original y el tiempo gastado en la respuesta de la consulta inyectada y luego infiere la salida de la declaración inyectada carácter por carácter.

Inyección basada en errores

Sqlmap agrega al parámetro vulnerable en la solicitud HTTP una cadena de declaración sintácticamente inválida que causa un mensaje de error específico de la base de datos. Luego, Sqlmap analiza la respuesta HTTP tratando de encontrar mensajes de error que contengan el código SQL inyectado y la salida de la subconsulta. Este método de inyección SQL solo funciona si el sistema de gestión de bases de datos (DBMS) está configurado para mostrar mensajes de error del servidor.

Inyección basada en consultas UNION

Sqlmap agrega al parámetro vulnerable en la solicitud HTTP una declaración SQL sintácticamente válida que comienza con UNION ALL SELECT. Este método es útil cuando la página de la aplicación web utiliza un bucle FOR o similar para pasar la salida de la declaración SELECT, por lo que cada línea de salida de la consulta se imprime en el contenido de la página. Sqlmap también es capaz de explotar vulnerabilidades de inyección SQL “parcial” basada en UNION. Estas vulnerabilidades ocurren cuando no se usa el ciclo FOR y solo se muestra la primera entrada de la salida de la consulta.

Inyección basada en consultas apiladas (piggybacking)

Si la aplicación web de destino soporta consultas apiladas, Sqlmap agrega al parámetro vulnerable en la consulta HTTP un carácter de punto y coma ( ; ) seguido de la declaración SQL a ser inyectada. Esta técnica se usa para realizar la inyección de declaraciones SQL distintas de SELECT (como declaraciones de definición de datos o manipulación de datos). Potencialmente, este método puede usarse para obtener acceso de lectura/escritura al sistema de archivos y ejecución de comandos del sistema operativo, dependiendo del servidor de bases de datos (DBMS) y los privilegios del usuario de la sesión.

Como puedes ver, Sqlmap es una herramienta poderosa capaz no solo de revelar vulnerabilidades, sino también de explotarlas con diversas técnicas de inyección SQL. Aquí tienes más sobre métodos de detección de inyección SQL.

Preparaciones para el testing

Para realizar nuestra demostración, necesitamos alguna aplicación de “prueba” susceptible a inyecciones SQL, así que utilizamos un servidor web simple escrito en Python. Este servidor está diseñado para mostrar información de la base de datos definida por los parámetros en la cadena de URL. Guardamos el código del servidor web en el archivo webserv_inj.py:

import re
import urllib.request
from http.server import BaseHTTPRequestHandler, HTTPServer
from urllib.parse import urlparse

import pyodbc

global dbconnection
global dbcursor

class InjectedServer(BaseHTTPRequestHandler):
    def do_GET(self):
        self.send_response(200)
        self.send_header("Content-type", "text/html charset=windows-1251")
        self.end_headers()
        o = urlparse(self.path)
        params = urllib.request.unquote(o.query)
        m = re.search("id=(?P[^;]+);name=(?P[^;]+)", params)
        id = m.group("id")
        name = m.group("name")
        dbconnection = pyodbc.connect(
            "Driver=PostgreSQL ODBC Driver(ANSI);Server=localhost;Port=54321;Database=test_db;Uid=postgres;Pwd=admin;UseServerSidePrepare=1")
        dbcursor = dbconnection.cursor()
        queryStr = "select * from injected_table where id = " + id + " and name = '" + name + "' order by id"
        dbcursor.execute(queryStr)
        result = dbcursor.fetchall()
        for row in result:
            self.wfile.write(bytes(str(row[0]), "utf-8"))
            self.wfile.write(bytes(str(row[1]), "utf-8"))
            self.wfile.write(bytes(str(row[2]), "utf-8"))

myServer = HTTPServer(("127.0.0.1", 6589), InjectedServer)
try:
    myServer.serve_forever()
except KeyboardInterrupt:
    pass
myServer.server_close()

Intentaremos vulnerar nuestro servidor web autodiseñado y obtener algunos datos de una base de datos PostgreSQL. Utilizamos el siguiente código para crear una nueva tabla de base de datos (“injected_table”) y llenarla con dos entradas:

CREATE TABLE injected_table
(
    id integer,
    name character varying(200),
    surname character varying(200)
)
INSERT INTO injected_table VALUES (1, Bob, Martin);
INSERT INTO injected_table VALUES (2, Denis, Morgan);

Así se ve la nueva tabla en PGAdmin

Así se ve la nueva tabla en PGAdmin

Luego iniciamos nuestro servidor ejecutando el siguiente comando a través del símbolo del sistema de Windows:

python webserv_inj.py

Para asegurarnos de que todo funciona como se espera, enviamos la siguiente consulta al servidor web a través del navegador:

http://127.0.0.1:6589/?id=2;name=Denis

Como resultado, el servidor web debería mostrar la entrada de la tabla “injected_table” con ID=2 y Nombre=Denis

Como resultado, el servidor web muestra la entrada de la tabla “injected_table” con ID=2 y Nombre=Denis

Probando el servidor web con Sqlmap

Ahora es el momento de verificar si nuestro servidor web puede ser objeto de una inyección SQL.

Primero, iniciamos el procedimiento de prueba de Sqlmap a través del símbolo del sistema:

python.exe sqlmap.py -u http://127.0.0.1:6589/?id=2;name=Denis

Cuando el proceso de prueba finaliza, veamos el archivo de registro de Sqlmap (se creó automáticamente y se guardó dentro de la carpeta “output”).

sqlmap identified the following injection point(s) with a total of 50 HTTP(s) requests:
---
Parameter: id (GET)
Type: boolean-based blind
Title: AND boolean-based blind - WHERE or HAVING clause
Payload: id=2;name=Denis' AND 8150=8150 AND 'lsHq'='lsHq

Type: AND/OR time-based blind
Title: PostgreSQL > 8.1 AND time-based blind
Payload: id=2;name=Denis' AND 9061=(SELECT 9061 FROM PG_SLEEP(5)) AND 'TLxE'='TLxE

Type: UNION query
Title: Generic UNION query (NULL) - 3 columns
Payload: id=2;name=Denis' UNION ALL SELECT NULL,NULL,(CHR(113)||
CHR(112)||CHR(120)||CHR(120)||CHR(113))||(CHR(88)||CHR(109)||CHR(66)||CHR(103)||CHR(114)||
CHR(69)||CHR(83)||CHR(119)||CHR(113)||CHR(98)||CHR(110)||CHR(73)||CHR(90)||CHR(83)||
CHR(90)||CHR(121)||CHR(113)||CHR(102)||CHR(85)||CHR(117)||CHR(107)||CHR(72)||CHR(78)||
CHR(101)||CHR(79)||CHR(90)||CHR(112)||CHR(120)||CHR(74)||CHR(106)||CHR(114)||CHR(105)||
CHR(85)||CHR(84)||CHR(71)||CHR(104)||CHR(71)||CHR(89)||CHR(75)||CHR(111))||(CHR(113)||
CHR(22)||CHR(107)||CHR(122)||CHR(113))-- -
---
back-end DBMS: PostgreSQL

Según lo muestra el registro, Sqlmap identificó con éxito la versión del DBMS (PostgreSQL) y determinó que el parámetro “ID” es vulnerable a la inyección SQL. Además, Sqlmap nos propuso tres variantes de declaraciones SQL que pueden ser utilizadas para realizar la inyección SQL (cadenas de “Payload”).

Configuraciones de reglas de seguridad de DataSunrise (sección de inyecciones SQL)

Configuraciones de reglas de seguridad de DataSunrise (sección de inyecciones SQL)

Y ahora verificaremos qué tan efectivamente DataSunrise puede proteger el servidor web vulnerable (y la base de datos de PostgreSQL asociada) contra inyecciones SQL.

Creé una regla de Seguridad de “inyección SQL” (consulta la guía del usuario de DataSunrise para más detalles) y eliminé los archivos que Sqlmap creó durante la primera prueba.

Ahora corremos el procedimiento de prueba de Sqlmap nuevamente (como se describió anteriormente) y cuando termina, verificamos el registro de la utilidad (nota que Sqlmap no pudo crear un archivo de registro, así que estamos usando su registro de línea de comandos).

Registro de Sqlmap

Según el registro, Sqlmap determinó que todos los parámetros probados no son vulnerables a la inyección SQL, incluido el parámetro “ID” que fue marcado anteriormente como inyectable.

Conclusión

Nuestro experimento prueba que el firewall de DataSunrise es altamente efectivo para prevenir inyecciones SQL. No obstante, para la mejor protección posible contra las amenazas más complejas, es necesario tomar medidas protectoras extendidas como las siguientes:

  • Seguir las mejores prácticas de la industria para desarrollar aplicaciones web resistentes a inyecciones SQL
  • Realizar ataques simulados de hackers en tus bases de datos y aplicaciones web para revelar posibles vulnerabilidades (los llamados “tests de penetración”)
  • Realizar auditorías continuas de la base de datos para detección de brechas y fugas de datos
  • Seguir las recomendaciones y guías del desarrollador sobre el uso seguro de bases de datos y software asociado.

DataSunrise soporta todas las bases de datos y almacenes de datos principales como Oracle, Exadata, IBM DB2, IBM Netezza, MySQL, MariaDB, Greenplum, Amazon Aurora, Amazon Redshift, Microsoft SQL Server, Azure SQL, Teradata y más. Te invitamos a descargar una prueba gratuita si deseas instalarlo en tus instalaciones. En caso de que seas un usuario en la nube y ejecutes tu base de datos en Amazon AWS o Microsoft Azure puedes obtenerlo desde el marketplace de AWS o el marketplace de Azure.

Siguiente

Métodos de Detección de Inyecciones SQL

Métodos de Detección de Inyecciones SQL

Más información

¿Necesita la ayuda de nuestro equipo de soporte?

Nuestros expertos estarán encantados de responder a sus preguntas.

Información general:
[email protected]
Servicio al Cliente y Soporte Técnico:
support.datasunrise.com
Consultas sobre Asociaciones y Alianzas:
[email protected]