Возвратно-ориентированное программирование - Return-oriented programming

Возвратно-ориентированное программирование (ROP) это эксплойт компьютерной безопасности метод, позволяющий злоумышленнику выполнить код при наличии средств защиты[1] Такие как исполняемая защита пространства и подпись кода.[2]

В этом методе злоумышленник получает контроль над стек вызовов захватить программу поток управления а затем выполняет тщательно выбранные машинная инструкция последовательности, которые уже присутствуют в памяти машины, называются «гаджетами».[3] Каждый гаджет обычно заканчивается инструкция по возврату и находится в подпрограмма внутри существующей программы и / или кода разделяемой библиотеки. Связанные вместе, эти гаджеты позволяют злоумышленнику выполнять произвольные операции на машине, используя средства защиты, предотвращающие более простые атаки.

Фон

Пример макета стека вызовов. Подпрограмма DrawLine был вызван DrawSquare. Обратите внимание, что на этой диаграмме стек растет вверх.

Возвратно-ориентированное программирование - это расширенная версия разбивание стека атака. Как правило, эти типы атак возникают, когда противник манипулирует стек вызовов воспользовавшись ошибка в программе часто переполнение буфера. При переполнении буфера функция, которая не выполняет должным образом проверка границ перед сохранением предоставленных пользователем данных в память примет больше входных данных, чем может сохранить должным образом. Если данные записываются в стек, избыточные данные могут переполнять пространство, выделенное для переменных функции (например, «локальные» на диаграмме стека справа), и перезаписывать адрес возврата. Этот адрес позже будет использоваться функцией для перенаправления потока управления обратно в звонящий. Если он был перезаписан, поток управления будет перенаправлен в место, указанное новым адресом возврата.

В стандартной атаке переполнения буфера злоумышленник просто написать код атаки («полезная нагрузка») в стек, а затем перезапишите адрес возврата местоположением этих вновь записанных инструкций. До конца 1990-х гг. операционные системы не предлагал никакой защиты от этих атак; Майкрософт Виндоус до 2004 года не обеспечивала защиты от переполнения буфера.[4] В конце концов, операционные системы начали бороться с эксплуатацией ошибок переполнения буфера, отмечая память, в которую записываются данные, как неисполняемые, метод, известный как исполняемая защита пространства. Если этот параметр включен, машина будет отказываться выполнять любой код, расположенный в доступных для записи областях памяти, не позволяя злоумышленнику разместить полезную нагрузку в стеке и перейти к ней посредством перезаписи адреса возврата. Поддержка оборудования позже стали доступны усиление этой защиты.

Благодаря предотвращению выполнения данных злоумышленник не может выполнить злонамеренно введенные инструкции, потому что типичное переполнение буфера перезаписывает содержимое в разделе данных памяти, который помечен как неисполняемый. Чтобы победить это, атака, ориентированная на возврат, не внедряет вредоносный код, а использует уже существующие инструкции, называемые «гаджетами», путем манипулирования адресами возврата. Обычное предотвращение выполнения данных не может защитить от этой атаки, потому что злоумышленник не использовал вредоносный код, а скорее объединил «хорошие» инструкции, изменив адреса возврата; поэтому используемый код не будет помечен как неисполняемый.

Техника возврата в библиотеку

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

При атаке с возвратом в библиотеку злоумышленник перехватывает поток управления программой, используя уязвимость переполнения буфера, как описано выше. Вместо того, чтобы пытаться записать полезные данные атаки в стек, злоумышленник вместо этого выбирает доступную библиотечную функцию и перезаписывает адрес возврата своим местоположением входа. Дальнейшие местоположения стопки затем перезаписываются в соответствии с применимыми соглашения о вызовах, чтобы тщательно передать правильные параметры функции, чтобы она выполняла функции, полезные для злоумышленника. Эта техника была впервые представлена Солнечный дизайнер в 1997 г.[5] и позже был расширен до неограниченного связывания вызовов функций.[6]

Заимствованные фрагменты кода

Подъем 64-битный x86 процессоры принесли с собой изменение в соглашение о вызове подпрограмм, которое требовало, чтобы первый аргумент функции передавался в регистр вместо в стеке. Это означало, что злоумышленник больше не мог настроить вызов библиотечной функции с желаемыми аргументами, просто манипулируя стеком вызовов с помощью эксплойта переполнения буфера. Разработчики общей библиотеки также начали удалять или ограничивать библиотечные функции, которые выполняли действия, особенно полезные для злоумышленника, такие как системный вызов обертки. В результате стало намного сложнее успешно провести атаку возврата в библиотеку.

Следующим этапом эволюции стала атака, в которой использовались фрагменты библиотечных функций вместо целых функций для использования уязвимостей переполнения буфера на машинах с защитой от более простых атак.[7] Этот метод ищет функции, содержащие последовательности инструкций, которые выталкивают значения из стека в регистры. Тщательный выбор этих кодовых последовательностей позволяет злоумышленнику поместить подходящие значения в соответствующие регистры для выполнения вызова функции в соответствии с новым соглашением о вызовах. Остальная часть атаки продолжается как атака возврата в библиотеку.

Атаки

Возвратно-ориентированное программирование основывается на подходе заимствованных фрагментов кода и расширяет его, чтобы обеспечить Тьюринг завершен функциональность для злоумышленника, включая петли и условные ветви.[8][9] Иными словами, ориентированное на возврат программирование предоставляет полностью функциональный «язык», который злоумышленник может использовать, чтобы заставить взломанный компьютер выполнить любую желаемую операцию. Ховав Шахам опубликовал эту технику в 2007 году.[10] и продемонстрировал, как все важные программные конструкции могут быть смоделированы с использованием ориентированного на возврат программирования для целевого приложения, связанного со стандартной библиотекой C и содержащего уязвимость, связанную с переполнением буфера.

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

На x86-архитектуре

Хотя атаки с ориентированным на возврат программированием могут выполняться на различных архитектурах,[10] Статья Шахама и большая часть последующей работы сосредоточены на Intel x86 архитектура. Архитектура x86 - это архитектура переменной длины. CISC Набор инструкций. В ориентированном на возврат программировании на x86 используется тот факт, что набор инструкций очень "плотный", то есть любая случайная последовательность байтов может быть интерпретирована как некоторый допустимый набор инструкций x86.

Следовательно, можно искать код операции который изменяет поток управления, в первую очередь команду возврата (0xC3), а затем просматривает двоичный файл назад в поисках предшествующих байтов, которые образуют, возможно, полезные инструкции. Эти наборы инструкций «гаджеты» затем могут быть связаны путем перезаписи адреса возврата с помощью эксплойта переполнения буфера адресом первой инструкции первого гаджета. Затем в стек последовательно записывается первый адрес последующих устройств. По завершении первого гаджета будет выполнена инструкция возврата, которая вытолкнет адрес следующего гаджета из стека и перейдет к нему. По завершении этого устройства цепочка продолжается с третьего и так далее. Объединив небольшие последовательности инструкций, злоумышленник может произвести произвольное поведение программы из уже существующего библиотечного кода. Шахам утверждает, что при любом достаточно большом количестве кода (включая, но не ограничиваясь, стандартную библиотеку C), будет существовать достаточное количество гаджетов для полной по Тьюрингу функциональности.[10]

Был разработан автоматизированный инструмент, помогающий автоматизировать процесс обнаружения гаджетов и построения атаки на двоичный файл.[11] Этот инструмент, известный как ROPgadget, просматривает двоичный файл в поисках потенциально полезных гаджетов и пытается собрать их в полезную нагрузку для атаки, которая порождает оболочку для приема произвольных команд от злоумышленника.

О рандомизации разметки адресного пространства

В рандомизация разметки адресного пространства также есть уязвимости. Согласно статье Шахама и др.,[12] ASLR на 32-битных архитектурах ограничено количеством бит, доступных для рандомизации адресов. Только 16 из 32 бит адреса доступны для рандомизации, а 16 бит рандомизации адреса могут быть побеждены атакой грубой силы за считанные минуты. Для 64-битных архитектур 40 бит из 64 доступны для рандомизации. В 2016 году атака полным перебором для 40-битной рандомизации возможна, но вряд ли останется незамеченной. Кроме того, рандомизацию можно обойти с помощью методов дерандомизации.

Даже при идеальной рандомизации утечка содержимого памяти поможет вычислить базовый адрес DLL во время выполнения.[13]

Без использования инструкции возврата

Согласно статье Checkoway et al,[14] можно выполнять ориентированное на возврат программирование на архитектурах x86 и ARM без использования инструкции возврата (0xC3 на x86). Вместо этого они использовали тщательно продуманные последовательности инструкций, которые уже существуют в памяти машины, чтобы вести себя как инструкция возврата. Команда возврата имеет два эффекта: во-первых, она ищет четырехбайтовое значение наверху стека и устанавливает указатель инструкции на это значение, а во-вторых, увеличивает значение указателя стека на четыре. В архитектуре x86 последовательности инструкций jmp и pop могут действовать как инструкция возврата. В ARM последовательности инструкций загрузки и ветвления могут действовать как инструкция возврата.

Поскольку этот новый подход не использует инструкцию возврата, он имеет негативные последствия для защиты. Когда программа защиты проверяет не только несколько возвратов, но и несколько инструкций перехода, эта атака может быть обнаружена.

Защиты

G-Free

Технику G-Free разработали Каан Онарлиоглу, Лейла Бильге, Андреа Ланци, Давиде Бальзаротти и Энгин Кирда. Это практическое решение против любых возможных форм программирования, ориентированного на возврат. Решение исключает все невыровненные инструкции свободного перехода (такие как RET или CALL, которые злоумышленники могут использовать для изменения потока управления) внутри двоичного исполняемого файла и защищает инструкции свободного перехода от использования злоумышленником. Способ, которым G-Free защищает обратный адрес, аналогичен канарейке XOR, реализованной StackGuard. Кроме того, он проверяет подлинность вызовов функций, добавляя блок проверки. Если ожидаемый результат не найден, G-Free вызывает сбой приложения.[15]

Рандомизация разметки адресного пространства

Было предложено несколько методов отражения атак на основе программирования, ориентированного на возврат.[16] Большинство из них полагаются на случайное расположение программного и библиотечного кода, так что злоумышленник не может точно предсказать расположение инструкций, которые могут быть полезны в гаджетах, и, следовательно, не может создать успешную цепочку программных атак, ориентированных на возврат. Одна довольно распространенная реализация этой техники, рандомизация разметки адресного пространства (ASLR), загружает разделяемые библиотеки в разные области памяти при каждой загрузке программы. Хотя ASLR широко используется в современных операционных системах, он уязвим для утечка информации атаки и другие подходы для определения адреса любой известной библиотечной функции в памяти. Если злоумышленник может успешно определить расположение одной известной инструкции, можно вывести положение всех остальных и построить программную атаку, ориентированную на возврат.

Этот подход рандомизации может быть применен дальше, перемещая все инструкции и / или другое состояние программы (регистры и объекты стека) программы отдельно, а не только расположение библиотек.[17][18][19] Это требует обширной поддержки во время выполнения, такой как программный динамический транслятор, для объединения рандомизированных инструкций во время выполнения. Этот метод позволяет затруднить поиск и использование гаджетов, но требует значительных накладных расходов.

Другой подход, применяемый kBouncer, модифицирует операционную систему, чтобы убедиться, что инструкции возврата действительно перенаправляют поток управления обратно в место, следующее сразу за инструкцией вызова. Это предотвращает цепочку гаджетов, но влечет за собой серьезное снижение производительности,[требуется разъяснение ] и неэффективен против атак программирования, ориентированных на переходы, которые изменяют переходы и другие инструкции, изменяющие поток управления, вместо возврата.[20]

Рандомизация двоичного кода

Некоторые современные системы, такие как Cloud Lambda (FaaS) и удаленные обновления IoT, используют облачную инфраструктуру для выполнения компиляции на лету перед развертыванием программного обеспечения. Методика, которая вводит вариации в каждый экземпляр исполняемого программного обеспечения, может значительно повысить устойчивость программного обеспечения к ROP-атакам. Грубая форсировка Cloud Lambda может привести к атаке нескольких экземпляров рандомизированного программного обеспечения, что снижает эффективность атаки. Асаф Шелли опубликовал методику в 2017 году[21] и продемонстрировали использование двоичной рандомизации в системе обновления программного обеспечения. Для каждого обновленного устройства облачная служба вводила варианты кода, выполняла онлайн-компиляцию и отправляла двоичный файл. Этот метод очень эффективен, потому что ROP-атаки полагаются на знание внутренней структуры программного обеспечения. Недостатком этого метода является то, что программное обеспечение никогда не тестируется полностью перед развертыванием, поскольку невозможно протестировать все варианты рандомизированного программного обеспечения. Это означает, что многие методы двоичной рандомизации применимы для сетевых интерфейсов и системного программирования и менее рекомендуются для сложных алгоритмов.

SEHOP

Защита от перезаписи структурированного обработчика исключений - это функция Windows, которая защищает от наиболее распространенных атак переполнения стека, особенно от атак на структурированный обработчик исключений.

Против атак потока управления

Поскольку небольшие встраиваемые системы быстро распространяются из-за расширения Интернет вещей, потребность в защите таких встроенных систем также возрастает. Используя аппаратное управление доступом к памяти (IB-MAC), можно защитить недорогие встроенные системы от злонамеренных потоков управления и атак переполнения стека. Защита может быть обеспечена путем разделения стека данных и стека возврата. Однако из-за отсутствия блок управления памятью в некоторых встроенных системах аппаратное решение не может применяться ко всем встроенным системам.[22]

Против руткитов, ориентированных на возврат

В 2010 году Джинку Ли и др. предложил[23] что соответствующим образом модифицированный компилятор может полностью исключить «гаджеты», ориентированные на возврат, заменив каждый вызов ж с последовательностью инструкций толкать $ index; jmp ж и каждый Ret с последовательностью инструкций поп % ebx; jmp стол(% ebx), куда стол представляет собой неизменяемую таблицу всех "законных" адресов возврата в программе и индекс представляет собой конкретный индекс в этой таблице. Это предотвращает создание гаджета, ориентированного на возврат, который возвращается прямо с конца функции на произвольный адрес в середине другой функции; вместо этого гаджеты могут возвращаться только по «законным» адресам возврата, что резко увеличивает сложность создания полезных гаджетов. Ли и др. утверждал, что "наша методика обратного косвенного обобщает возвратно-ориентированное программирование назад к старому стилю return-into-libc ".[23] Их компилятор проверки концепции включал оптимизация глазка фаза для работы с «некоторыми машинными инструкциями, которые содержат код операции возврата в своих кодах операции или непосредственных операндах»,[23] Такие как движение $ 0xC3, % eax.

Коды аутентификации указателя (PAC)

Архитектура ARMv8.3-A представляет новую функцию на аппаратном уровне, которая использует неиспользуемые биты в адресном пространстве указателя для криптографической подписи адресов указателя с помощью специально разработанного настраиваемый блочный шифр[24][25] который подписывает желаемое значение (обычно адрес возврата) в сочетании со значением «локального контекста» (например, указателем стека).

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

В частности Яблоко A12 микросхемы, используемые в iPhone, обновлены до ARMv8.3 и используют PAC. Linux получил поддержку аутентификации указателя в ядре в версии 5.7, выпущенной в 2020 году; Поддержка для пространство пользователя приложений было добавлено в 2018 году.[26]

Смотрите также

Рекомендации

  1. ^ Васкес, Уго (1 октября 2007 г.). «Взлом платформы Check Point Secure» (PDF). Пентест. Барселона, Испания: Pentest Consultores. п. 219. Сложить резюме.
  2. ^ Шахам, Ховав; Бьюкенен, Эрик; Ремер, Райан; Дикарь, Стефан. «Возвратно-ориентированное программирование: эксплойты без внедрения кода». Получено 2009-08-12.
  3. ^ Buchanan, E .; Roemer, R .; Shacham, H .; Сэвидж, С. (октябрь 2008 г.). «Когда хорошие инструкции становятся плохими: обобщение ориентированного на возврат программирования на RISC» (PDF). Материалы 15-й конференции ACM по компьютерной и коммуникационной безопасности - CCS '08. С. 27–38. Дои:10.1145/1455770.1455776. ISBN  978-1-59593-810-7.
  4. ^ Предотвращение выполнения данных Microsoft Windows XP SP2
  5. ^ Солнечный конструктор, Эксплойты return-into-lib (c), Bugtraq
  6. ^ Нергал, Фрак 58, статья 4, return-into-lib (c) эксплойты
  7. ^ Себастьян Крамер, эксплойты переполнения буфера x86-64 и техника эксплуатации заимствованных фрагментов кода, 28 сентября 2005 г.
  8. ^ Abadi, M. N .; Будиу, М .; Erlingsson, Ú .; Лигатти, Дж. (Ноябрь 2005 г.). «Целостность потока управления: принципы, реализации и приложения». Материалы 12-й конференции ACM по компьютерной и коммуникационной безопасности - CCS '05. С. 340–353. Дои:10.1145/1102120.1102165. ISBN  1-59593-226-7.
  9. ^ Abadi, M. N .; Будиу, М .; Erlingsson, Ú .; Лигатти, Дж. (Октябрь 2009 г.). «Принципы, реализации и приложения целостности потока управления». ACM-транзакции по информационной и системной безопасности. 13: 1–40. Дои:10.1145/1609956.1609960.
  10. ^ а б c Шахам, Х. (октябрь 2007 г.). «Геометрия невинной плоти на кости: возврат в libc без вызовов функций (на x86)». Материалы 14-й конференции ACM по компьютерной и коммуникационной безопасности - CCS '07. С. 552–561. Дои:10.1145/1315245.1315313. ISBN  978-1-59593-703-2.
  11. ^ Джонатан Салван и Аллан Вирт, ROPgadget - поиск гаджетов и автопробег
  12. ^ [Shacham et al., 2004] Ховав Шахам, Мэтью Пейдж, Бен Пфафф, Ю-Джин Го, Нагендра Модадугу и Дэн Бонех. Об эффективности рандомизации адресного пространства. В материалах 11-й конференции ACM по компьютерной и коммуникационной безопасности (CCS), 2004 г.
  13. ^ [Bennett et al., 2013] Джеймс Беннетт, Ичонг Линь и Туфик Хак. Число зверя, 2013. https://www.fireeye.com/blog/threat-research/2013/02/the-number-of-the-beast.html
  14. ^ ЧЕКОВЕЙ, С., ДЭВИ, Л., ДМИТРИЕНКО, А., САДЕГИ, А.-Р., ШАЧАМ, Х. И ВИНАНДИ, М. 2010. Программирование, ориентированное на возврат, без возврата. В материалах CCS 2010, A. Keromytis и V. Shmatikov, Eds. ACM Press, 559–72
  15. ^ ONARLIOGLU, K., BILGE, L., LANZI, A., BALZAROTTI, D., AND KIRDA, E. 2010. G-Free: победа над программированием, ориентированным на возврат, с помощью двоичных файлов без гаджетов. В Proceedings of ACSAC 2010, M. Franz and J. McDermott, Eds. ACM Press, 49–58.
  16. ^ Skowyra, R .; Casteel, K .; Охрави, H .; Зельдович, Н .; Стрейлейн, В. (октябрь 2013 г.). «Систематический анализ защиты от программирования, ориентированного на возврат» (PDF). Исследования атак, вторжений и защит. Конспект лекций по информатике. 8145. С. 82–102. Дои:10.1007/978-3-642-41284-4_5. ISBN  978-3-642-41283-7. Архивировано из оригинал (PDF) на 22 февраля 2014 г.
  17. ^ Венкат, Ашиш; Шамасундер, Шрисканда; Шахам, Ховав; Таллсен, Дин М. (01.01.2016). "HIPStR: Перенос состояния гетерогенной программы ISA". Труды двадцать первой международной конференции по архитектурной поддержке языков программирования и операционных систем. АСПЛОС '16. Нью-Йорк, Нью-Йорк, США: ACM: 727–741. Дои:10.1145/2872362.2872408. ISBN  9781450340915.
  18. ^ Hiser, J .; Nguyen-Tuong, A .; Co, M .; Холл, М .; Дэвидсон, Дж. У. (май 2012 г.). «ILR: Куда делись мои гаджеты?». Симпозиум IEEE по безопасности и конфиденциальности 2012 г.. С. 571–585. Дои:10.1109 / SP.2012.39. ISBN  978-1-4673-1244-8.
  19. ^ [1], Венкат, Ашиш; Арвинд Кришнасвами и Коити Ямада, "Перемещение состояния программы, управляемое двоичным переводчиком" 
  20. ^ Василис Паппас. kBouncer: эффективное и прозрачное противодействие ROP. Апрель 2012 г.
  21. ^ [2], «Методы и системы безопасности путем мутации кода», выпущенный 04.05.2017 
  22. ^ ФРАНСИЛЛОН, А., ПЕРИТО, Д., И КАСТЕЛЛУЧСИЯ, С. 2009. Защита встроенных систем от атак потока управления. В Proceedings of SecuCode 2009, S. Lachmund and C. Schaefer, Eds. ACM Press, 19–26.
  23. ^ а б c Цзиньку Ли, Чжи Ван, Сюйсянь ЦЗЯН, Майк Грейс и Сина Бахрам. Победить руткиты, ориентированные на возврат, с помощью «безвозвратных» ядер. В Материалы EuroSys 2010под редакцией Г. Мюллера. ACM Press, 195–208.
  24. ^ Аванзи, Роберто (2016). Семейство блочных шифров QARMA (PDF). Транзакции IACR по симметричной криптологии (ToSC). т. 17 вып. 1 (опубликовано 8 марта 2017 г.). С. 4–44. Дои:10.13154 / tosc.v2017.i1.4-44. Архивировано из оригинал (PDF) 13 мая 2020 г.
  25. ^ Безопасность продуктов Qualcomm. «Аутентификация указателя на ARMv8.3» (PDF). Qualcomm Technologies Inc. В архиве (PDF) с оригинала 6 июня 2020 г.. Получено 16 июня, 2020. Таким образом, мы разработали QARMA, новое семейство легких настраиваемых блочных шифров.
  26. ^ "Linux 5.7 для 64-битной ARM обеспечивает аутентификацию указателя в ядре, мониторы активности - Phoronix". www.phoronix.com. Получено 2020-03-31.

внешняя ссылка