Vulnerabilidad en Visual Studio CVE-2024-30052

Este artículo examina la vulnerabilidad CVE-2024-30052 recientemente descubierta, que permite a los atacantes utilizar archivos de volcado para ejecutar código malicioso a través de Visual Studio. El estudio cubre el proceso de descubrimiento de este problema, los mecanismos vulnerables de los PDB integrados y los detalles de una explotación exitosa, destacando la importancia de prestar atención a la seguridad incluso en herramientas de desarrollo familiares.

El artículo está dedicado a la vulnerabilidad CVE-2024-30052, que permite ejecutar código arbitrario al depurar archivos de volcado en Visual Studio.

El investigador ynwarcs descubrió e informó por primera vez el problema a Microsoft en agosto de 2023, y la compañía lanzó una actualización para corregir la falla en junio de 2024. Un especialista de ynwarcs compartió algunos detalles sobre esta vulnerabilidad y también proporcionó un código PoC.

Muchos profesionales a menudo necesitan depurar archivos de volcado en Visual Studio. Esto es extremadamente útil para investigar fallas difíciles de reproducir o condiciones del programa que queremos prevenir. A menudo, estos volcados provienen de fuentes no confiables: la mayoría de las grandes empresas que implementan aplicaciones nativas en Windows, por ejemplo, utilizan sistemas automatizados de detección de fallos en los que se recopila un archivo de volcado como parte de la telemetría y se carga en un portal al que los desarrolladores tienen acceso para realizar análisis de fallos. . Por ejemplo, Google utiliza su versión personalizada de crashpad para capturar e informar fallos en Google Chrome.

Esto expone potencialmente a los desarrolladores a ataques mediante archivos de volcado. Si hay una vulnerabilidad en Visual Studio que puede activarse al abrir un archivo de volcado especialmente diseñado, un atacante podría insertar ese volcado en el sistema de informes de fallas y simplemente esperar a que el desarrollador lo abra. Tampoco es raro que un usuario final envíe manualmente un archivo de volcado, por ejemplo a través de un ticket de soporte, lo que aumenta las posibilidades de que un desarrollador abra el archivo. La principal superficie de ataque reside en los archivos PDB, que se pueden proporcionar junto con el archivo de volcado (con extensiones arbitrarias si es necesario) y que VS abrirá fácilmente durante la depuración. En general, los BPD se consideran bastante inseguros:

  • Pueden contener renderizadores que son capaces de ejecutar código arbitrario al intentar renderizar algunos datos en VS.
  • Pueden contener una configuración de servidores de origen que ejecutan comandos arbitrarios al intentar recuperar el archivo de origen.

Sin embargo, los renderizadores especificados a través de archivos PDB están deshabilitados al depurar volcados, y los comandos del servidor de origen también están deshabilitados de forma predeterminada y requieren la habilitación manual por parte del usuario. Por lo tanto, en investigaciones anteriores, me concentré en encontrar vulnerabilidades que no requirieran el uso de ninguno de estos componentes, y encontré muchas que Microsoft parcheó posteriormente. La mayoría de ellos estaban en msdia140.dll , una biblioteca utilizada para analizar y consultar datos de archivos PDB. Todos estos problemas fueron errores de corrupción de memoria. Aunque algunos de ellos eran bastante explotables, me pareció que era poco probable que se utilizaran de manera realista en ataques reales.

El año pasado, ynwarcs decidió investigar otras bibliotecas que Visual Studio utiliza durante sus sesiones de depuración con la esperanza de descubrir una falla lógica que permitiría ejecutar el código sin recurrir a la corrupción de la memoria. Finalmente, ynwarcs encontró una manera de ejecutar código arbitrario al depurar un archivo de volcado administrado.

PDB integrados, fuentes integradas

Hace unos años, Microsoft introdujo el formato Portable PDB. Este formato fue pensado como un reemplazo del formato MSF clásico para módulos administrados, principalmente para admitir multiplataforma y optimizaciones sobre el formato estándar. Al mismo tiempo, se agregó la capacidad de incrustar archivos PDB portátiles en el ejecutable en tiempo de compilación mediante el comando -debug:embedded . El procedimiento de implementación no está particularmente documentado, al menos que yo sepa, pero no es difícil descubrir cómo se logra, por ejemplo mediante ingeniería inversa en algunas bibliotecas de C# Runtime y siguiendo sugerencias en la documentación pública de Microsoft.

  1. Primero, se crea un archivo PDB portátil normal y luego se comprime utilizando la secuencia Deflate.
  2. Se crea un “blob” de datos que contiene dos valores de 32 bits (número mágico (“MPDB”) + tamaño de PDB sin comprimir) seguidos de los datos de PDB comprimidos.
  3. Este blob se inserta en el ejecutable en una sección especial y hace referencia a la entrada del directorio de depuración de PE a través de:
    • DataPointer apuntando a un blob.
    • DataSize igual al tamaño del blob.
    • IsPortableCodeView establecido en verdadero .
    • Tipo establecido en 17 (es decir, PDB portátil integrado).

Podemos ver esto en acción, por ejemplo, usando PETools para ver una DLL central de .NET compilada con una PDB integrada:

La entrada del directorio de depuración en la parte inferior es del tipo 17, y podemos ver que los datos a los que apunta tienen el formato “MPDB” seguido de 0x2910 (la longitud del PDB sin comprimir) y luego los datos del PDB comprimidos.

Con el tiempo, se han solicitado la posibilidad de incrustar archivos fuente en el PDB. Esto ahora es posible de varias maneras, como estableciendo EmbedAllSources en verdadero en el archivo vcxproj o especificando el indicador -embed en la línea de comando del compilador. Los archivos fuente están integrados en el “Secuencia de fuentes integradas” en un archivo PDB portátil y un depurador puede recuperarlos fácilmente si es necesario.

Las dos características descritas anteriormente son muy útiles cuando se desarrolla de forma iterativa un proyecto administrado y se depura una versión heredada. Si bien esto no sucede con frecuencia, suele ser muy frustrante (y a menudo imposible) depurar un volcado antiguo o una versión antigua de un ejecutable sin una copia de seguridad del PDB o del archivo fuente asociado a él. Con las PDB y las fuentes integradas, la información se almacena directamente en el ejecutable (y, por lo tanto, en el volcado si se captura con la memoria llena), lo que brinda una experiencia de depuración completa.

Archivos no imprimibles

Cuando depura archivos de volcado, VS confía completamente en los datos que contienen. Esto significa que Visual Studio aceptará sin problemas las PDB integradas y las fuentes dentro de esas PDB. Incluso si se prefieren los datos en el disco, si faltan, se utilizarán los datos ubicados en el archivo de volcado. Mientras pensaba en posibles formas de abusar de la confianza que VS deposita en los archivos fuente incrustados, recordé un comportamiento extraño que encontré antes. Se sabe que VS admite la apertura de archivos de imágenes, pero solo ciertos formatos como JPG o PNG. Un día intenté abrir un archivo WebP y recibí el siguiente mensaje:

Al hacer clic en “Aceptar” o “X”, el archivo WebP se abrió en Paint:

Se supone que VS puede llamar a programas externos si no sabe cómo manejar un tipo de archivo en particular. Ejecuté el depurador para rastrear el código que implementa este comportamiento y obtuve la siguiente pila de llamadas:

... métodos SHELL32 ...
shell32.dll!ShellExecuteW
msenv.dll!CExternalEditorFactory::CreateEditorInstance
msenv.dll!CVsUIShellOpenDocument::LoadCreateEditorInstance
msenv.dll!CVsUIShellOpenDocument::CreateInitEditorInstance
msenv.dll!CVsUIShellOpenDocument::OpenStandardEditor
msenv.dll!CVsUIShellOpenDocument::OpenStandardEditorAsync
...Métodos CLR...
msenv.dll!CVsUIShellOpenDocument::OpenDocumentViaProject2
msenv.dll!CVsUIShellOpenDocument::OpenDocumentViaProject

Durante una breve investigación descubrí que:

  • Al abrir un archivo, VS intentará encontrar el editor/visor interno asociado con la extensión del archivo.
  • Si no se encuentra ningún editor asociado, el archivo se abrirá en un editor (de texto) estándar.
  • Si el archivo contiene caracteres no imprimibles, la ejecución saltará al código que se muestra arriba.

El elemento más interesante de la pila de llamadas es CExternalEditorFactory::CreateEditorInstance . Aquí está su implementación descompilada:

HRESULT CExternalEditorFactory::CreateEditorInstance(..., const wchar_t* filePath, ...)
{
    const wchar_t* extensiónPtr = wcsrchr(filePath, L'\\');
    if (extensionPtr && (CompareFilenames(extensionPtr, L".exe") == 0 || CompareFilenames(extensionPtr, L".com") == 0))
        devolver 0x80041FEB;

    bool useOpenAssoc = falso;
    wchar_t assocProgramPath[MAX_PATH + 4];
    uint32_t assocProgramPathLen = MAX_PATH;
    HRESULT assocRes = AssocQueryStringW(ASSOCF_NOTRUNCATE | ASSOCF_VERIFY, ASSOCSTR_EXECUTABLE, extensionPtr, L"edit", assocProgramPath, &assocProgramPathLen);
    si (FALLÓ (assocRes))
    {
        useOpenAssoc = verdadero;
        assocProgramPathLen = MAX_PATH;
        assocRes = AssocQueryStringW(ASSOCF_NOTRUNCATE | ASSOCF_VERIFY, ASSOCSTR_EXECUTABLE, extensionPtr, L"open", assocProgramPath, &assocProgramPathLen);
    }
    si (FALLÓ (assocRes))
        devolver 0x80041FEB;

    ...
    // Compruebe si el nombre del programa coincide con devenv.exe o nombres especiales:
    // VBExpress, VCSExpress, VJSExpress, VCExpress, VWDExpress, VPDExpress, VSWinExpress, WDExpress, VSLauncher, vsgd, vsga
    // si coincide, se cancela la operación
    ...

    if (CompareFilenames(filePath, assocProgramPath)!= ​​0)
    {
        wchar_t assocProgramShortPath[MAX_PATH+1];
        GetShortPathNameW(a3, assocProgramShortPath, MAX_PATH);
        if (CompareFilenames(assocProgramPath, assocProgramShortPath)! = 0)
        {  
            SHELLEXECUTEINFOW execInfo = {};
            ... // configurando los parámetros execInfo
            execInfo.lpVerb = useOpenAssoc? "abrir": "editar";
            execInfo.lpFile = rutadelarchivo;
            execInfo.nShow = 1;
            ShellExecuteW(&execInfo);
            ...
        }
    }
    ...
}

Esta función requiere varios parámetros, incluida la ruta completa al archivo que se va a abrir. Las llamadas a AssocQueryStringW están diseñadas para encontrar un programa predeterminado que interactúe con una extensión de nombre de archivo. VS primero busca el programa asociado con la acción “editar” y, si no encuentra ninguno, utiliza el programa asociado con la acción “abrir”. Si se encuentra alguno de estos programas, se realizan varias comprobaciones y, si todas pasan, se llama a ShellExecuteW para abrir el archivo en el programa asociado.

Este comportamiento indica una posible ruta de ataque mediante el uso de archivos fuente incrustados:

  • Si podemos forzar a VS a abrir un archivo fuente incrustado aleatorio al depurar un volcado,
  • Si podemos forzar que este archivo fuente tenga una extensión arbitraria,
  • Si hay una extensión asociada con un programa que ejecutará código arbitrario basado en los datos del archivo cuando se abra,

entonces podemos ejecutar código arbitrario simplemente depurando el archivo de volcado.

Creación de prueba de concepto

Para probar el realismo del ataque, intenté crear un poc simple en el que reemplazaría el archivo fuente legítimo en el PDB incrustado con un archivo PDF de ejemplo, con la esperanza de que VS:

  • Lo reconoce como un archivo fuente incorporado legítimo,
  • Lo abrirá a través de un editor externo durante una sesión de depuración, incluidas las sesiones de depuración de volcado.

Elegí PDF porque sabía que probablemente contendría caracteres no imprimibles y definitivamente tendría un programa asociado en el sistema (Firefox en este caso). La creación del poc requirió los siguientes pasos:

  1. Cree un proyecto .NET simple y cambie el nombre del archivo principal de Program.cs a Program.pdf .
  2. Compile el proyecto con el indicador -debug:portable . Esto crea un archivo exe y un archivo dll con PDB portátiles en el disco. El archivo fuente está incrustado en la PDB asociada con la DLL.
  3. Modifique el archivo PDB portátil para reemplazar los datos del archivo fuente original con los datos del archivo PDF que queremos incrustar.
    • Para hacer esto, encontré exactamente en qué parte del archivo se serializa el archivo fuente incrustado. Su formato se describe en la especificación de formato.
    • Luego reemplacé los datos con los datos del PDF. Estos datos se comprimen usando deflactar. Para facilitarme las cosas, hice el archivo fuente original lo suficientemente grande como para acomodar los nuevos datos sin moverlos y correr el riesgo de romper el formato.
    • También actualicé el hash del archivo fuente en la tabla de documentos para evitar que Visual Studio lo rechace como no válido.
  4. Incruste el PDB portátil recién creado en el archivo ejecutable. Utilicé un programa personalizado para esto porque no sabía que existían herramientas que pudieran hacer esto. El programa simplemente expandió el directorio de depuración del ejecutable e insertó una nueva sección de datos PDB en él, a la que hacía referencia la nueva entrada.
  5. Ejecute el ejecutable, déjelo bloquear y descargue toda la memoria. Para capturar volcados automáticamente, seguí este tutorial y configuré DumpType en 2 (volcado de memoria completa).
  6. Elimine/cambie el nombre de los archivos exe, dll, pdb y fuente del disco. Esto obligará a VS a utilizar la información incrustada del volcado en lugar de los datos disponibles en el disco.
  7. Abra el archivo de volcado en VS y seleccione “Depurar con administrado”.

En este punto me encontré con el mismo cuadro de mensaje que se muestra arriba y al hacer clic en “Aceptar” o “X” abrí el archivo PDF de muestra en Firefox. Esto confirmó que la ruta del código problemática podría deberse al depurar archivos de volcado y abrir fuentes incrustadas.

Búsqueda ACE

Después de confirmar la hipótesis, quedaba encontrar extensiones que pudieran usarse para lograr ACE (Ejecución de código arbitrario). Visual Studio filtra algunas extensiones, como .exe y .com , pero estaba convencido de que había otras que se escaparían. Terminé escribiendo un programa que recorre en iteración todas las extensiones posibles de 2, 3 y 4 letras y genera los programas asociados con ellas usando AssocQueryStringW .

Sólo me llevó unos 20 minutos y pronto tuve una lista completa de asociaciones en mi PC. Si bien muchos de los archivos podrían usarse para ejecutar código arbitrario cuando se abren a través del programa predeterminado, la mayoría de ellos tenían una asociación de “edición” con un editor de texto, lo que no funcionó para nosotros. Después de un análisis cuidadoso, identifiqué tres extensiones que parecían particularmente adecuadas:

  • CHM o HTML compilado por Microsoft. Los archivos de este tipo se abren usando hh.exe . Este formato se utiliza principalmente para archivos de ayuda en Windows y, a veces, aparece si accidentalmente presiona F1 en algunos programas. Los archivos CHM pueden contener código VB arbitrario que se ejecutará cuando se abran.
  • HTA , o aplicación HTML, asociada a mshta.exe . Estos también son archivos HTML extendidos que pueden contener código VB que se ejecuta cuando se abre el archivo.
  • PY o secuencias de comandos Python. En una instalación limpia de Windows no existe tal asociación, pero es probable que el desarrollador tenga instalado Python, en cuyo caso la extensión se asociará con Python. Por supuesto, abrir un script de Python puede provocar la ejecución de código arbitrario.

De forma predeterminada, los archivos CHM se compilan y contienen caracteres no imprimibles. Por otro lado, los archivos HTA y PY están basados ​​en texto y requieren incrustar caracteres no imprimibles manteniendo su funcionalidad. Esto no supone un gran problema:

  • Agregar caracteres que no se imprimen después de la etiqueta HTML de cierre en la fuente HTA no impide que hh.exe ejecute el código especificado dentro de la etiqueta.
  • Agregar un comentario seguido de algunos caracteres nulos en un script de Python no impide que se ejecute el resto del código.

Operación

Con todo esto en mente, es hora de crear un exploit. Sin embargo, en lugar de seguir los mismos pasos que describí anteriormente, escribí un programa C# que automatiza todo el proceso y lo alimenté con tres archivos diferentes (CHM/HTA/PY) para crear tres volcados diferentes. Tan pronto como comience a depurar cualquiera de estos en VS, se iniciará calc.exe , demostrando ACE.

En GitHub hay disponible un programa que crea un archivo de volcado basado en el archivo fuente de entrada. Puede encontrar instrucciones sobre cómo usarlo en el archivo README del repositorio . Aquí hay una demostración de PoC que utiliza un archivo de entrada CHM que ejecuta calc.exe :

Corrección

No tuve la paciencia para aplicar ingeniería inversa completa a la solución. Pero puedes ver un nuevo cambio en CVsUIShellOpenDocument::OpenStandardEditor , que se parece a esto:

HRESULT CVsUIShellOpenDocument::OpenStandardEditor(..., banderas uint64_t, ...)
{
    //++++++++
    si (banderas y 0xF0000000)
    {
        devolver 0x80042010;
    }
    //++++++++
    
    ...
    CVsUIShellOpenDocument::CreateInitEditorInstance(...)
}

El bit alto del parámetro flags pasado a la función ahora se establece al abrir fuentes incrustadas durante las sesiones de depuración, pero no se establece cuando, por ejemplo, se arrastra un archivo a un VS inactivo. Si se establece, la función se niega a continuar ejecutando CreateInitEditorInstance , lo que daría como resultado el comportamiento descrito anteriormente.

Si intenta abrir manualmente el archivo fuente en VS mientras depura un volcado, ahora aparece el siguiente mensaje, lo que significa que VS ni siquiera permite que el usuario caiga manualmente en la trampa:

La vulnerabilidad CVE-2024-30052 demuestra cuán crítica es la seguridad de las herramientas para los desarrolladores. El error, que puede causar la ejecución de código arbitrario, abre la puerta para que los atacantes ataquen a las empresas a través de archivos de volcado confiables y PDB integrados. Este caso resalta lo importante que es actualizar periódicamente las herramientas de desarrollo, monitorear de cerca los informes de fallas y ser consciente de los riesgos potenciales al trabajar con archivos externos.
#Seguridad ? #Ciberseguridad ?️ #VisualStudio ? #Vulnerabilidad ? #Desarrolladores ?‍? #PDBfiles ? #CVE2024 ? #Exploit ? #Malware ⚠️ #Actualización ?

0 Votes: 0 Upvotes, 0 Downvotes (0 Points)

Donaciones
STREAMER

[sp_wpcarousel id="11665"]

Segui Nuestras Redes
  • LinkedIn17.3k+
  • Whatsapp1.7k+

Advertisement

Loading Next Post...
Encontranos
Search Trending
Loading

Signing-in 3 seconds...

Signing-up 3 seconds...

All fields are required.