Las actualizaciones de seguridad publicadas por Microsoft el 11 de abril de 2023 abordaron más de 90 vulnerabilidades individuales. De particular interés fue CVE-2023-21554, apodado QueueJumper, una vulnerabilidad de ejecución remota de código que afecta 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 servicios de adversarios Randori y X-Force, por parte de Valentina Palmiotti, Fabius Watson y Aaron Portnoy.
Las siguientes cualidades de CVE-2023-21554 llamaron la atención inicialmente:
Manténgase al día sobre las tendencias más importantes e intrigantes de la industria sobre IA, automatización, datos y 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 formateados. Para comprender cómo llevar a cabo una conversación con el endpoint, se requirió una inspección adicional del código subyacente.
Del aviso, no está claro de inmediato 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 Microsoft Update Catalog.
Resultados de búsqueda del Microsoft Update Catalog para KB5025224
Específicamente, se recuperó el archivo de actualización acumulativa
windows10.0-kb5025224-x64_3522b1b562ed44bc949541dd1c7d08e1e967d925.msu
para Windows 11 para sistemas basados en x86.
Se utilizó el extractor 7-Zip para descomprimir el contenido del archivo MSU y los archivos CAB que contenía. Al buscar la cadena “msmq” en todos los archivos de las carpetas resultantes, se obtiene el archivo Container Index,
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 con Hex-Rays Decompiler reveló símbolos para la versión parcheada que contenían nombres de funciones detallados que parecen hacer referencia a los identificadores de vulnerabilidad del Microsoft Security Research Center (MSRC):
Símbolos de indicadores de características dentro de MQQM.dll
Después de una inspección más cercana, los símbolos que contienen números de caso MSRC corresponden a indicadores de características para arreglos de vulnerabilidades. Los indicadores de características son un componente de Windows que alternan varias funciones y experimentos. Aquí, la “característica” descubierta es en realidad un parche para una vulnerabilidad. Si la característica está habilitada, se ejecuta la ruta de código segura y parcheada. De lo contrario, se ejecuta la ruta de código original no parcheada.
Fragmento de código descompilado que muestra el indicador de características para el arreglo de vulnerabilidades
Hubo una verificación de indicadores de características para cada una de las vulnerabilidades que comprendían CVE-2023-21554 tanto en el componente del usuario como en el del kernel. 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ísticas para la mayoría o todas las vulnerabilidades corregidas el martes de parches de abril de 2023.
Las referencias cruzadas de estos indicadores nos ayudaron a identificar rápidamente las ubicaciones de los códigos parcheados. En particular, los cambios dentro de relacionados con el indicadorMSRC76146_MSMQ_OOBRWFixes parecieron de mayor interés.
La comprobación de estos indicadores de características 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 un arreglo de vulnerabilidad
En el fragmento de código descompilado que se muestra arriba, la ruta del código parcheado 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 este indicador de características y otras, se determinó que CVE-2023-21554 consta de varios errores que verifican de manera insuficiente el tamaño de varios tipos de secciones 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 del paquete, el paso final en
Comprobación de acceso a memoria fuera de límites para el fin del 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 fueron nuevamente indicadas por los símbolos de indicadores de características, que también hacen referencia al caso 76146 de MSRC como se observa en .
Símbolos de indicadores de características dentro de mqac.sys
El análisis del indicador de características
Para realizar las operaciones asociadas, el componente del kernel 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ísticas para el arreglo de vulnerabilidades en el controlador del kernel mqac.sys
Como se ve en el fragmento de código descompilado anterior, si el indicador de características está habilitado, se llaman a las funciones “seguras”
La mayoría del código relacionado con el análisis de protocolos se encuentra dentro de la biblioteca que carga elmqsvc.exe, se debe enviar una solicitud MSMQ válida desde el cliente. La especificación y el protocolo de mensajes de MSMQ son amplios y complejos. Inicialmente, se encontró código público para escanear servidores MSMQ en un gist de GitHub que sirvió de base para una exploración más profunda del procesamiento de paquetes. Además, la documentación de Microsoft fue útil para comprender el formato de mensajes MSMQ.
El código dentro del 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(@$t0+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(@$t0+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 empieza con una estructura BaseHeader de la forma:
Estructura del objeto BaseHeader
Los campos del mensaje entrante son 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 que llama a la función llamada
La estructura de un
Desensamblado que calcula el tamaño total de la sección EodHeader
En el desensamblado anterior, el puntero al comienzo del
Sesión de WinDbg que muestra una violación de acceso al escribir al final de un mensaje MSMQ con formato incorrecto
Para evaluar la gravedad de la escritura fuera de límites obtenida por las vulnerabilidades, primero investigamos la asignación y gestión de la memoria subyacente.
Antes de procesar un paquete de mensajesMSMQ. Esta función llama al controlador del kernel medianteNtDeviceIoControl.
Descompilación de la función de asignación de búfer de paquetes
El componente del kernel devuelve un búfer que se particiona desde una vista mapeada de un archivo en disco, almacenado en el directorio
Diseño de memoria de ProcessHacker del proceso MQSVC que muestra que la memoria del búfer de paquetes es una asignación de archivos
La dirección del búfer del paquete, junto con un identificador de paquete aleatorio, se devuelve al espacio del usuario luego de la solicitud de asignación a través de IOCTL. El controlador usa el identificador para calcular la dirección del búfer de paquetes cuando maneja solicitudes desde el espacio del usuario.
La memoria de respaldo para los búferes vulnerables está dentro de un archivo asignado y, por lo tanto, no en una pila del proceso. Además, la memoria afectada no almacena ningún objeto. Lo único que está contenido en la asignación de archivos es el contenido de los mensajes de 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 el posicionamiento relativo de la asignación de archivos al pila del proceso para sobrescribir los punteros de objetos. Por lo tanto, para poder ejecutar código de forma remota, necesitamos algún método que nos permita configurar la memoria en una posición predecible.
Después de experimentar con el envío de mensajes MSMQ legítimos al destino, se descubrió que es posible forzar una nueva asignación de pila adyacente a un mapeo de archivos
Diseño de memoria del proceso MQSVC que muestra una nueva pila asignado de forma adyacente a una asignació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.
En la experimentación de investigación realizada, se descubrió que es posible que un usuario sin privilegios cree una cola que esté abierta a cualquier persona para enviar mensajes de forma remota, de forma predeterminada. La fila 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 confía en MSMQ como dependencia central. Por lo tanto, el escenario de ataque no es irreal.
La vulnerabilidad de acceso a la memoria fuera de los límites introduce una primitiva de explotación que permite a un
cliente malicioso escribir unOnDiskExtensionHeader
asignada para el 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
está escrito enAddress0x00000000Address+0x2
0x0000000000000000Address+0x12
0x0000000000000000
está escrito en Address+0x1A
0x00000094
está escrito en Address+0xE
0x0000Address+0x220x0000
está escrito 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. La conversión de cada byte en un octeto IPv4 produce la dirección , que es la dirección de origen IPv4 del cliente.
Este escenario permite la escritura de datos controlados por el atacante a través de una dirección de origen a una compensación controlada desde la asignación de paquetes en la memoria. Si bien es muy restrictivo y posiblemente poco práctico, en teoría podría usarse para controlar con precisión los valores escritos en la memoria realizando múltiples solicitudes desde diferentes direcciones en desplazamientos de paquetes decrecientes.
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.
Uno de los ataques que se consideró fue corromper el puntero a una sección específica del mensaje para apuntar a la memoria fuera de límites y luego recuperar el mensaje para leer la memoria adyacente.
Sin embargo, el comienzo del análisis de cada sección verifica la posición de la sección actual; por lo tanto, 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 tuviera 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 del paquete 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 control limitado en los contenidos de escritura con las escrituras adicionales no controladas que corrompen la memoria adyacente, junto con el conocimiento limitado en el diseño de los mensajes demostraron ser un gran obstáculo en la explotación.
En el momento del análisis, solo se evaluaron las vulnerabilidades del espacio de usuario involucradas en el procesamiento inicial de un paquete de mensajes MSMQ para determinar su explotabilidad. El análisis de las vulnerabilidades variantes del kernel podría descubrir vías adicionales de explotación. Por ejemplo, es posible que incluir un encabezado mal formado genere una primitiva de escritura en el mapeo de memoria del kernel del archivo . En algunos casos, las verificaciones 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 la misma asignación de archivos que el espacio del usuario, no en un grupo (pila) de kernel. 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 con seguridad si un sistema aplicó 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ímites, por lo que no bloqueará el proceso de servicio. Si el indicador 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 establecer 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 memoria de respaldo de ubicación 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 en el destino. En este escenario, es posible realizar un grooming para que se asigne una pila 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, si bien la explotación remota de QueueJumper puede no ser imposible, los requisitos antes mencionados dificultan su cumplimiento. Esta entrada en el blog solo aborda lo básico de lo que es una especificación de mensaje, servicio y protocolo muy complejos. Se justifica una mayor investigación de vulnerabilidades tanto en el espacio del usuario como en las operaciones de los componentes del kernel.