Skip to content
KitploitKITPLOIT
HerramientasExploitsBlog
Log in
Enviar
HerramientasExploitsBlog
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.

FeedsContactoPrivacidad© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
CVE-2026-88776 — Análisis técnico de CVE-2026-88776, un desbordamiento negativo de enteros previo a la autenticación en el analizador de registros Oracle TNS de nsppe de NetScaler que provoca una escritura fuera de límites y un fallo del motor de paquetes. | Kitploit
Herramientas/GitHubGitHub/scyrix-llc/cve-2026-88776
Forensia de MemoriaAnálisis de VulnerabilidadesExplotaciónIngeniería InversaSeguridad de RedesAnálisis de BinariosPapers e Investigación
GitHubscyrix-llc/cve-2026-88776

CVE-2026-88776

Análisis técnico de CVE-2026-88776, un desbordamiento negativo de enteros previo a la autenticación en el analizador de registros Oracle TNS de nsppe de NetScaler que provoca una escritura fuera de límites y un fallo del motor de paquetes.

Ver Repositorio
213hace 28 díasAú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-88776: NetScaler nsppe (Escritura OOB Pre-Auth)

Desbordamiento negativo de entero en el analizador de registros DataStream / Oracle TNS

Resumen

NetScaler puede balancear la carga de bases de datos Oracle. Apunte un vserver de tipo ORACLE hacia él y el motor de paquetes comenzará a hablar el propio protocolo Oracle TNS, analizando el tráfico de los clientes con un manejador integrado. Ese manejador mantiene una pequeña máquina de estados por conexión para recordar en qué punto se encuentra dentro de un registro TNS.

Uno de esos estados significa "estoy en medio de un registro, vienen más bytes". Cuando llega el siguiente segmento, el manejador lee su longitud y le resta 10, porque 10 bytes de cada segmento son cabecera.

Nadie se preguntó nunca qué ocurre si el segmento tiene menos de 10 bytes.

Envíe uno. Un segmento diminuto de 1 a 9 bytes entra en ese estado, la longitud se vuelve negativa y, como la longitud reside en un registro sin signo de 16 bits, no se vuelve negativa. Se desborda a algo enorme, hasta aproximadamente 64 KB. El manejador entonces hace memcpy alegremente de esa cantidad de datos desde su paquete hacia un búfer temporal fijo de 0x748 bytes en .bss. El motor no es PIE, así que la dirección que se está pisoteando nunca se mueve.

No hace falta iniciar sesión. Ni siquiera necesita una base de datos detrás del vserver, porque el propio appliance responde al handshake TNS. Todo el ataque es una única conversación TCP.

Ambas mitades se demostraron en vivo:

  • Dispare la longitud desbordada y el motor de paquetes muere con SIGSEGV, derribando el plano de datos del appliance durante aproximadamente un minuto. Determinista, repetible, bucleable.
  • Ajuste la longitud y obtiene la versión silenciosa. Los bytes del atacante aterrizan sobre las variables globales situadas junto al búfer temporal y el motor sigue funcionando. Eso es una primitiva de escritura, no solo un crash.

Causa raíz

La máquina de estados, y cómo dirigirla

El manejador almacena su estado por conexión en [pcb+0x15a]. La mayoría de los estados son aburridos. El que importa aquí es 0x1F4, que significa "en medio de un registro, esperando continuación", y se dirige una conexión hacia él usando nada más que bytes de protocolo ordinarios:

record type 6 -> deep-parser state 6 -> byte 0x03 (TTIFUN)
  -> state 0x126 -> TTC function byte 0x5e (OALL8)
  -> jump table 0x23589e0, index 0x59 -> writer at bfe27b:
       [pcb+0x15a] = 0x1F4

El siguiente paquete en esa conexión luego se despacha en 0x1F4, a través de bd49a7 hacia bd5362, y aterriza aquí:

bd5432: memset(0x30a7e60, 0, 0x748)    ; scratch region (ends 0x30a85a8)
bd5445: mov   rcx,[rbp-0x208]          ; inbound packet buffer
bd544c: movzx eax,WORD [rcx+0xf2]      ; u16 wire length of the segment
bd5453: add   eax,0xfffffff6           ; len = len - 10   <== THE UNDERFLOW
bd5456: mov   WORD [0x30a8476],ax      ; wrapped length PERSISTED to .bss
bd545d: movzx edx,ax                   ; memcpy length (1..9 -> 0xfff7..0xffff)
bd5460: mov   rsi,[rcx+0xe8]
bd5467: add   rsi,0xa                  ; src = payload + 10
bd546b: mov   edi,0x30a8075            ; dst = FIXED .bss global
bd5470: call  1b075e0                  ; memcpy: up to ~64 KB OOB write
bd5475: mov   BYTE [0x30a8478],1

Léelo como una frase. Toma la longitud del segmento. Réstale 10. Almacena el resultado, pásalo a memcpy, listo. En ningún momento nada pregunta si "longitud menos 10" sigue siendo un número que tenga sentido.

La protección que no está

Contamos cada referencia a ese campo de longitud en esta función. Treinta de ellas. Exactamente una es una comprobación, en bd4083, y lo único que hace es comparar con cero. Un segmento de longitud cero es rechazado. Cualquier otra longitud, incluida de 1 a 9, entra directamente en la resta.

El código cree claramente que la máquina de estados habrá entregado un registro suficientemente completo para cuando se ejecute el estado 0x1F4. La máquina de estados nunca prometió tal cosa. Un segmento truncado que llega como su propio paquete satisface todas las condiciones de despacho y aparece cinco bytes más corto.

La parte verdaderamente exasperante es que el proveedor conoce esta clase de error. En otra parte del mismísimo binario, sub_119c940 realiza la misma aritmética de longitud menos constante y la protege con cmp eax,0x3f9 / ja. El patrón seguro estaba justo ahí. Este sitio simplemente no lo usó.

Lo que golpeas cuando se desborda

El destino, 0x30a8075, vive dentro de una región de scratch de 0x748 bytes con solo 0x533 bytes de espacio legítimo delante de él. La copia desbordada irrumpe más allá de eso en los globales de DataStream y de negociación de al lado, con tus bytes. Y la longitud desbordada en sí se persiste en 0x30a8476, donde el código posterior la lee de vuelta y confía en ella. Esa es una segunda vía de corrupción, a un paso del memcpy.


El disparador

La configuración es una línea de configuración, un despliegue estándar de DataStream:

add lb vserver v ORACLE <ip> 1521

No se necesita backend. El appliance termina TNS por sí mismo y construye su propio paquete Accept, con la cadena de proveedor "Netscaler" y todo.

La conversación consta de cuatro pasos:

1. TNS Connect (version 0x13A)
     <- the appliance answers Resend(11), then Accept(2), 32 bytes, v0x139

2. one complete, benign TTC round-trip
     (some builds like to glue your runt onto the previous segment;
      this resets the segmentation so the runt lands alone)

3. the arming segment: a TNS Data packet whose declared length is
     actual + 32, carrying TTC bytes {03 5E} (TTIFUN / OALL8)
     -> the state machine latches [pcb+0x15a] = 0x1F4, mid-record

4. the runt: 1-9 bytes, sent as its own TCP segment
     -> passes the zero check, dispatches on 0x1F4
     -> length - 10 wraps
     -> memcpy(0x30a8075, payload+10, ~0xFFF6)
     -> the packet engine dies

Los pasos 1 a 3 son pura conversación. El paso 4 son cinco bytes.


Comportamiento de fallo observado

Esto se ha disparado dos veces en un appliance 14.1-73.30, misma máquina, misma compilación, dos ejecuciones independientes. En ambas ocasiones el motor de paquetes recibió SIGSEGV con un volcado de memoria coincidente, ns.log registró la señal 11 dentro de la ventana, y el plano de datos quedó inactivo durante el reinicio en caliente de ~60 segundos.

El control negativo pasó en ambas ejecuciones. Ejecute la conversación idéntica pero haga que el segmento final sea de 10 bytes coherentes y no ocurre nada. El motor lo procesa y continúa. La longitud reducida es la única variable que importa.

Descargar herramienta