Sigreturn-ориентированное программирование ( SROP ) — это метод эксплойта компьютерной безопасности , который позволяет злоумышленнику выполнять код при наличии мер безопасности, таких как неисполняемая память и подпись кода. [1] Впервые он был представлен на 35-м симпозиуме IEEE по безопасности и конфиденциальности в 2014 году, где он получил награду за лучшую студенческую работу . [2] Этот метод использует те же основные предположения, что и метод возвратно-ориентированного программирования (ROP): злоумышленник, управляющий стеком вызовов , например, через переполнение буфера стека , может влиять на поток управления программы с помощью простых последовательностей инструкций, называемых гаджетами . Атака работает путем помещения поддельной структуры sigcontext [3] в стек вызовов, перезаписывая исходный адрес возврата местоположением гаджета, который позволяет злоумышленнику вызвать системный вызов sigreturn [4] . [5] Часто для успешного осуществления этой атаки требуется всего один гаджет. Этот гаджет может находиться в фиксированном месте, что делает эту атаку простой и эффективной, с настройкой, как правило, более простой и портативной, чем та, которая необходима для простой техники возвратно-ориентированного программирования . [1]
Программирование, ориентированное на Sigreturn, можно считать странной машиной , поскольку оно допускает выполнение кода за пределами исходной спецификации программы. [1]
Sigreturn-ориентированное программирование (SROP) — это метод, аналогичный return-ориентированному программированию (ROP), поскольку он использует повторное использование кода для выполнения кода за пределами исходного потока управления. В этом смысле злоумышленник должен иметь возможность провести атаку на разрушение стека , обычно через переполнение буфера стека , чтобы перезаписать адрес возврата, содержащийся внутри стека вызовов .
Если используются такие механизмы, как предотвращение выполнения данных , злоумышленник не сможет просто поместить шелл-код в стек и заставить машину выполнить его, перезаписав адрес возврата. При наличии такой защиты машина не будет выполнять никакой код, присутствующий в областях памяти, помеченных как записываемые и неисполняемые. Поэтому злоумышленнику придется повторно использовать код, уже присутствующий в памяти.
Большинство программ не содержат функций, которые позволят злоумышленнику напрямую выполнить желаемое действие (например, получить доступ к оболочке ) , но необходимые инструкции часто разбросаны по памяти. [6]
Программирование с возвратом требует, чтобы эти последовательности инструкций, называемые гаджетами, заканчивались инструкцией RET
. Таким образом, злоумышленник может записать последовательность адресов для этих гаджетов в стек, и как только RET
инструкция в одном гаджете будет выполнена, поток управления перейдет к следующему гаджету в списке.
Эта атака возможна благодаря тому, как обрабатываются сигналы в большинстве POSIX -подобных систем. Всякий раз, когда поступает сигнал, ядру необходимо переключить контекст на установленный обработчик сигналов. Для этого ядро сохраняет текущий контекст выполнения в кадре в стеке. [5] [6]
Структура, помещенная в стек, является архитектурно-специфическим вариантом структуры sigcontext , которая содержит различные данные, включающие содержимое регистров на момент переключения контекста. Когда выполнение обработчика сигналов завершено, sigreturn()
вызывается системный вызов.
Вызов системного вызова sigreturn позволяет легко устанавливать содержимое регистров с помощью одного гаджета, который можно легко найти в большинстве систем. [1]
Существует несколько факторов, которые характеризуют эксплойт SROP и отличают его от классического эксплойта возвратно-ориентированного программирования. [7]
Во-первых, ROP зависит от доступных гаджетов, которые могут сильно отличаться в разных двоичных файлах , что делает цепочки гаджетов непереносимыми. Рандомизация адресного пространства (ASLR) затрудняет использование гаджетов без утечки информации для получения их точных позиций в памяти.
Хотя существуют Тьюринг-полные ROP-компиляторы, [8] обычно нетривиально создать цепочку ROP. [7]
Эксплойты SROP обычно переносимы между различными двоичными файлами с минимальными усилиями или вообще без них и позволяют легко устанавливать содержимое регистров, что может быть нетривиальным или невыполнимым для эксплойтов ROP, если необходимые гаджеты отсутствуют. [6] Более того, SROP требует минимального количества гаджетов и позволяет создавать эффективные шеллкоды путем объединения системных вызовов в цепочку. Эти гаджеты всегда присутствуют в памяти, а в некоторых случаях всегда находятся в фиксированных местах: [7]
Пример гаджета, необходимого для эксплойтов SROP, всегда можно найти в области памяти VDSO в системах x86- Linux :
__kernel_sigreturn proc рядом : pop eax mov eax , 77h int 80h ; LINUX — sys_sigreturn nop lea esi , [ esi + 0 ] __kernel_sigreturn endp
В некоторых версиях ядра Linux ASLR можно отключить, установив ограничение на размер стека на неограниченное значение [9] , что фактически обходит ASLR и обеспечивает легкий доступ к гаджету, присутствующему в VDSO.
Для ядер Linux до версии 3.3 также можно найти подходящий гаджет на странице vsyscall, который представляет собой механизм для ускорения доступа к определенным системным вызовам, часто используемым устаревшими программами, и всегда находится в фиксированном месте.
Можно использовать гаджеты для записи в содержимое стековых фреймов, тем самым создавая самомодифицирующуюся программу . Используя эту технику, можно разработать простую виртуальную машину , которую можно использовать в качестве цели компиляции для Тьюринг-полного языка. Пример такого подхода можно найти в статье Босмана, которая демонстрирует построение интерпретатора для языка, похожего на язык программирования Brainfuck . Язык предоставляет счетчик программ PC
, указатель памяти P
и временный регистр, используемый для 8-битного сложения A
. Это означает, что также можно разработать сложные бэкдоры или запутанные атаки. [1]
Существует ряд методов смягчения атак SROP, основанных на рандомизации макета адресного пространства , канарейках и куки-файлах или теневых стеках .
Рандомизация компоновки адресного пространства затрудняет использование подходящих гаджетов, делая их расположение непредсказуемым.
Предложено смягчение SROP, называемое сигнальными куки-файлами . Оно заключается в способе проверки того, что структура sigcontext не была подделана с помощью случайного куки-файла, объединенного с помощью XOR с адресом расположения стека, где он должен храниться. Таким образом, системному вызову sigreturn нужно просто проверить наличие куки-файла в ожидаемом месте, эффективно смягчая SROP с минимальным влиянием на производительность. [1] [10]
В версиях ядра Linux выше 3.3 эмулируется интерфейс vsyscall, и любая попытка напрямую выполнить гаджеты на странице приведет к исключению. [11] [12]
Grsecurity — это набор исправлений для ядра Linux , призванный усилить и улучшить безопасность системы. [13] Он включает в себя так называемую защиту обратного адреса (RAP), помогающую защититься от атак с повторным использованием кода. [14]
Начиная с 2016 года Intel разрабатывает технологию обеспечения контроля потока ( CET ), чтобы помочь смягчить и предотвратить эксплойты с перескоком стека. CET работает путем внедрения теневого стека в ОЗУ, который будет содержать только адреса возврата, защищенные блоком управления памятью ЦП . [15] [16]