Плани щодо посилення механізму захисту W^X в OpenBSD
Тео Де Раадт поділився планами посилення механізму захисту пам'яті W^X (Write XOR Execute). Суть механізму в тому, що сторінки пам'яті процесу не можуть бути доступні одночасно на запис і виконання. Таким чином, код може бути виконаний тільки після заборони запису, а запис до сторінки пам'яті можливий лише після заборони виконання. Механізм W^X допомагає захистити програми в просторі користувача від типових атак, що здійснюються через переповнення буфера, у тому числі від переповнень стека та активний у OpenBSD за замовчуванням.
З початку робіт над W^X було зрозуміло, що це довга дорога, оскільки існує значна кількість додатків, які використовують JIT. Реалізації JIT можна розділити на три категорії:
Перемикаючі пам'ять між W і X станами, упокорюючись зі «вартістю» системного виклику mprotect.
Створюють псевдоніми між парою W і X відображень однієї й тієї пам'яті.
Найбільш "брудний" варіант - вимагають моделі пам'яті W | X, що допускає одночасне здійснення запису та виконання.
В даний час стало значно менше програм, що використовують третій варіант і більше, що використовують перший і другий. Тим не менш, так як було необхідно запускати і програми з W|X JIT (головним чином, Chromium і Iridum), була додана опція монтування файлової системи wxallowed, яка дозволяла використовувати пам'ять одночасно і для запису і для виконання, у випадку, якщо виконуваний ELF-файл відзначений маркером wxneeded, а самі додатки додатково захищалися, використовуючи механізми заставу и розкрити для обмеження списку використовуваних системних дзвінків та доступних для програми частин файлової системи відповідно.
Для подальшого ускладнення експлуатації вразливостей у подібних додатках запропоновано доповнення механізму MAP_STACK, яка перевіряє, чи виконується системний виклик із доступної для запису сторінки пам'яті. Якщо сторінка доступна для запису, процес буде завершено. Таким чином, зловмисник не зможе використовувати системні виклики і буде змушений намагатися знайти потрібні гаджети в реалізації JIT або навіть виконувати більш важку роботу з виявлення заглушок системних викликів безпосередньо всередині випадково пов'язаного libc.
Процеси Chrome/Iridium і так досить надійно захищені за допомогою pledge і unveil, але позбавлення можливості використовувати, наприклад, системний виклик write(2), очевидно, має певну перевагу, оскільки створює додаткові складності, що атакує. Втім, складнощі можуть виникнути й у тому випадку, якщо реалізація JIT використовує нативні системні виклики з пам'яті W|X. Однак є підстави сподіватися, що з подібним не доведеться зіткнутися, оскільки ABI неодноразово змінювалося, але ніхто ніколи не повідомляв про проблеми.
Зміни доступні в регулярних снапшотах гілки OpenBSD-Сurrent, всі зацікавлені запрошуються до тестування.
Окремого коментаря з боку Тео заслужили пов'язані новини про появу в Chrome/Iridium режиму JITless. На його думку, це прийнятно для деяких моделей використання, однак, ймовірно, не для всіх, тому що в даному режимі явно зросте навантаження на процесор. Зараз Chrome в основному буде працювати, якщо відключити «wxallowed» для /usr/local, хоч і ймовірні проблеми з деякими розширеннями (наприклад наводиться ghostery). Так чи інакше, Тео сподівається, що повноцінна робота в JITless-режимі буде доведена до робочого стану найближчим часом.