Атака может быть применена к приложениям, в которых при проверках используется сравнение отличий значений от нуля. Пример уязвимого кода:
int auth = 0; ... // код проверки, меняющий значение auth в случае успешной аутентификации if(auth != 0) return AUTH_SUCCESS; else return AUTH_FAILURE;
В контексте данного примера для успешной атаки достаточно добиться искажения любого бита в памяти, приходящейся на 32-разрядную переменную auth в стеке. При искажении любого бита в переменной значение уже не будет равно нулю и условный оператор определит успешное прохождение аутентификации. Подобные шаблоны проверки достаточно распространены в приложениях и встречаются, например, в SUDO, OpenSSH, MySQL и OpenSSL.
Атака может быть применена и на сравнения вида «if(auth == 1)», но в этом случае её проведение усложняется, так как нужно исказить не любой бит из 32, а последний бит. Метод также может использоваться для влияния на значения переменных в процессорных регистрах, так как содержимое регистров может быть на время сброшено в стек при переключении контекста, вызове функций или срабатывании обработчика сигнала. В промежуток времени, пока регистровые значения находятся в памяти, в эту память можно внести искажения и в регистр будет восстановлено изменённое значение.
Для искажения битов применяется одна из модификаций атаки класса RowHammer. Так как память DRAM представляет собой двухмерный массив ячеек, каждая из которых состоит из конденсатора и транзистора, выполнение непрерывного чтения одной и той же области памяти приводит к флуктуации напряжения и аномалиям, вызывающим небольшую потерю заряда соседних ячеек. Если интенсивность чтения большая, то соседняя ячейка может потерять достаточно большой объём заряда и очередной цикл регенерации не успеет восстановить её первоначальное состояние, что приведёт к изменению значения сохранённых в ячейке данных. Для защиты от RowHammer производители чипов добавили механизм TRR (Target Row Refresh), который блокирует искажение ячеек в частных случаях, но не защищает о всех возможных вариатов атаки.
Для защиты от атаки Mayhem рекомендуется использовать в сравнениях не оценку отличий от нуля или совпадения с единицей, а проверку совпадений, используя случайное значение затравки c ненулевыми октетами. В этом случае для выставления нужного значения переменной необходимо точно исказить существенное число битов, что нереалистично, в отличие от искажения одного бита. Пример не подверженного атаке кода:
int auth = 0xbe406d1a; ... // код проверки, выставляющий значение auth в 0x23ab8701 в случае успешной аутентификации if(auth == 0x23ab8701) return AUTH_SUCCESS; else return AUTH_FAILURE;
Указанный метод защиты уже применён разработчиками sudo и вошёл в состав выпуска 1.9.15 как исправление уязвимости CVE-2023-42465. Прототип кода для совершения атаки планируют опубликовать после внесения исправлений в основные уязвимые проекты.
Источник: http://www.opennet.ru/opennews/art.shtml?num=60334