Введение
Техника компьютерной безопасности
Адресное пространство случайной компоновки (ASLR) — это техника компьютерной безопасности, предназначенная для предотвращения эксплуатации уязвимостей, связанных с повреждением памяти. Чтобы не дать злоумышленнику надёжно перенаправить выполнение кода, например, на конкретную эксплуатируемую функцию в памяти, ASLR случайным образом располагает в адресном пространстве ключевые области данных процесса, включая базовый адрес исполняемого файла и позиции стека, кучи и библиотек.
История
Проект Linux PaX впервые ввёл термин "ASLR" и опубликовал первую разработку и реализацию ASLR в июле 2001 года в виде патча для ядра Linux. Она считается полноценной реализацией, предоставляющей также патч для рандомизации стека ядра, начиная с октября 2002 года. Первой широко используемой операционной системой, поддерживающей ASLR по умолчанию, стала OpenBSD версии 3.4 в 2003 году, а затем Linux в 2005 году.
Преимущества
Рандомизация адресного пространства затрудняет некоторые виды атак на безопасность, усложняя злоумышленнику предсказание целевых адресов. Например, злоумышленникам, пытающимся осуществить атаку "возврат в libc", необходимо найти код для выполнения, а другим, пытающимся выполнить внедренный в стек shellcode – сначала найти сам стек. В обоих случаях система делает связанные адреса памяти непредсказуемыми с точки зрения атакующего. Эти значения приходится угадывать, и ошибочная догадка обычно приводит к аварийному завершению приложения, которое нельзя восстановить.
Уменьшение энтропии
Злоумышленники могут использовать несколько методов для уменьшения энтропии в рандомизированном адресном пространстве, от простой утечки информации до атак, уменьшающих энтропию на несколько бит за одну попытку (например, с помощью распыления кучи). Мало что можно предпринять для противодействия этому. Информацию о структуре памяти можно получить, используя уязвимости формата строки. Функции формата строки, такие как printf, используют переменный список аргументов; спецификаторы формата описывают структуру этого списка. В силу способа передачи аргументов, каждый спецификатор формата приближается к вершине стека. В конечном итоге можно извлечь указатель возврата и указатель фрейма стека, раскрывая адрес уязвимой библиотеки и адрес известного фрейма стека, что может устранить рандомизацию библиотеки и стека как препятствие для атакующего. Также можно уменьшить энтропию в стеке или куче. Стек обычно должен быть выровнен по 16 байт, что является наименьшим возможным интервалом рандомизации, в то время как куча выравнивается по страницам, обычно 4096 байт. При проведении атаки можно выровнять повторяющиеся атаки по этим интервалам; для инъекции шелл-кода можно использовать NOP-слайд, а строку '' можно заменить на '' для произвольного количества слешей при попытке возврата в system. Количество удаленных битов составляет ровно для n атакованных интервалов. Такие уменьшения ограничены объемом данных в стеке или куче. Например, стек обычно ограничен 8 и может уменьшаться до гораздо меньшего размера, что позволяет получить максимум 19, хотя более консервативная оценка составляет около 8–10, что соответствует 4–16. Android 5.0 отказался от поддержки PIE и требует, чтобы все динамически связанные исполняемые файлы были позиционно-независимыми. Рандомизация порядка загрузки библиотек была принята в проект Android с открытым исходным кодом 26 октября 2015 года. Она отключена по умолчанию и может быть включена установкой sysctl vm.randomize_mmap в 1.
FreeBSD
Поддержка ASLR появилась в FreeBSD 13.0. Она включена по умолчанию, начиная с версии 13.2.
iOS (iPhone, iPod touch, iPad)
Apple представила ASLR в iOS 4.3 (выпущенной в марте 2011 года). KASLR был представлен в iOS 6. Случайно выбранная базовая область ядра – , где – случайный байт из SHA1 (случайных данных), сгенерированный iBoot (загрузчик iOS второго этапа).
Линукс
Ядро Linux по умолчанию включало слабую форму ASLR с версии ядра 2.6.12, выпущенной в июне 2005 года. Патчсеты PaX и Exec Shield для ядра Linux обеспечивают более полную реализацию. Патч Exec Shield для Linux обеспечивает 19 бит стековой энтропии на период 16 байтов и 8 бит рандомизации базового адреса mmap на период 1 страницы размером 4096 байт. Это помещает базовый адрес стека в область шириной 8 МБ, содержащую 524 288 возможных позиций, а базовый адрес mmap – в область шириной 1 МБ, содержащую 256 возможных позиций. ASLR может быть отключен для конкретного процесса путем изменения его домена исполнения с помощью функции personality(2). Ряд опций sysctl контролируют поведение ASLR. Например, определяет, что рандомизировать; наиболее сильный вариант – 2. определяет, сколько бит рандомизировать для mmap. Исполняемый файл, независимый от позиции (PIE), реализует случайный базовый адрес для основного исполняемого файла и был представлен 18 апреля 2004 года. Он обеспечивает такую же случайность адреса для основного исполняемого файла, как и для общих библиотек. Функцию PIE нельзя использовать совместно с функцией prelink для одного и того же исполняемого файла. Инструмент prelink реализует рандомизацию на этапе prelink, а не во время выполнения, поскольку по своей конструкции prelink предназначен для обработки релокации библиотек до того, как это сделает динамический линковщик, что позволяет выполнить релокацию один раз для множества запусков программы. В результате, настоящая рандомизация адресного пространства сведет на нет цель prelinking. В 2014 году Марко Гисберт и Риполл опубликовали технику offset2lib, которая ослабляет Linux ASLR для PIE-исполняемых файлов. Ядра Linux загружают PIE-исполняемые файлы сразу после их библиотек; в результате существует фиксированный сдвиг между исполняемым файлом и функциями библиотеки. Если злоумышленник найдет способ узнать адрес функции в исполняемом файле, адреса библиотеки также станут известны. Они продемонстрировали атаку, которая находит адрес менее чем за 400 попыток. Они предложили новую опцию для рандомизации размещения исполняемого файла относительно библиотеки.
Ядро Linux 5.18, выпущенное в мае 2022 года, снизило эффективность как 32-битных, так и 64-битных реализаций. Файловые системы Linux вызывают thp get unmapped area для обработки mmap, подкрепленного файлом. С изменением в 5.18 файлы размером более 2 МиБ возвращают адреса, выровненные по границе 2 МиБ, чтобы они могли потенциально быть подкреплены огромными страницами. (Ранее повышенное выравнивание применялось только к отображениям с прямым доступом (DAX).) Между тем, библиотека C (libc) со временем выросла в размерах и превысила этот порог в 2 МиБ, поэтому вместо выравнивания по границе страницы 4 КиБ (как это было раньше), эти библиотеки теперь выровнены по границе 2 МиБ: это привело к потере 9 бит энтропии. Для 32-битного Linux многие дистрибутивы не показывают никакой рандомизации при размещении libc. Для 64-битного Linux 28 бит энтропии уменьшаются до 19 бит. В ответ Ubuntu увеличила значение своей настройки. Мартин Дуча добавил тестовый пример в Linux Test Project для обнаружения этой проблемы.
Расположение адресной зоны ядра
Рандомизация расположения адресного пространства ядра (KASLR) обеспечивает рандомизацию адресного пространства образа ядра Linux, случайным образом определяя местоположение кода ядра при загрузке. KASLR был включен в основную ветку ядра Linux в версии 3.14, выпущенной 30 марта 2014 года. При компиляции его можно отключить во время загрузки, указав соответствующий параметр в параметрах загрузки ядра. В процессорах x86 существует несколько атак по сторонним каналам, которые могут привести к утечке адресов ядра. В конце 2017 года была разработана изоляция таблиц страниц ядра (KPTI, также известная как KAISER) для противодействия этим атакам. Однако этот метод не защищает от атак по сторонним каналам, использующих коллизии в структурах предсказателя ветвлений. По состоянию на 2021 год, более гранулярная рандомизация расположения адресного пространства ядра (или KASLR с гранулярностью функций, FGKASLR) является планируемым расширением KASLR для рандомизации на уровне отдельных функций.
Microsoft Windows
В Windows Vista от Microsoft (выпущенной в январе 2007 года) и последующих версиях ASLR включена только для исполняемых файлов и динамических библиотек, которые при компиляции были специально настроены на использование ASLR. Для обеспечения совместимости, по умолчанию для других приложений она не активирована. Обычно несовместимость возникает только со старым программным обеспечением, и ASLR можно полностью включить, отредактировав запись в реестре или установив Microsoft Enhanced Mitigation Experience Toolkit. Также рандомизируются адреса размещения кучи, стека, блока среды процесса и блока среды потока. В техническом документе по безопасности от Symantec отмечается, что ASLR в 32-битной Windows Vista может оказаться не таким надежным, как предполагалось, и Microsoft признала наличие уязвимости в реализации данной функции. Системы предотвращения вторжений, работающие на хосте, такие как WehnTrust и Ozone, также предоставляют ASLR для операционных систем Windows XP и Windows Server 2003. WehnTrust имеет открытый исходный код. Полные сведения о реализации Ozone недоступны. В феврале 2012 года было установлено, что эффективность ASLR на 32-битных системах Windows до Windows 8 может снижаться при нехватке памяти. Аналогичный эффект был достигнут и в Linux в рамках того же исследования. При тестировании система Mac OS X 10.7.3 выдала панику ядра, поэтому поведение ASLR в этом случае осталось неясным.
NetBSD
Поддержка ASLR в пользовательском пространстве появилась в NetBSD 5.0 (выпущенной в апреле 2009 года) и была включена по умолчанию в актуальной версии NetBSD в апреле 2016 года. Поддержка ASLR в ядре для архитектуры amd64 была добавлена в актуальной версии NetBSD в октябре 2017 года, что сделало NetBSD первой BSD-системой с поддержкой KASLR.
OpenBSD (всего один раз)
В 2003 году OpenBSD стала первой широко используемой операционной системой, поддерживающей надежную форму ASLR и активировавшей её по умолчанию. OpenBSD завершила внедрение поддержки ASLR в 2008 году, добавив поддержку исполняемых файлов PIE. Функция malloc(3) в OpenBSD 4.4 была разработана для повышения безопасности за счет использования ASLR и функций защиты пустых страниц, реализованных в системном вызове mmap OpenBSD, а также для обнаружения ошибок использования памяти после освобождения. Выпущенная в 2013 году OpenBSD 5.3 стала первой широко используемой операционной системой, включившей исполняемые файлы, независимые от позиции, по умолчанию на нескольких аппаратных платформах, а OpenBSD 5.7 активировала статические исполняемые файлы, независимые от позиции (Static PIE), по умолчанию. В Mac OS X Lion 10.7 (выпущенной в июле 2011 года) Apple расширила свою реализацию, охватив все приложения, заявив: «механизм рандомизации адресного пространства (ASLR) был улучшен для всех приложений. Теперь он доступен для 32-битных приложений (наряду с защитой области памяти), что делает 64-битные и 32-битные приложения более устойчивыми к атакам». Начиная с OS X Mountain Lion 10.8 (выпущенной в июле 2012 года) и более поздних версий, вся система, включая ядро, а также расширения ядра (kexts) и зоны, случайным образом переносятся во время загрузки системы.
Солярис
ASLR была внедрена в Solaris, начиная с Solaris 11.1 (выпущенной в октябре 2012 года). ASLR в Solaris 11.1 может быть настроена глобально для системы, для каждой зоны или для отдельных исполняемых файлов.
Эксплуатация
Было продемонстрировано, что атака по стороннему каналу с использованием буфера предсказания переходов позволяет обойти защиту ASLR.