
Recorrido de CVE-2021-43229
Vulnerabilidad de elevación de privilegios de Windows NTFS
Distinto de:
Parche: 14 de diciembre de 2021
Según @AravGarg3 en Twitter, CVE-2021-43229 parece ser explotable y estar relacionado con un desbordamiento de enteros.
Fuente: https://twitter.com/AravGarg3/status/1479447843458863104
| Versiones menores de Windows 10 | Fechas de lanzamiento |
|---|
| 1387 | 22/11/2021 |
| 1415 | 14/12/2021 |
Usando BinDiff con IDA Pro, el resultado del diffing del parche muestra los siguientes cambios:
| Similitud | Confianza | Función | Información | |
|---|---|---|---|---|
| NOK | 0.98 | 0.99 | NtfsCommonSetInformation$fin$0 | Modificaciones de salto |
| 0.97 | 0.99 | NtSetShortNameInfo | ||
| 0.96 | 0.99 | NtfsUpdateSecurity | ||
| NOK | 0.91 | 0.94 | NtfsRenameToPrivateDir$fin$1 | Modificaciones de salto |
| 0.89 | 0.98 | NtfsInitializeFileInDirectory | ||
| OK | 0.88 | 0.95 | TxfAllocateAndStoreNameForTxLogging | Verificación de longitud |
| OK | 0.87 | 0.93 | NtfsRenameToPrivateDir | Verificación de longitud |
| OK | 0.81 | 0.95 | TxfAllocateFullFilePathForChangeNotify | Verificación de longitud |
| 0.76 | 0.94 | NtfsCommonSetInformation |
Tres candidatos destacan:
Según la Guía de actualización de seguridad de Microsoft de diciembre, cuatro CVE están relacionados con NTFS:
CVE-2021-43240 parece estar relacionado con NtSetShortNameInfo.
NtfsRenameToPrivateDir, TxfAllocateAndStoreNameForTxLogging y TxAllocateFullFilePathForChangeNotify tienen los tres la misma nueva verificación de longitud, y parecen estar relacionados con CVE-2021-43229, CVE-2021-43230 y CVE-2021-43231, no necesariamente en ese orden. Actualmente, no es posible saber cuál es cuál, Microsoft es un poco tacaño con esta información.
En los tres CVE ocurre un desbordamiento de enteros durante el cálculo del tamaño de asignación (longitud de la ruta del directorio + longitud del nombre del archivo), lo que provoca un desbordamiento de búfer basado en pool con los dos memmove posteriores de la ruta del directorio y el nombre del archivo.
NtfsRenameToPrivateDirLa ruta a NtfsRenameToPrivateDir se muestra a continuación:
NtfsCommonSetInformation
|__________________
| |
v v
NtfsSetLinkInfo NtfsSetRenameInfo
|__________________|
|
v
NtfsRemoveSupersededTarget
|
v
NtfsRenameToPrivateDir
En primer lugar, para llamar a NtfsCommonSetInformation, simplemente llama a NtSetInformationFile. Luego, para pasar por NtfsSetLinkInfo y NtfsSetRenameInfo, usa respectivamente FileLinkInformationEx y FileRenameInformationEx como clase de información de archivo en NtSetInformationFile.
Para alcanzar NtfsRemoveSupersededTarget a través de NtfsSetRenameInfo, es necesario establecer las banderas FILE_RENAME_REPLACE_IF_EXISTS y FILE_RENAME_POSIX_SEMANTICS. Renombra un archivo con el nombre de uno existente para acceder a NtfsRemoveSupersededTarget. Para NtfsRenameToPrivateDir, es un poco complicado, porque el archivo reemplazado debe estar abierto por algún proceso.
Desafortunadamente, se realiza una verificación de longitud antes de la llamada a NtfsRemoveSupersededTarget.
El método con NtfsSetLinkInfo es similar a NtfsSetRenameInfo, solo los nombres de las banderas difieren, pero sus significados siguen siendo los mismos. Pero al igual que con NtfsSetRenameInfo, se realiza otra verificación antes de la llamada a NtfsRemoveSupersededTarget.
TxfAllocateAndStoreNameForTxLoggingLa ruta a TxfAllocateAndStoreNameForTxLogging se muestra a continuación:
NtfsCommonCreate
|
v
NtfsCreateNewFile
|
v
TxfNewFileCreate
|
v
TxfAllocateAndStoreNameForTxfLogging
En primer lugar, para llamar a NtfsCommonCreate, simplemente llama a CreateFile.
La función TxfNewFileCreate tiene el prefijo Txf que significa "NTFS transaccional" y se llama cuando se crea un archivo transaccionado. TxfAllocateAndStoreNameForTxfLogging se llama durante el proceso para almacenar la ruta del archivo transaccionado.
Solo son necesarias dos llamadas:
El código vulnerable de TxfAllocateAndStoreNameForTxLogging se muestra a continuación:
...
and di, 2
add di, [rsi+UNICODE_STRING.Length] ; File name
add di, [rsp+68h+RelativeNormalizedDirectoryPath.Length] ; OVERFLOW HERE
cmp [rsp+68h+arg_20], r12b
jnz loc_16592C
movzx edx, di
add rdx, size UNICODE_STRING ; NumberOfBytes
mov ecx, cs:PoolType
or ecx, 10h ; PoolType
mov r8d, 'afxT' ; Tag
call cs:__imp_ExAllocatePooliWthTag
...
Para desencadenar el desbordamiento, es necesario crear un archivo con una longitud excesiva, más de 0xFFFF bytes (32767 caracteres).
Un problema que surge es que el nombre de un archivo o directorio no puede superar los 256 caracteres, incluido el carácter NULL. Para resolver esto, será necesario usar subcarpetas profundas. Curiosamente, no es tan fácil, incluso con subcarpetas creadas exitosamente, el subarchivo no se puede crear, seguramente debido a algunas comprobaciones realizadas anteriormente.
Usando la barra del explorador es posible notar el formato utilizado para mostrar la ruta del directorio. No es lo que esperaba, en lugar de usar una ruta "clásica", el explorador usa el formato anticuado de DOS, el formato corto 8.3.
Manteniendo la creación de subcarpetas como antes y usando nombres cortos para los subdirectorios durante la creación del archivo, funciona.
Es importante notar que se agregarán 16 bytes al tamaño desbordado, que es el tamaño de la UNICODE_STRING que representará la ruta final. Esto se debe a que la memoria solicitada contendrá la UNICODE_STRING seguida del búfer de esta UNICODE_STRING.
Método:
Condiciones actuales:
Un artículo interesante de Synacktiv en SSTIC 2020 podría ser una idea para investigar, apuntando a VS Heap.
El CVE-2020-17087, un caso similar de explotación, fue presentado por PixiePoint Security usando la técnica mencionada anteriormente.