
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:
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.
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.
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.
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:
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:
entonces podemos ejecutar código arbitrario simplemente depurando el archivo de volcado.
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:
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:
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.
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:
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:
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 :
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 ?