
Разбор CVE-2021-43229
Уязвимость повышения привилегий Windows NTFS
Отличается от:
Патч: 14 декабря 2021 г.
Согласно @AravGarg3 в Twitter, CVE-2021-43229 кажется эксплуатируемым и связан с целочисленным переполнением.
Источник: https://twitter.com/AravGarg3/status/1479447843458863104
| Минорные версии Windows 10 | Даты выпуска |
|---|---|
| 1387 | 11/22/2021 |
| 1415 | 12/14/2021 |
Используя BinDiff с IDA Pro, результат сравнения патчей со следующими изменениями:
Три кандидата выходят на первый план:
Согласно Руководству по обновлениям безопасности (Security Update Guide) от Microsoft за декабрь, четыре CVE связаны с NTFS:
CVE-2021-43240, по-видимому, связан с NtSetShortNameInfo.
NtfsRenameToPrivateDir, TxfAllocateAndStoreNameForTxLogging и TxfAllocateFullFilePathForChangeNotify все три имеют одну и ту же новую проверку длины и, по-видимому, относятся к CVE-2021-43229, CVE-2021-43230 и CVE-2021-43231, не обязательно в таком порядке. В настоящее время невозможно узнать, какая к чему относится, Microsoft немного скупа на эту информацию.
Во всех трех CVE возникает целочисленное переполнение при вычислении размера выделения (длина пути каталога + длина имени файла), что приводит к переполнению буфера в пуле (pool-based buffer overflow) с последующими двумя операциями memmove пути каталога и имени файла.
NtfsRenameToPrivateDirПуть к NtfsRenameToPrivateDir показан ниже:
NtfsCommonSetInformation
|__________________
| |
v v
NtfsSetLinkInfo NtfsSetRenameInfo
|__________________|
|
v
NtfsRemoveSupersededTarget
|
v
NtfsRenameToPrivateDir
Прежде всего, чтобы вызвать NtfsCommonSetInformation, просто вызовите NtSetInformationFile. Затем, чтобы пройти через NtfsSetLinkInfo и NtfsSetRenameInfo, используйте соответственно FileLinkInformationEx и FileRenameInformationEx в качестве класса информации о файле в NtSetInformationFile.
Чтобы добраться до NtfsRemoveSupersededTarget через NtfsSetRenameInfo, необходимо установить флаги FILE_RENAME_REPLACE_IF_EXISTS и FILE_RENAME_POSIX_SEMANTICS. Переименуйте файл с именем существующего, чтобы получить доступ к NtfsRemoveSupersededTarget. Для NtfsRenameToPrivateDir это немного сложнее, потому что заменяемый файл должен быть открыт любым процессом.
К сожалению, проверка длины выполняется перед вызовом NtfsRemoveSupersededTarget.
Метод с NtfsSetLinkInfo аналогичен NtfsSetRenameInfo, только имена флагов различаются, их значения остаются теми же. Но так же, как и в NtfsSetRenameInfo, перед вызовом NtfsRemoveSupersededTarget выполняется еще одна проверка.
TxfAllocateAndStoreNameForTxLoggingПуть к TxfAllocateAndStoreNameForTxLogging показан ниже:
NtfsCommonCreate
|
v
NtfsCreateNewFile
|
v
TxfNewFileCreate
|
v
TxfAllocateAndStoreNameForTxfLogging
Прежде всего, чтобы вызвать NtfsCommonCreate, просто вызовите CreateFile.
Функция TxfNewFileCreate имеет префикс Txf, что означает "Transactional NTFS" (транзакционная NTFS), и вызывается при создании транзакционного файла. TxfAllocateAndStoreNameForTxfLogging вызывается в процессе для хранения пути к транзакционному файлу.
Необходимы только два вызова:
Уязвимый код TxfAllocateAndStoreNameForTxLogging показан ниже:
...
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
...
Чтобы вызвать переполнение, необходимо создать файл чрезмерной длины, более 0xFFFF байт (32767 символов).
Проблема в том, что имя файла или каталога не может быть длиннее 256 символов, включая нулевой символ. Чтобы решить эту проблему, потребуется использование глубоких подпапок. Как ни странно, это не так просто, даже при успешном создании подпапок подфайл создать не удается, вероятно, из-за некоторых проверок, выполняемых ранее.
Используя строку адреса explorer, можно заметить формат, используемый для отображения пути к каталогу. Это не то, что я ожидал: вместо использования «классического» пути explorer использует устаревший формат DOS, короткий формат 8.3.
Сохранение создания подпапок как ранее и использование коротких имен для подкаталогов при создании файла решают задачу.
Важно отметить, что к переполненному размеру будет добавлено 16 байт — размер UNICODE_STRING, который будет представлять конечный путь. Это связано с тем, что запрашиваемая память будет содержать UNICODE_STRING, за которым следует буфер этого UNICODE_STRING.
Метод:
Текущие условия:
Интересный отчет от Synacktiv на SSTIC 2020 может стать идеей для изучения, нацелившись на VS Heap.
Подобный случай эксплуатации CVE-2020-17087 был представлен PixiePoint Security с использованием упомянутой выше техники.
| Сходство | Уверенность | Функция | Информация |
|---|
| NOK | 0.98 | 0.99 | NtfsCommonSetInformation$fin$0 | Модификации переходов |
| 0.97 | 0.99 | NtSetShortNameInfo | ||
| 0.96 | 0.99 | NtfsUpdateSecurity | ||
| NOK | 0.91 | 0.94 | NtfsRenameToPrivateDir$fin$1 | Модификации переходов |
| 0.89 | 0.98 | NtfsInitializeFileInDirectory | ||
| OK | 0.88 | 0.95 | TxfAllocateAndStoreNameForTxLogging | Проверка длины |
| OK | 0.87 | 0.93 | NtfsRenameToPrivateDir | Проверка длины |
| OK | 0.81 | 0.95 | TxfAllocateFullFilePathForChangeNotify | Проверка длины |
| 0.76 | 0.94 | NtfsCommonSetInformation |