Дефекты проектирования Intel Core 2 Duo - AI90: Атрибут доступа к странице памяти может быть установлен до генерации исключения

ОГЛАВЛЕНИЕ

AI90: Атрибут доступа к странице памяти может быть установлен до генерации исключения

  • Проблема: если лимит сегмента кода установлен близко к концу кодовой страницы, то при определенных обстоятельствах следующей за ней странице памяти процессор может назначить атрибут доступа  до генерации исключения общего нарушения защиты или выхода за пределы лимитов кодового сегмента.
  • Последствия: при проявлении дефекта страница памяти, следующая за последней страницей кодового сегмента, получает атрибут доступа, даже если изначально она была недоступна для чтения.
  • Решение: пагубное влияние дефекта может быть нейтрализовано путем установки сторожевой страницы (отсутствующей в памяти или неисполняемой), отделяющей кодовый сегмент от последующего за ним семена.

Вот мы и добрались до дефекта, особо отмеченного Тео де Раадтом в качестве подходящего кандидата для атаки на операционные системы (за исключением OpenBSD в конфигурации по умолчанию). Что же это за операционные системы такие?!

В NT лимиты сегментов кода, данных и стека «распахнуты» на все адресное пространство, нижнюю половину которого занимает прикладной код, верхнюю – операционная система. Так что за пределами кодового сегмента вообще ничего нет. Да и чтобы добраться до его конца, необходимо сначала как-то попасть на уровень ядра, где можно делать что угодно и без всяких дефектов процессора (правда, в Core 2 Duo есть еще один интересный дефект, обнаруженный автором и не описанный в последней errata – при выполнении кусочка инструкции, находящегося в самом конце кодового сегмента, декодер, определяя длину инструкции по первым байтам, пытается считать ее продолжение, которого нет, в результате чего происходит «заворот» в начало сегмента, первой странице которого также присваивается атрибут доступа, после чего генерируется исключение, которое хакеру необходимо отловить, чтобы система не свалилась в BSOD, но что это даст?!

Младшие страницы адресного пространства специально сделаны недоступными в NT для отлова обращения по нулевым указателям, свидетельствующих о том, что программа обращается к невыделенной области памяти, и Windows передает ей исключение, которая та может обработать тем или иным образом, но чаще всего обработчик конструктивно непредусмотрен, и тогда система завершает работу приложения в аварийном режиме.

Установка атрибута доступа на первую страницу приведет к подавлению исключения, и программа упадёт не в момент обращения к нулевому указателю, а чуть позже – когда попытается обработать считанный оттуда мусор. Не слишком-то большое достижение, к тому же легко реализуемое на прикладном уровне без обращения к дефектам процессора).

Правда, 16-разрядные приложения имеют свои собственные 16-разрядные лимиты, и теоретически благодаря ошибке в процессоре атакующий может получить доступ к данным, которые ему читать не положено. В смысле по атрибутам страниц не положено, а так… если атакующий может запускать приложения, то отформатировать диск или удалить все файлы – быстрее и надежнее.

А вот из 32-разрядного приложения вызвать 16-разрядное, ну не то чтобы невозможно, но все-таки достаточно сложно (имеется в виду вызов из shell-кода, исполняющегося в 32-разрядном приложении). Другими словами, на Windows этот дефект не оказывает ровным счетом никакого воздействия.

А что на счет BSD и Linux? Штатные ядра также исповедуют плоскую модель. Кодовый сегмент находится в самом конце адресного пространства, и ничего интересного за ним нет. Некоторые защитные пакеты, разработанные еще в ту далекую эпоху, когда процессоры поддерживали атрибут, «исполняемый» только на уровне селекторов, а необходимость защиты стека, кучи и данных от исполнения заброшенного хакером туда shell-кода уже назрела – произошло вот что: нестандартные ядерные расширения урезали лимиты стека и сегмента данных (расположенных в начале) и отобрали у них атрибут «исполняемый». А за ними расположили сегмент кода. Вот если бы они поступили в обратном порядке (сначала код, потом стек и данные), то у хакеров была бы потенциальная возможность доступа к недоступным данным, вот только… стек и куча доступы и так… без всяких дефектов процессора.

Конечно, можно предположить, что где-то есть операционная система, в которой сначала идут пользовательские сегменты кода и данных, а потом расположен сегмент операционной системы, хранящий данные, защищенные от чтения, поскольку, будучи прочитанными, они позволят повысить уровень своих привилегий, например, но… если такая операционная система и есть, то это не Linux, не Windows, не BSD и не QNX… а какая-то студенческая поделка. Вопрос: какой интерес ее атаковать?! Короче, на этот дефект процессора можно вообще не обращать внимания. Ну разве что при разработке новых операционных систем, радикально отличающихся от уже существующих.

Windows использует «плоскую» модель памяти с «распахнутыми» границами сегментов