Las actualizaciones de seguridad publicadas por Microsoft el 11 de abril de 2023 abordaron más de 90 vulnerabilidades individuales. Destacó especialmente el CVE-2023-21554, llamado QueueJumper, una vulnerabilidad de ejecución remota de código que afectaba al servicio Microsoft Message Queueing (MSMQ). MSMQ es un componente opcional de Windows que permite a las aplicaciones intercambiar mensajes a través de colas de mensajes a las que se puede acceder tanto local como remotamente. Este análisis se realizó en colaboración con los equipos de Randori® y X-Force Adversary Services, por Valentina Palmiotti, Fabius Watson y Aaron Portnoy.
Inicialmente, las siguientes cualidades de CVE-2023-21554 llamaron la atención:
Manténgase al día sobre las tendencias más importantes e intrigantes del sector en materia de IA, automatización, datos y mucho más con el boletín Think. Consulte la Declaración de privacidad de IBM.
Para determinar cómo detectar la presencia de MSMQ, se configuró un sistema de prueba con el componente en un entorno de laboratorio. Al conectarse al endpoint de MSMQ en el puerto 1801, el servidor no respondió con ningún dato. Se podría suponer que el servidor no responderá sin recibir datos razonablemente formados. Para entender cómo mantener una conversación con el endpoint, era necesario inspeccionar más a fondo el código subyacente.
Por el aviso, no está claro inmediatamente qué binario fue parcheado. El primer paso para identificar el código modificado fue descargar el archivo de actualización. Esto se logró buscando KB5025224 en el catálogo de actualizaciones de Microsoft.
Resultados de búsqueda del catálogo de actualizaciones de Microsoft para KB5025224
En concreto, el archivo de actualización acumulativa
windows10.0-kb5025224-x64_3522b1b562ed44bc949541dd1c7d08e1e967d925.msu
para Windows 11 para sistemas basados en x86 se recuperó.
El extractor 7-Zip se utilizaba para descomprimir el contenido del archivo MSU y los archivos CAB que contenía. La búsqueda de la cadena "msmq" en todos los archivos de las carpetas resultantes produjo el archivo índice de contenedor,
Windows11.0-KB5025239-x64/express.psf.cix.xml,
que incluía la siguiente entrada:
<File id="21296" name="amd64_microsoft-windows-msmq-queuemanager-core_31bf3856ad364e35_10.0.22621.1555_none_5f975f8fdb349517\f\mqqm.dll" length="34811" time="133245266510000000" attr="128">
Esta entrada hace referencia a
Para identificar los cambios realizados entre las versiones parcheadas y no parcheadas del archivoMQQM.dll1.00
Resultados de BinDiff entre archivos MQQM.dll parcheados y no parcheados
El análisis de estas funciones mediante el descompilador Hex-Rays reveló que los símbolos de la versión parcheada contenían nombres de funciones detallados que parecen hacer referencia a los identificadores de vulnerabilidad del Centro de Investigación de Seguridad de Microsoft (MSRC):
Símbolos de indicador de característica dentro de MQQM.dll
Tras un análisis más detallado, los símbolos que contienen los números de caso del MSRC corresponden a indicadoresde características para correcciones de vulnerabilidades. Los indicadores de características son un componente de Windows que alterna varias funcionalidades y experimentos. En este caso, la característica descubierta es en realidad un parche para una vulnerabilidad. Si la característica está habilitada, se ejecuta la ruta del código segura y parcheada. De lo contrario, se ejecuta la ruta del código original sin parches.
Fragmento de código descompilado que muestra el indicador de característica para la corrección de la vulnerabilidad
Había una comprobación de indicadores de características para cada una de las vulnerabilidades que comprendían CVE-2023-21554 tanto en el componente de usuario como en el del núcleo. El análisis de los binarios restantes contenidos en el paquete de actualización de seguridad reveló que también se introdujeron indicadores de característica para la mayoría o para todas las vulnerabilidades corregidas en el Patch Tuesday de abril de 2023.
Las referencias cruzadas de estas banderas nos ayudaron a identificar rápidamente las ubicaciones de los códigos parcheados. En particular, los cambios dentro de relacionados con la marca ixes MSRC76146_MSMQ_OOBRWF
La comprobación de esta característica se produce ocho veces dentro de la función. A continuación se muestra una de estas verificaciones:
Fragmento de código descompilado que muestra la corrección de la vulnerabilidad
En el fragmento de código descompilado que se muestra arriba, la ruta de código parcheada obtiene el puntero a la siguiente sección del mensaje MSMQ a través de una llamada a
Fragmento de descompilación de la función GetNextSectionPtrSafe
Después de examinar todas las apariciones de esta marca de característica y otras, se determinó que CVE-2023-21554 consta de varios errores que comprueban insuficientemente el tamaño de varios tipos de sección de mensajes MSMQ. Estas vulnerabilidades permiten que el puntero al final del mensaje MSMQ se incremente en un desplazamiento arbitrario de 32 bits fuera de los límites del búfer asignado originalmente.
Tras el procesamiento de paquetes, el último paso de
Comprobación de acceso a memoria fuera de límite para fin de mensaje
Al evaluar la explotabilidad de las vulnerabilidades, se identificaron vulnerabilidades adicionales del kernel en el controlador del kernel correspondiente para el servicio MSMQ, . Las vulnerabilidades se indicaron nuevamente mediante símbolos de característica, que también hacen referencia al caso MSRC 76146 observado en .
Símbolos de indicadores de características dentro de mqac.sys
El análisis del indicador de la característica
Para realizar las operaciones asociadas, el componente del núcleo analiza varias secciones del búfer de paquetes de MSMQ. A continuación se muestran dos ejemplos de este tipo:
Fragmento de código descompilado que muestra el indicador de característica para la corrección de vulnerabilidades en el controlador del núcleo mqac.sys
Como se ve en el fragmento de código descompilado anterior, si la característica está activada, las funciones “seguras”
La mayoría del código relacionado con el análisis de protocolos se encuentra dentro de la biblioteca , que carga el procesomqsvc.exe, se debe enviar una solicitud MSMQ válida desde el cliente. La especificación y el protocolo de mensajes MSMQ son amplios y complejos. Inicialmente, se encontró un código público para escanear servidores MSMQ en un gist de GitHub que proporcionó la base para una exploración más profunda del procesamiento de paquetes. Además, la documentación de Microsoft fue útil para comprender el formatode mensajes MSMQ.
El código dentro de la DLL acepta datos a través del puerto 1801 mediante una llamada a la función WSARecv , como se puede ver en la sesión de depuración a continuación:
0:020> bp ws2_32!wsarecv ; g
Breakpoint 0 hit
WS2_32!WSARecv:
00007ffd`651115c0 48895c2408 mov qword ptr [rsp+8],rbx ss:000000aa`f07fef30=0000000000000006
0:019> k
# Child-SP RetAddr Call Site
00 000000aa`f07fef28 00007ffd`57ba9cb0 WS2_32!WSARecv
01 000000aa`f07fef30 00007ffd`57b9683d
MQQM!NoReceivePartialBuffer+0x38
02 000000aa`f07fefb0 00007ffd`57b2078e MQQM!CWinsockConnection::ReceivePartialBuffer+0x7d
03 000000aa`f07ff010 00007ffd`57b25b28
MQQM!CSockTransport::BeginReceive+0xe6
04 000000aa`f07ff060 00007ffd`57b2d40b
MQQM!CSockTransport::NewSession+0x194
05 000000aa`f07ff3f0 00007ffd`57b2d367 MQQM!CSessionMgr::AcceptSockSession+0x6f
06 000000aa`f07ff430 00007ffd`645e26bd MQQM!AcceptIPThread+0x6a7
07 000000aa`f07ff7d0 00007ffd`6650a9f8
KERNEL32! BaseThreadInitThunk+0x1d
08 000000aa`f07ff800 00000000`00000000 ntdll!RtlUserThreadStart+0x28
0:019> r @$t0=@rdx
0:019> pt
WS2_32!WSARecv+0x19f:
00007ffd`6511175f c3 ret
0:019> dc poi(@$t 0+8) LC
000001b5`880ff490 62f06110 524f494c 00000070 5a5a5a5a .a.bLIORp…ZZZZ
000001b5`880ff4a0 0073006e 00610074 0063006e 00200065 n.s.t.a.n.c.e. .
000001b5`880ff4b0 00440049 00000000 00000000 00000000 I.D………….
0:019> ba r1 poi(@$t 0+8) ; g
Breakpoint 1 hit
MQQM!CBaseHeader::SectionIsValid+0x154:
00007ffd`57b53450 7462 je
¡MQQM! CBaseHeader::SectionIsValid+0x1b8 (00007ffd’57b534b4) [br=1]
La función es responsable de analizar el comienzo de un nuevo mensaje, que comienza con una estructura BaseHeader del formato:
Estructura del objeto BaseHeader
Los campos de los mensajes entrantes están validados por
Código de desensamblado para SectionIsValid dentro de MQQM.dll
Después de la validación inicial, la mayor parte del análisis del protocolo se produce dentro de la función constructora
Descompilación que muestra la vulnerabilidad en el manejo de EodHeader
La descompilación anterior muestra la ruta parcheada llamando a la función llamada
La estructura de un
Desensamblado calculando el tamaño total de la sección EodHeader
En el desensamblado anterior, el puntero al principio de
Sesión WinDbg que muestra una infracción de acceso al escribir al final de un mensaje MSMQ mal formado
Para evaluar la potencia de la escritura fuera de los límites obtenida por las vulnerabilidades, primero investigamos la asignación y la gestión de la memoria subyacente.
Antes de procesar un paquete de mensajesMSMQ. Esta función llama al controlador del kernel a través deNtDeviceIoControl.
Descompilación de la función de asignación del búfer de paquetes
El componente del kernel devuelve un búfer que se divide a partir de una vista mapeada de un archivo en disco, almacenado en el directorio
El diseño de memoria de ProcessHacker del proceso MQSVC muestra que la memoria del búfer de paquetes es una mapeo de archivos
La dirección del búfer del paquetes, junto con un identificador de paquete aleatorio, se devuelve al espacio del usuario después de la solicitud de asignación a través de IOCTL. El controlador utiliza el identificador para calcular la dirección del búfer de paquetes al gestionar solicitudes desde el espacio de usuario.
La memoria de respaldo de los búferes vulnerables está dentro de un archivo mapeado y, por lo tanto, no en una pila del proceso. Además, la memoria afectada no almacena ningún objeto. Lo único que contiene la asignación de archivos es el contenido de los mensajes MSMQ junto con los metadatos que se almacenan en el
Además, sin un conocimiento previo del diseño de la memoria, no es posible conocer la posición relativa de la asignación de archivos a la pila del proceso para sobrescribir los punteros de objetos. Por lo tanto, para poder obtener la ejecución remota de código, necesitamos algún método para dar forma a la memoria en una posición predecible.
Tras experimentar con el envío de mensajes MSMQ legítimos al objetivo, se descubrió que es posible forzar una nueva asignación de montones junto a un mapeo de archivos
Diseño de memoria del proceso MQSVC que muestra una nueva pila asignada de forma adyacente a una correlación de archivos MQ
Sin embargo, esto requiere que el atacante tenga acceso para enviar mensajes a al menos una cola en el objetivo; de lo contrario, los mensajes se descartarán y sobrescribirán y, por lo tanto, no ocuparán la memoria de paquetes de forma persistente.
Durante el experimento de investigación realizado, se descubrió que es posible que un usuario sin privilegios cree una cola abierta a cualquiera para enviar mensajes de remotamente, de forma predeterminada. La cola persiste en el sistema de manera indefinida. Aunque la mayoría de los usos modernos de MSMQ existen como componentes y adaptadores opcionales, proveedores como Oracle, Veritas y Xerox ofrecen software empresarial que se basa en MSMQ como dependencia principal. Por lo tanto, el escenario de ataque no es poco realista.
La vulnerabilidad de acceso a memoria fuera de límites introduce una primitiva de explotación que permite a un
cliente malicioso escribir unOnDiskExtensionHeader
asignada al paquete.
Al evaluar una vulnerabilidad que permite escribir valores en un desplazamiento,
se deben considerar algunas propiedades:
En el caso de las vulnerabilidades de QueueJumper, el desplazamiento del búfer asignado a la escritura OOB es controlable porque se calcula utilizando datos controlados por el atacante. Sin embargo, el contenido de la escritura OOB tiene un control limitado.
Aquí,Address. La serie de operaciones que se producen es la siguiente:
0x000000000000000C
se escribe enAddress0x00000000Address+0x2
0x0000000000000000Address+0x12
0x0000000000000000
se escribe en Address+0x1A
0x00000094
se escribe Address+0xE
0x0000Address+0x220x0000
se escribe en Address+0x62
memcpy(Address+0xA6, Source, Source->AddressLength+0x08)
ElSourcememcpy define una única dirección de transporte de un tipo específico (por ejemplo, NetBIOS). La definición es la siguiente:
typedef struct _TA_ADDRESS {
USHORT AddressLength;;
USHORT AddressType; Info;
UCHAR Address[1];;
} TA_ADDRESS, *PTA_ADDRESS;
Especifica el número de bytes en una dirección del AddressType especificado.
Especifica el tipo de dirección de transporte.
Especifica una matriz de tamaño variable que contiene la dirección de transporte.
En una sesión de depuración que aparece a continuación,TA_ADDRESS
rax=0000014e1d110180 rbx=0000014e1d110180 rcx=0000014e1d110184
rdx=0000014e1ce86b10 rsi=0000014e1d110001 rdi=0000000545d7fa50
rip=00007ff843208074 rsp=0000000545d7f940 rbp=0000000545d7f980
r8=000000000000000c r9=0000000000000002 r10=0000000000000000
r11=0000000545d7f938 r12=0000000000000002 r13=0000000000001000
r14=0000014e1ce86b10 r15=0000000000000000
iopl=0 nv up ei pl nz na po nc
cs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000206
MQQM!CQmPacket::CQmPacket+0x89c:
00007ff8`43208074 e8a5780a00 call MQQM!memcpy (00007ff8`432af91e)
0:017> dc rcx
0000014e`1d110184 00010004 00000000 8620a8c0 00000000 ………. …..
Arriba, el objetoTA_ADDRESS, un tipo de1. Al convertir cada byte en un octeto IPv4 se obtiene la dirección , que es la dirección IPv4 de origen del cliente..
Este escenario permite la escritura de datos controlados por el atacante a través de una dirección a un desplazamiento controlado de la asignación del paquete en la memoria. Aunque muy restrictivo y posiblemente poco práctico, teóricamente podría usarse para controlar con precisión los valores escritos en memoria haciendo múltiples peticiones desde direcciones variables con desplazamientos de paquetes decrementadores.
Debido al número de limitaciones encontradas para lograr la ejecución remota ciega de código, se investigaron escenarios alternativos de ataque, como fugas de información.
Un ataque que se consideró consistía en corromper el puntero a una sección específica del mensaje para que apuntara a una memoria fuera de límites y, posteriormente, recuperar el mensaje para leer la memoria adyacente.
Sin embargo, al principio del análisis de cada sección se realiza una comprobación de la posición de la sección actual, por lo que no podemos engañar a la lógica de análisis para que analice una sección de datos que esté fuera de los límites.
Otro posible escenario de ataque es sobrescribir el OnDiskExtensionHeader de otro mensaje para engañar al destinatario del mensaje de los orígenes del mensaje recibido. Del mismo modo, es posible sobrescribir el contenido de los mensajes destinados a colas a las que el atacante no tiene acceso. Sobrescribir contenidos específicos de un mensaje requeriría que el atacante dispusiera de información sobre el mensaje, como su tamaño.
Hay una sección opcional llamada SoapHeader que es susceptible de acceso a datos fuera de los límites, con el siguiente formato:
Formato de paquete SoapHeader
Se observó que la memoria utilizada para almacenar los datos de los paquetes MSMQ no se borra correctamente cuando se libera el búfer. Como resultado, el envío de un paquete MSMQ de menor tamaño que un paquete MSMQ anterior dará como resultado un diseño de memoria que contiene los datos del paquete actual seguidos de los datos de los paquetes MSMQ procesados previamente.
Se descubrió que el
El control limitado en el contenido de escritura, con las escrituras adicionales no controladas que corrompían la memoria adyacente, junto con el conocimiento limitado sobre la disposición de los mensajes, resultaron ser un gran obstáculo para la explotación.
En el momento del análisis, solo se evaluaron las vulnerabilidades del espacio de usuario implicadas en el procesamiento inicial de un paquete de mensajes MSMQ para determinar su explotabilidad. El análisis de las vulnerabilidades de las variantes del kernel podría revelar nuevas vías de explotación. Por ejemplo, es posible que la inclusión de un encabezado mal formado obtenga una primitiva de escritura en la asignación de memoria del kernel del archivo . En algunos casos, las comprobaciones en el procesamiento del espacio de usuario impiden que el kernel realice algunas operaciones de posprocesamiento.
Además, en el caso de las variantes del kernel, el atacante tiene menos control directo sobre el contenido del mensaje y también opera en el mismo mapeo de archivos que el espacio de usuario, no en un grupo de kernel (heap). Las mitigaciones, como KASLR, también presentan obstáculos que son difíciles de superar para la explotación remota.
Gracias a la implementación del código parcheado, un cliente remoto puede determinar de forma segura si un sistema ha aplicado la actualización. Esto se puede hacer enviando un mensaje MSMQ que desencadene la vulnerabilidad, pero que en realidad no provoque un acceso fuera de límite, por lo que no bloqueará el proceso de servicio. Si la alerta HTTP se activa en el UserHeader del mensaje, se espera un SRMPEnvelopeHeader. En el parche, se realiza una comprobación de un desbordamiento de enteros en el campo multiplicado por 2. Esta longitud se puede configurar de modo que el resultado de la multiplicación se desborde a un número pequeño igual al tamaño real de los datos.
Fragmento de código descompilado que muestra la comprobación de desbordamiento de enteros en SRMPEnvelopeHeader DataLength
Si el destino se parchea, la vulnerabilidad provoca que se lance una excepción y el servidor abortará el procesamiento del mensaje, por lo que no se envía respuesta al cliente. Si no está parcheado, el servidor procesará el mensaje normalmente y enviará una respuesta.
Debido a la ubicación de la memoria de respaldo de los búferes vulnerables, la ejecución remota de código parece más factible para un atacante con la capacidad de enviar mensajes a cualquier cola del objetivo. En este escenario, es posible preparar el terreno para que se asigne un montón adyacente. El control extremadamente limitado sobre el contenido de escritura presenta desafíos para la explotación remota. Debido a mitigaciones como ASLR, también se debe obtener una fuga de información. Es posible que una sola escritura de una constante (0xC, 0x0
En última instancia, llegamos a la conclusión de que, aunque la explotación remota de QueueJumper puede no ser imposible, los requisitos antes mencionados dificultan su cumplimiento. Esta entrada del blog solo aborda superficialmente lo que es una especificación, un servicio y un protocolo muy complejos. Se justifica una investigación más profunda sobre la vulnerabilidad tanto en el espacio de usuario como en las operaciones de los componentes del kernel.