
Эксплойт для CVE-2024-21980, направленный на прошивку AMD SEV для расшифровки произвольной памяти выведенных из эксплуатации гостей SEV-SNP через обход принудительного выполнения командного буфера.
Этот репозиторий содержит эксплойт для уязвимости в прошивке SEV. Эксплойт позволяет расшифровывать произвольную память гостя SEV-SNP после его вывода из эксплуатации.
Протестировано на версии 1.55.16 (последняя на момент написания).
В прошивке SEV есть таблица master_handler_table, содержащая указатели на функции для всех команд, а также несколько дополнительных свойств, относящихся к командам. Два из этих дополнительных свойств — cmd_buf_type и snp_cmd_buf_enforcement. cmd_buf_type определяет, следует ли копировать буфер команды в память хоста и/или из неё. snp_cmd_buf_enforcement определяет, должны ли эти операции копирования подвергаться проверкам, подтверждающим, что память, поддерживающая буфер команды, находится в состоянии FIRMWARE или DEFAULT. Команды, для которых cmd_buf_type имеет значение CMD_BUF_OUTPUT_ONLY, CMD_BUF_INPUT_AND_OUTPUT или CMD_BUF_INPUT_AND_OUTPUT_ERROR, должны иметь snp_cmd_buf_enforcement, установленное в true. В противном случае запись вывода команды может привести к повреждению памяти внутри области, покрываемой RMP. snp_cmd_buf_enforcement установлено в true для всех таких команд, за одним исключением — SEV_MCMD_ID_ATTESTATION: у этой команды cmd_buf_type установлено в CMD_BUF_INPUT_AND_OUTPUT_ERROR, но snp_cmd_buf_enforcement установлено в false. В результате можно выполнить SEV_MCMD_ID_ATTESTATION с буфером команды, указывающим на память, покрываемую RMP, и эта память будет повреждена после записи вывода.
Я не вижу, зачем SEV_MCMD_ID_ATTESTATION нужно было бы делать исключением; мне кажется вероятным, что это могло быть опечаткой/ошибкой копирования.
SEV_MCMD_ID_ATTESTATION записывает только в одно поле length (4 байта) в буфере команды, поэтому только эти байты мы можем использовать для повреждения памяти. SEV_MCMD_ID_ATTESTATION всегда записывает одно и то же значение — 0x000000d0. К счастью, к буферу команды нет требований по выравниванию, поэтому мы можем многократно сдвигать буфер команды, чтобы повредить больший диапазон непрерывной памяти. Мы воспользуемся этим, чтобы повредить первые 16 байт страницы контекста гостя статическим шаблоном. Эти первые 16 байт содержат начальное значение UMC-ключа, и, принудительно установив его в статическое значение, мы можем заставить ключ шифрования гостя стать статическим.
Предоставленный здесь эксплойт в значительной степени основан на том, который я предоставил для SWPSIRT-2684/CVE-2023-31355.
Чтобы использовать уязвимость, можно выполнить следующие шаги:
SEV_MCMD_ID_ATTESTATION. Оставьте этого гостя работающим.0x2000 для гостя-жертвы. Любой другой адрес в области, покрываемой RMP, тоже подойдет, хотя фиксированный адрес полезен для отладки.0x2000 для гостя-атакующего. Это должен быть тот же адрес, что использовался на шаге 1.SNP_DBG_ENCRYPT для расшифровки памяти гостя-жертвы, используя страницу контекста гостя-атакующего. Это удастся, поскольку гость-жертва и гость-атакующий имеют одинаковое начальное значение UMC-ключа.Влияние здесь должно быть, по крайней мере, таким же, как и в случае SWPSIRT-2684. На данный момент мне неясно, можно ли использовать эту ошибку для расшифровки памяти работающего гостя до его вывода из эксплуатации.
snp_cmd_buf_enforcement должно быть установлено в true для SEV_MCMD_ID_ATTESTATION.
Интересно, что патчи поддержки хост-системы Linux KVM не нужно обновлять, поскольку они уже перечисляют SEV_CMD_ATTESTATION_REPORT в sev_cmd_buf_writable как команду, требующую, чтобы её буфер команды находился в состоянии FIRMWARE. Изменения могут потребоваться или не потребоваться для других гипервизоров.