Supresión del sonido: encadenamiento de vulnerabilidades para la ejecución remota de código en Outlook: parte 1
Resumen ejecutivo
Ben Barnea, investigador de Akamai descubrió dos vulnerabilidades en Microsoft Windows a las que se asignó la CVE-2023-35384 y la CVE-2023-36710.
Un atacante en Internet puede encadenar las vulnerabilidades para crear una explotación completa de ejecución remota de código (RCE) sin clic en los clientes de Outlook.
La primera vulnerabilidad radica en el análisis de una ruta de acceso por parte de la función MapUrlToZone . Para explotar esta vulnerabilidad es necesario enviar un correo electrónico especialmente diseñado a un cliente de Outlook, que a su vez descargará un archivo de sonido especial de un servidor controlado por el atacante.
La segunda vulnerabilidad se encuentra en el administrador de compresión de audio (ACM). Esta vulnerabilidad se explota cuando el archivo de sonido descargado se reproduce automáticamente, lo que puede provocar la ejecución de código en el equipo de la víctima. Esta vulnerabilidad se describe detalladamente en la parte 2 de esta entrada de blog.
Estas vulnerabilidades se divulgaron de forma responsable a Microsoft y se solucionaron en los Patch Tuesday de agosto de 2023 y octubre de 2023 .
Los equipos Windows que tienen instalada la actualización de software de octubre de 2023 están protegidos frente a estas vulnerabilidades. Además, los clientes de Outlook que utilizan servidores de Exchange con la actualización de software de marzo de 2023 instalada están protegidos contra la función explotada.
Descripción general
Entre las vulnerabilidades corregidas como parte del Patch Tuesday de marzo de 2023 se encontraba una vulnerabilidad crítica de Outlook con la CVE-2023-23397, que fue explotada en el mundo real por Forest Blizzard, identificado por Microsoft como un atacante patrocinado por el Estado ruso. En diciembre de 2023, Microsoft, junto con el Comando Cibernético Polaco (DKWOC), publicó que había observado intentos de explotación recientes de esta vulnerabilidad por parte del mismo atacante. Esta vulnerabilidad permitía a un atacante forzar a un cliente de Outlook a conectarse al servidor del atacante. Como parte de esta conexión, el cliente envía sus credenciales NTLM al atacante, que puede descifrarlas sin conexión o utilizarlas en un ataque de retransmisión. Esta vulnerabilidad se podía explotar de forma remota a través de Internet sin ninguna interacción del usuario (sin hacer clic).
Después de la publicación del parche para esta vulnerabilidad, descubrimos una omisión que hemos descrito en la anterior entrada de blog. Esta omisión se corrigió en el Patch Tuesday de mayo de 2023. En esa publicación, recomendamos que Microsoft eliminara la función explotada, ya que introduce una superficie de ataque amplia y compleja. Dado que esta función permanece en Outlook, hemos decidido investigarla más a fondo.
Finalmente, pudimos obtener una cadena de vulnerabilidades de RCE completa en Outlook. Hemos detectado otra omisión a la vulnerabilidad original de Outlook, una omisión que nuevamente permitía obligar al cliente a conectarse a un servidor controlado por el atacante y descargar un archivo de sonido malicioso. A continuación, logramos detectar una vulnerabilidad en la biblioteca de análisis de medios de Windows que se utiliza para procesar y reproducir cualquier archivo de audio en general y los sonidos de notificación de Outlook en particular. Un atacante que encadene estas vulnerabilidades puede lograr una RCE sin clic en clientes de Outlook vulnerables.
Esta serie de entradas de blog en dos partes presentará la investigación que hemos llevado a cabo para detectar las dos vulnerabilidades. Esta primera parte se centrará en la omisión previa y en una nueva. En la parte 2, describiremos la vulnerabilidad de análisis de medios que hemos detectado.
La vulnerabilidad original
La vulnerabilidad de Outlook que se corrigió en marzo se activa cuando un atacante envía un correo electrónico que contiene un recordatorio con un sonido de notificación personalizado. Este sonido personalizado lo especifica el atacante como una ruta, utilizando la propiedad de MAPI extendida PidLidReminderFileParameter. Un atacante puede especificar una ruta UNC que haría que el cliente recuperara el archivo de sonido de cualquier servidor SMB. Como parte de la conexión al servidor SMB remoto, se envía el hash Net-NTLMv2 en un mensaje de negociación (Figura 1).
Para solucionar el problema, el código llama ahora a MapUrlToZone para clasificar la ruta como intranet, local o Internet. Si la dirección URL apunta a un recurso de Internet, se utiliza el sonido de recordatorio predeterminado en lugar del personalizado.
Búsqueda de una omisión
Después de aplicar la mitigación, nos preguntamos si era posible omitirla.
En este contexto, omitirla significa encontrar una ruta que supere la prueba de ubicación local y que se utilice en Outlook para descargar el archivo de sonido desde una ubicación remota. Es decir, necesitamos encontrar una ruta que MapUrlToZone considere que no es de Internet, pero que CreateFile trate como un dominio de Internet.
Para encontrar una omisión de este tipo, necesitábamos entender completamente el funcionamiento interno de las funciones y las operaciones realizadas como parte del análisis de ruta.
Rutas de acceso y URL de Windows
Hay muchos tipos diferentes de rutas DOS en Windows, y se ha llevado a cabo una amplia investigación acerca de ellas y su conversión a rutas NT. En esta publicación no trataremos los diferentes tipos de rutas de Windows; la entrada de blog de James Forshaw trata este tema en profundidad.
Volvamos a nuestras funciones de interés. CreateFile recibe una ruta de Windows; MapUrlToZone (como indica su nombre en inglés) se le puede transferir una URL o una ruta. Para encontrar una omisión, primero necesitamos entender qué tipos de ruta son compatibles con cada función (o con ambas).
Nota: CreateFile y MapUrlToZone no procesan por sí mismos las rutas de acceso; utilizan en cambio otras funciones de WinAPI para este fin. Por razones de brevedad, usaremos CreateFile y MapUrlToZone para hacer referencia a sus funciones de análisis de rutas subyacentes.
CreateFile |
MapUrlToZone |
|
---|---|---|
RtlPathTypeUncAbsolute |
✔ |
✔ |
RtlPathTypeDriveAbsolute |
✔ |
✔ |
RtlPathTypeDriveRelative |
✔ |
✔ |
RtlPathTypeRooted |
✔ |
✘ |
RtlPathTypeRelative |
✔ |
✘ |
RtlPathTypeLocalDevice |
✔ |
✔ |
RtlPathTypeRootLocalDevice |
✔ |
✘ |
Esquemas (file://, http://) |
✘ |
✔ |
Tabla 1: Tabla comparativa de las capacidades de ruta de CreateFile y MapUrlToZone
Como se muestra en la Tabla 1, solo haya cuatro tipos de ruta que son compatibles con ambas funciones: RtlPathTypeUncAbsolute, RtlPathTypeDriveAbsolute, RtlPathTypeDriveRelative, y RtlPathTypeLocalDevice.
Primer intento
El primer intento de encontrar una omisión se realizó con una ruta UNC absoluta (RtlPathTypeUncAbsolute). En la Figura 2 se detalla la estructura de la ruta.
¿Cómo sabe Windows dónde comienza el componente de ruta? En la Tabla 2 se muestra el código correspondiente (RtlGetFullPathName_Ustr).
case RtlPathTypeUncAbsolute:
SeperatorsFound = 0;
for ( CurrentIndex = 2; CurrentIndex < InputPathLength; ++CurrentIndex )
{
CurrentChar = InputPathString->Buffer[CurrentIndex];
if ( CurrentChar == '\\' || CurrentChar == '/' )
{
SeperatorsFound++;
if ( SeperatorsFound == 2 )
break;
}
}
Tabla 2: Fragmento de código de RtlGetFullPathName_Ustr que gestiona la ruta UNC
Podemos ver que el código omite el prefijo UNC absoluto ("\\") y, a continuación, supone que el componente de ruta comienza un carácter después del segundo separador de ruta ('\ ' o '/ ').
Pero qué sucede si proporcionamos una ruta como "\\\\localhost\..\Akamai.com\dir\file.txt"?
La ruta se procesará de la siguiente manera:
"\\\\" se interpreta como el prefijo UNC y el componente de ruta raíz
El componente de ruta es "localhost\..\Akamai.com\dir\file.txt"
Normalmente, no puede ir ninguna cantidad de ".." por encima de la ruta raíz. Por ejemplo, "\\localhost\directory\..\file.txt" daría como resultado "\\localhost\directory\file.txt". Sin embargo, puesto que en nuestro ejemplo "..." no forma parte de la ruta raíz, la ruta se convierte a "\\\Akamai.com\dir\file.txt".
Esto significa que hemos encontrado una manera de manipular la ruta eliminando partes de esta.
Así es como CreateFile procesa esta ruta; cómo la gestiona MapUrlToZone (Tabla 3)? Primero elimina las barras diagonales inversas adicionales y, de ese modo, interpreta la ruta de forma diferente:
\\localhost es el nombre del servidor
\..\ se ignora (ya que no podemos ir por encima del nombre del servidor)
Akamai.com\dir\file.txt conforma el componente de ruta
Ruta de entrada: \\\\localhost\..\Akamai.com\dir\file.txt |
|
---|---|
CreateFile |
MapUrlToZone |
\\\Akamai.com\dir\file.txt |
\\localhost\Akamai.com\dir\file.txt |
Tabla 3: Rutas de entrada para CreateFile y MapUrlToZone y resultado de su análisis
MapUrlToZone devuelve 0 (Local) para la ruta mostrada anteriormente.
Aunque parece que hemos encontrado una omisión, lamentablemente, la ruta no se puede utilizar para activar una solicitud UNC. Observe la barra diagonal adicional al principio de la ruta de acceso procesada por CreateFile : esta marca que el nombre del servidor está vacío. Cuando el proveedor UNC múltiple (MUP) consulta a los distintos proveedores de red si pueden gestionar este nombre de servidor (vacío), todos devuelven false, por lo que no se realiza ninguna solicitud.
Un mal uso de la diferencia entre MapUrlToZone y CreateFile en el modo de gestionar esta ruta puede requerir una solución más complicada, como podría ser encontrar una forma de omitir la barra diagonal inversa adicional o una discrepancia de análisis en el código MUP. Es una sugerencia para una investigación futura.
Segundo intento: omisión n.º 1 (CVE-2023-29324)
Dado que el intento con las rutas UNC absolutas no ha funcionado, continuamos con el siguiente tipo de ruta compatible con UNC: RtlPathTypeLocalDevice. "\\.\UNC\Akamai.com\test.wav" es un ejemplo de ruta de un dispositivo local. Específicamente, apunta al nombre del dispositivo UNC, que se redirigirá al controlador MUP.
Como hemos indicado anteriormente, para encontrar una omisión, necesitamos examinar las diferentes operaciones realizadas como parte del análisis de las rutas. En la tabla 4 se muestra esa diferencia.
CreateFile |
MapUrlToZone |
---|---|
Si RtlPathTypeLocalDevice → Avanzar 4 caracteres |
Si RtlPathTypeLocalDevice → Avanzar 4 caracteres |
Omitir espacios finales |
|
Convertir '/' a '\' |
|
Contraer '\' repetida |
|
Eliminar componentes '.' y '..' |
Eliminar componentes '.' y '..' |
Tabla 4: Diferentes operaciones completadas como parte del análisis de ruta
Podemos ver que CreateFile realiza operaciones adicionales, como convertir barras diagonales en barras diagonales inversas y contraer barras diagonales inversas repetidas.
Veamos una ruta que aprovecha una de estas diferencias : el uso de un separador de ruta adicional. En la Tabla 5 se muestran las rutas resultantes después de que el código haya omitido el prefijo "UNC\".
Ruta de entrada: \\.\UNC\\Akamai.com\test.wav |
|
---|---|
CreateFile |
MapUrlToZone |
Akamai.com\test.wav |
\Akamai.com\test.wav |
Tabla 5: Rutas resultantes después de omitir UNC/un prefijo
Observe la ruta en la columna derecha. Una ruta que empieza por un separador de ruta seguido de un carácter que no es un separador de ruta se denomina ruta de acceso raíz. MapUrlToZone utiliza las funciones IsRootedPath o IsDrivePath para determinar si el componente de ruta de acceso raíz es local. En nuestro caso, la ruta es de acceso raíz y, por lo tanto, MapUrlToZone devuelve local.
CreateFile no tiene el separador de ruta adicional después del prefijo UNC, por lo que sabe extraer el nombre de dominio correctamente y ahora tiene acceso al servidor SMB de Akamai.com para recuperar el archivo test.wav. Hemos encontrado una ruta que MapUrlToZone considera local, pero CreateFile no. Esta omisión ha vuelto a activar la explotación de la vulnerabilidad de Outlook CVE-2023-23397.
Para mitigar este problema, Microsoft intentó hacer que los dos flujos fueran más similares; las operaciones de conversión de barras diagonales en barras diagonales inversas y contracción de separadores de ruta repetidos se agregaron en esta ocasión al flujo de análisis de rutas de MapUrlToZone .
Una reflexión…
En la sección anterior, hemos observado que MapUrlToZone comprueba si el componente de ruta después de "\\.\UNC\" es una ruta de unidad o de acceso raíz. No podemos hacer de este componente de ruta una ruta de acceso raíz después de la corrección porque los separadores de ruta repetidos están contraídos. Sin embargo, sí podemos proporcionar una ruta de unidad; por ejemplo, "\\.\UNC\C:Akamai.com/test.wav".
De hecho, esto hace que MapUrlToZone devuelva 0. Lamentablemente, ningún proveedor de red puede gestionar una ruta con dos puntos en ella, por lo que esta confusión no nos resulta útil. Al igual que en nuestro primer intento (fallido), encontrar una confusión con el código de análisis MUP puede provocar una nueva vulnerabilidad.
Tercer intento: omisión n.º 2 (CVE-2023-35384)
Después de la corrección, las operaciones realizadas por las dos funciones son casi las mismas (Tabla 6).
CreateFile |
MapUrlToZone |
---|---|
Si RtlPathTypeLocalDevice → Avanzar 4 caracteres |
Si RtlPathTypeLocalDevice → Avanzar 4 caracteres |
Omitir espacios finales |
|
Convertir '/' a '\' |
Convertir '/' a '\' |
Contraer '\' repetida |
Contraer '\' repetida |
Eliminar componentes '.' y '..' |
Eliminar componentes '.' y '..' |
Tabla 6: Operaciones realizadas por CreateFile y MapUrlToZone después de la corrección
Sin embargo, si profundizamos aún más, podemos preguntarnos: ¿Cómo decide cada función que la ruta es una ruta de dispositivo local? En la Tabla 7 se muestran fragmentos de código de cada función que ayudan a determinar el tipo de ruta.
CreateFile
if (IS_PATH_SEPARATOR(Path[0]) &&
IS_PATH_SEPARATOR(Path[1]) &&
(Path[2] == '.' || Path[2] == '?') &&
IS_PATH_SEPERATOR(Path[3])
return RtlPathTypeLocalDevice;
MapUrlToZone
!strncmp(path, "\\.\", 4) || !strncmp(path, "\\?\", 4)
Tabla 7: Fragmentos de código que determinan el tipo de ruta
Con CreateFile, un separador de ruta puede ser una barra diagonal o una barra diagonal inversa; por ejemplo, "\\./" se considera una ruta de dispositivo local. Con MapUrlToZone, solo las rutas "\\.\" o "\\?\" exactas se consideran rutas de dispositivo local. Esto es una confusión de tipo de ruta: podemos hacer que CreateFile reconozca el componente "\\./" como una ruta de dispositivo local, mientras que MapUrlToZone no lo hará. Esta confusión implica una gestión diferente de la ruta por parte de las dos funciones.
Teniendo esto en cuenta, utilizaremos una ruta que contenga el componente "confuso": \\./UNC/Akamai.com/file.wav.
Al analizar la toma de decisiones para este tipo de ruta, este es el flujo de MapUrlToZone:
¿Es la ruta una unidad local o una ruta de acceso raíz? No
¿IsLocalDeviceUNC? No
¿PathIsUNCW? Sí
PathIsUNCW devuelve true y, por lo tanto, la función lo marca como una ruta UNC absoluta y avanza dos caracteres para omitir el prefijo UNC "\\". La salida de cada función se muestra en la Tabla 8.
Ruta de entrada: \\./UNC/Akamai.com/file.wav |
|
---|---|
CreateFile |
MapUrlToZone |
UNC\Akamai.com\file.wav |
./UNC/Akamai.com/file.wav |
Tabla 8: Rutas de salida para las funciones CreateFile y MapUrlToZone
Llegado este punto, CreateFile concluye que su salida es una ruta UNC y que Akamai.com es el nombre de host.
En cambio, MapUrlToZone determina la siguiente información:
Esquema: file://
Host: . (punto)
Ruta: /UNC/Akamai.com/file.wav
URI absoluto: file://./UNC/Akamai.com/file.wav
Resulta que cuando el URI absoluto empieza por "file://./" (donde el host es "."), el código interpreta el nombre compartido como parte del espacio de nombres de dispositivos DOS (Figura 3). Por lo tanto, "file://./unc/" hace referencia al espacio de nombres UNC.
Como aclaración, ambas funciones consideran que nuestra ruta de entrada es una ruta UNC, pero de un tipo diferente: CreateFile la trata como una ruta de dispositivo local de Windows, mientras que MapUrlToZone la ve como una URL.
Al llegar a este punto, podemos generar confusión entre las dos funciones. Por desgracia, si no hacemos alguna trampa, MapUrlToZone Seguiría interpretando Akamai.com como el nombre de host, y puesto que este nombre de host es un dominio de Internet, la función devolverá 3, por lo que no se trata de una omisión. Tenemos que encontrar otra forma de abusar del proceso de análisis.
Más adelante, MapUrlToZone utiliza una función interna denominada SetPath para operar en el componente de ruta (Tabla 9).
CreateFile |
SetPath |
---|---|
Si RtlPathTypeLocalDevice → Avanzar 4 caracteres |
|
Omitir espacios finales |
|
Convertir '/' a '\' |
|
Contraer '\' repetida |
|
Eliminar componentes '.' y '..' |
Eliminar componentes '.' y '..' |
Tabla 9: Comparación de operaciones completadas entre CreateFile y SetPath
Nuevamente, podemos aprovechar la diferencia entre las operaciones llevadas a cabo por las dos funciones. Por nuestra vulnerabilidad anterior, sabemos que añadir una barra diagonal adicional puede provocar una omisión, por lo que tiene sentido volver a intentarlo. CreateFile simplemente eliminará la barra diagonal adicional.
Con MapUrlToZone, CreateUri devuelve el URI absoluto "file://./unc//Akamai.com/file.wav". Este URI se transfiere a GetZoneFromUriInternal, lo que lleva internamente a otra llamada a CreateUri.
¿Y por qué es un problema? Dado que CreateUri ha recibido una URL, la convierte de nuevo en una ruta de Windows mediante PathCreateFromUrlW. La ruta de Windows devuelta es "\\.\UNC\\Akamai.com\test.wav". La versión corregida ahora sabe eliminar la barra diagonal adicional y, por lo tanto, entiende correctamente que Akamai.com es el nombre de host.
Eso significa que necesitamos un abuso más complejo de la diferencia entre CreateFile y SetPath. En esta ocasión, abusaremos de dos diferencias:
CreateFile contrae los separadores de ruta repetidos.
CreateFile elimina los componentes '.' y '..' después de la contracción de los separadores de ruta repetidos.
Una ruta que abusa de ambas diferencias es \\./UNC/C://../Akamai.com/file.wav. Su procesamiento se detalla en el diagrama de flujo de la Figura 4.
Fig. 4: Diagrama de flujo de la ruta que analizan las dos funciones
Ya sabemos que la ruta final de CreateFilese tratará como una ruta UNC. En cuanto a la salida de SetPath, MapUrlToZone va a llamar a GetZoneFromUriInternal con el URI absoluto file://./UNC/C:/Akamai.com/file.wav. En esta ocasión , PathCreateFromUrlW convierte esta URL a la ruta de Windows "\\.\UNC\C:\Akamai.com\file.wav". Esta es una ruta local y, por lo tanto , MapUrlToZone devuelve 0 (local). ¡Hemos encontrado una vez más una omisión excelente!
Para corregir el problema, el código llama ahora a NormalizeDosDevicePrefix Para que convierta las barras diagonales en barras diagonales inversas, lo cual evita confusiones en la detección de una ruta del dispositivo local.
Detección y mitigación
Microsoft publicó una orientación completa para la detección y mitigación de la vulnerabilidad original de Outlook. A partir de nuestra observación, todos los métodos especificados se aplican a la nueva vulnerabilidad, ya que no dependen de la URL especificada en la propiedad PidLidReminderFileParameter .
Recomendamos que las organizaciones utilicen la microsegmentación para bloquear las conexiones SMB salientes a direcciones IP públicas remotas. Además, le recomendamos que desactive NTLM en su entorno o que agregue usuarios al grupo de usuarios protegidos, que impide el uso de NTLM como mecanismo de autenticación.
El bloqueo de las conexiones SMB salientes y la desactivación de NTLM pueden ayudar a evitar el robo de credenciales. Sin embargo, cuando las solicitudes SMB fallan, Windows pasa a WebDAV si está habilitado. El robo de credenciales no se puede explotar través de WebDAV, pero la descarga del archivo de sonido sigue siendo posible, que es el segundo paso en nuestra cadena de RCE.
¿Por qué parar ahora?
En esta publicación, hemos detallado el proceso de investigación que condujo al descubrimiento de las dos omisiones, incluido su análisis de la causa raíz. Como hemos mostrado, el código de análisis de las rutas de Windows es complejo y suele provocar vulnerabilidades. A los investigadores de seguridad que detectan código de gestión de rutas, les recomendamos que piensen en la superficie de ataque que presenta.
Aparte de la omisión de MapUrlToZone en el contexto de Outlook, no podemos descartar la posibilidad de que esas vulnerabilidades también puedan provocar omisiones Mark-of-the-Web (MotW).
Aparte de la capacidad de filtrar credenciales NTLM, también tenemos la capacidad de descargar y reproducir un archivo de sonido arbitrario. Ahora es el momento de leer la parte 2 de esta serie del blog, en la que se detalla la vulnerabilidad de análisis de sonido.