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

Возвратно-ориентированное программирование (англ. Return-oriented programming, ROP) — это техника эксплуатации уязвимостей в компьютерной безопасности, которая позволяет злоумышленнику исполнять произвольный код несмотря на защитные механизмы, такие как защита пространства выполнения и цифровая подпись кода[1][2][3]. Основная идея — захват управления над стеком вызовов программы, чтобы вместо внедрения чужого кода использовать последовательности машинных инструкций, уже присутствующие в памяти целевой программы. Эти последовательности называются гаджетами[4]. Каждый гаджет обычно завершает свою работу инструкцией возврата и располагается внутри подпрограмм приложений или разделяемых библиотек. Объединяя гаджеты в цепочку, злоумышленник способен выполнять любые вычисления, обходя запреты на исполнение «чужого» кода.

История

undefined

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

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

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

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

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

В атаке «возврат в библиотеку» злоумышленник, эксплуатируя переполнение буфера, подменяет адрес возврата на входную точку функции в библиотеке, а следующие значения в стеке формируют параметры этой функции согласно соглашению о вызовах. Впервые метод предложил Solar Designer в 1997 году[6], позднее технику расширили до цепочек вызовов[7].

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

Переход x86-систем к 64-разрядной архитектуре (x64) изменил соглашения о вызовах: теперь часть параметров функций передаётся через регистры процессора, а не через стек. Многие функции-библиотеки, полезные для атакующих, стали менее доступны или были удалены. В итоге атаки «возврат в библиотеку» стали сложнее, потому что нельзя было передавать произвольные параметры.

Следующий этап развития — атаки с использованием коротких последовательностей кода внутри функций библиотек, а не целых функций; эти цепочки позволяли подготавливать регистры к вызову[8]. Далее эксплойт выполнялся как атака возврата в библиотеку.

Особенности атаки

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

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

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

Хотя возвратно-ориентированные атаки возможны на разных архитектурах[11], большинство исследований посвящено x86. Это CISC-архитектура с переменной длиной инструкции, поэтому почти любая последовательность байтов может быть интерпретирована как корректные инструкции.

Автоматический поиск подряд идущих инструкций (гаджетов) с завершением на RETURN (0xC3) позволяет составлять произвольные цепочки для перенаправления управления. Злоумышленник помещает в стек адрес первого гаджета, далее адреса следующих гаджетов. Каждая инструкция возврата выполняет переход по очередному адресу. Так возможно реализовать сложное поведение из кода библиотеки. Согласно Шахаму, в достаточно большом коде (например, стандартной C-библиотеке) всегда можно найти необходимый набор гаджетов для Тьюринг-полной реализации[11].

Существуют инструменты (например, ROPgadget), упрощающие автоматический поиск гаджетов и сборку цепочек для эксплуатации уязвимостей[12].

Обход Address Space Layout Randomization (ASLR)

Механизм ASLR также не гарантирует полной защиты. По данным работы Шахама и других[13], в 32-разрядных системах имеет значение только часть бит адреса, что позволяет перебором за считанные минуты деанонимизировать размещение объектов. В 64-битных системах запас рандомизации выше, но при утечке информации о размещении кода в памяти (например, адреса функции библиотеки) защита теряет эффективность.

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

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

Согласно исследованиям Checkoway и др.[15], возможно создание возвратно-ориентированных атак (как на x86, так и на ARM), не используя инструкции RET. Подбираются последовательности jmp/pop (x86) или load/branch (ARM), ведущие к аналогичному результату: считывается адрес из стека и происходит переход по нему. Такой подход усложняет и обнаружение атак — нужно отслеживать не только возвраты, но и переходы (JMP и другие инструкции).

Защита

G-Free

Техника G-Free, разработанная группой исследователей, устраняет все невыравненные инструкции ветвления (RET, CALL), которыми обычно пользуются атакующие, и защищает их от несанкционированного использования. Механизм защиты адреса возврата аналогичен канареечным значениям (XOR canary) StackGuard и включает проверку подлинности вызова закладкой специального блока проверки. При обнаружении несоответствия программа аварийно завершает работу[16].

Address Space Layout Randomization

Большинство приёмов защиты от возвратно-ориентированных атак сводятся к рандомизации размещения кода и библиотек, чтобы злоумышленник не мог заранее угадать расположение гаджетов[17]. Реализация — рандомизация расположения адресного пространства (ASLR), при которой библиотеки загружаются по разным адресам при каждом запуске. Однако ASLR подвержена атакам по утечке информации: зная расположение одной функции, злоумышленник вычисляет остальные.

Варианты: перенос кода и состояния программы целиком (регистр, стек и пр.) требует сложной поддержки на лету (динамический транслятор). Эта мера эффективна для запутывания размещения гаджетов, но ведёт к заметному снижению производительности[18][19][20].

Один из вариантов — подход kBouncer: модернизируется ОС с верификацией, что инструкция возврата действительно возвращает управление за вызвавшую её CALL. Метод снижает производительность и не защищает от атак, изменяющих не возвраты, а переходы[21].

Рандомизация исполняемого кода

Современные системы облачного обновления программного обеспечения и вычислений (например, Cloud Lambda, Internet of Things) внедряют технику «рандомизации бинарников». Для каждого устройства облако на лету компилирует слегка изменённую версию программы, резко снижая эффективность ROP-атак: взлом одной версии не гарантирует успеха на других[22]. Недостаток метода — вариации могут нарушать тестируемость программ, поэтому чаще применяются для сетевых интерфейсов и системного программирования, но не для сложных алгоритмов.

SEHOP

Structured Exception Handler Overwrite Protection (SEHOP) — функция Windows, защищающая от типичных атак на обработчики исключений и стековую структуру.

Защита встроенных систем

С ростом числа встраиваемых систем и распространением Интернета вещей возрастает актуальность аппаратных методов защиты приложений. Используются технологии, разделяющие стек данных и стек возвратов, аппаратные инструкции контроля доступа (IB-MAC), но из-за отсутствия MMU реализуемы не во всех случаях[23].

Против возвратно-ориентированных rootkit

В 2010 году Ли Чзинку и др. предложили[24] модифицировать компиляторы так, чтобы убрать потенциальные гаджеты: каждую инструкцию CALL заменять на «push $index; jmp f», а инструкции RET — на «pop %reg; jmp table(%reg)», где table — список разрешённых адресов возврата. Это практически деобобщает возвратно-ориентированное программирование (сводит его к старой технике «возврат в библиотеку»). В реализации учитываются также инструкции, случайно содержащие коды возврата[24].

Pointer Authentication Codes (PAC)

Архитектура ARMv8.3-A на аппаратном уровне внедряет механизм криптографической подписи адресов указателей (PAC) с помощью дополнительных неиспользуемых битов адреса[25][26]. Проверка подписи выполняется непосредственно перед возвратом: любая подмена адреса приводит к сбою проверки.

В процессорах Apple Silicon с A12 и новее PAC работает «из коробки». В ядре Linux поддержка PAC появилась с версии 5.7 (2020), для пользовательских приложений — ещё в 2018 году[27].

В 2022 году исследователи MIT продемонстрировали подканальное нападение PACMAN, обходящее защиту PAC посредством спекулятивного исполнения[28].

Идентификация целей ветвления (BTI)

Архитектура ARMv8.5-A реализует в железе механизм проверки «точек вхождения» для косвенных переходов. Компилятор вставляет специальную инструкцию BTI (branch target identification) перед ожидаемыми целями перехода (точки входа функций и блоки switch/case)[29]. Защищённые таким образом страницы исполняемого кода не позволяют косвенный переход на произвольную инструкцию: только на BTI. Поскольку только ~1 % инструкций в среднем начинаются с BTI, вероятность успешной длинной цепочки гаджетов крайне мала.

PAC и BTI работают вместе: PAC подписывает источник перехода, BTI — проверяет валидность цели[30].

Примечания

  1. Васкес, Уго. Check Point Secure Platform Hack (англ.). Pentest 219. Pentest Consultores (1 октября 2007). Дата обращения: 23 июня 2024. Архивировано 15 июня 2015 года.
  2. Thread: CheckPoint Secure Platform Multiple Buffer Overflows. The Check Point User Group. Дата обращения: 23 июня 2024. Архивировано 5 января 2023 года.
  3. Hovav Shacham, Erik Buchanan, Ryan Roemer, Stefan Savage. Return-Oriented Programming: Exploits Without Code Injection. Дата обращения: 12 августа 2009. Архивировано 22 июля 2009 года.
  4. Buchanan E., Roemer R., Shacham H., Savage S. When Good Instructions Go Bad: Generalizing Return-Oriented Programming to RISC // Proceedings of the 15th ACM conference on Computer and communications security - CCS '08. — октябрь 2008. — P. 27–38. — ISBN 978-1-59593-810-7. — doi:10.1145/1455770.1455776.
  5. Microsoft Windows XP SP2 Data Execution Prevention (англ.). Дата обращения: 23 июня 2024. Архивировано 1 сентября 2008 года.
  6. Solar Designer, Return-into-lib(c) exploits, Bugtraq
  7. Nergal, Phrack 58 Article 4, return-into-lib(c) exploits
  8. Sebastian Krahmer, x86-64 buffer overflow exploits and the borrowed code chunks exploitation technique, 28 сентября 2005
  9. Abadi M. N., Budiu M., Erlingsson Ú., Ligatti J. Control-Flow Integrity: Principles, Implementations, and Applications // Proceedings of the 12th ACM conference on Computer and communications security - CCS '05. — ноябрь 2005. — P. 340–353. — ISBN 1-59593-226-7. — doi:10.1145/1102120.1102165.
  10. Abadi M. N., Budiu M., Erlingsson Ú., Ligatti J. (октябрь 2009). “Control-flow integrity principles, implementations, and applications”. ACM Transactions on Information and System Security. 13: 1—40. DOI:10.1145/1609956.1609960. S2CID 207175177. Проверьте дату в |date= (справка на английском)
  11. 1 2 3 Shacham H. The geometry of innocent flesh on the bone: return-into-libc without function calls (on the x86) // Proceedings of the 14th ACM conference on Computer and communications security - CCS '07. — октябрь 2007. — P. 552–561. — ISBN 978-1-59593-703-2. — doi:10.1145/1315245.1315313.
  12. Jonathan Salwan, Allan Wirth, ROPgadget — Gadgets finder and auto-roper
  13. Hovav Shacham, Matthew Page, Ben Pfaff, Eu-Jin Goh, Nagendra Modadugu, Dan Boneh. «On the effectiveness of address-space randomization». Proceedings of the 11th ACM conference on Computer and Communications Security (CCS), 2004.
  14. James Bennett, Yichong Lin, Thoufique Haq. The Number of the Beast, 2013. https://www.fireeye.com/blog/threat-research/2013/02/the-number-of-the-beast.html
  15. Checkoway, S., Davi, L., Dmitrienko, A., Sadeghi, A.-R., Shacham, H., Winandy, M. 2010. Return-oriented programming without returns. In Proceedings of CCS 2010, A. Keromytis and V. Shmatikov, Eds. ACM Press, 559—572
  16. Onarlioglu, K., Bilge, L., Lanzi, A., Balzarotti, D., Kirda, E. 2010. G-Free: Defeating return-oriented programming through gadget-less binaries. In Proceedings of ACSAC 2010, M. Franz and J. McDermott, Eds. ACM Press, 49-58.
  17. Skowyra R., Casteel K., Okhravi H., Zeldovich N., Streilein W. Systematic Analysis of Defenses against Return-Oriented Programming // Research in Attacks, Intrusions, and Defenses. — октябрь 2013. — Vol. 8145. — P. 82–102. — ISBN 978-3-642-41283-7. — doi:10.1007/978-3-642-41284-4_5.
  18. Venkat, Ashish. HIPStR // Proceedings of the Twenty-First International Conference on Architectural Support for Programming Languages and Operating Systems / Ashish Venkat, Sriskanda Shamasunder, Hovav Shacham … [и др.]. — ACM, 2016-01-01. — P. 727–741. — ISBN 9781450340915. — doi:10.1145/2872362.2872408.
  19. Hiser J., Nguyen-Tuong A., Co M., Hall M., Davidson J. W. ILR: Where'd My Gadgets Go? // 2012 IEEE Symposium on Security and Privacy. — май 2012. — P. 571–585. — ISBN 978-1-4673-1244-8. — doi:10.1109/SP.2012.39.
  20. Venkat, Ashish; Arvind Krishnaswamy & Koichi Yamada et al., "Binary translator driven program state relocation", US 9135435, published 2015-09-15
  21. Vasilis Pappas, kBouncer: Efficient and Transparent ROP Mitigation, апрель 2012.
  22. Shelly, Asaf, "Security methods and systems by code mutation", US application 2019347385, published 2019-11-14
  23. Francillon, A., Perito, D., Castelluccia, C. 2009. Defending embedded systems against control flow attacks. In Proceedings of SecuCode 2009, S. Lachmund and C. Schaefer, Eds. ACM Press, 19-26.
  24. 1 2 Li, Jinku; Wang, Zhi; Jiang, Xuxian; Grace, Mike; Bahram, Sina. Defeating return-oriented rootkits with «return-less» kernels. В сборнике: Proceedings of EuroSys 2010, ред. G. Muller. ACM Press, 195—208.
  25. Avanzi, Roberto (2016). The QARMA Block Cipher Family (PDF). IACR Transactions on Symmetric Cryptology (ToSC). 17 (published 8 марта 2017). pp. 4—44. DOI:10.13154/tosc.v2017.i1.4-44. Архивировано из оригинала (PDF) 2020-05-13.
  26. Qualcomm Product Security. Pointer Authentication on ARMv8.3. Qualcomm Technologies Inc.. Дата обращения: 16 июня 2020. Архивировано 6 июня 2020 года.
  27. Linux 5.7 For 64-bit ARM Brings In-Kernel Pointer Authentication, Activity Monitors - Phoronix. www.phoronix.com. Дата обращения: 31 марта 2020. Архивировано 31 марта 2020 года.
  28. Ravichandran, Joseph; Na, Weon Taek; Lang, Jay; Yan, Mengjia (июнь 2022). “PACMAN: attacking ARM pointer authentication with speculative execution”. Proceedings of the 49th Annual International Symposium on Computer Architecture. Association for Computing Machinery. DOI:10.1145/3470496.3527429. HDL:1721.1/146470. Проверьте дату в |date= (справка на английском)
  29. Applying PAC and BTI techniques to real code. developer.arm.com. Дата обращения: 4 февраля 2024. Архивировано 28 июня 2025 года.
  30. Control Flow Integrity, anti-malware active protection on Arm64 systems. sipearl.com. Дата обращения: 4 февраля 2024. Архивировано 4 августа 2025 года.

Литература

  • «Return-Oriented Programming: Exploits Without Code Injection», Hovav Shacham, Erik Buchanan, Ryan Roemer, Stefan Savage. BlackHat 2008. Return-Oriented Programming: Exploits Without Code Injection (англ.). Дата обращения: 23 июня 2024.
  • Buchanan E., Roemer R., Shacham H., Savage S. «When Good Instructions Go Bad: Generalizing Return-Oriented Programming to RISC» // Proceedings of the 15th ACM conference on Computer and communications security — CCS '08, 2008. When Good Instructions Go Bad: Generalizing Return-Oriented Programming to RISC // Proceedings of the 15th ACM conference on Computer and communications security - CCS '08. — октябрь 2008. — P. 27–38. — ISBN 978-1-59593-810-7. — doi:10.1145/1455770.1455776.

Ссылки

Категории