Программирование с возвратом сигнатуры (SROP ) - это эксплойт компьютерной безопасности метод, позволяющий злоумышленнику выполнить код при наличии таких мер безопасности, как неисполняемая память и подпись кода. Он был впервые представлен на 35-й конференции IEEE по безопасности и конфиденциальности в 2014 году, где получил награду за лучшую студенческую работу. Этот метод использует те же базовые предположения, что и метод ориентированного на возврат (ROP) программирования: злоумышленник управляет стеком вызовов , например, посредством переполнения буфера стека, может влиять на поток управления программы с помощью простых последовательностей инструкций, называемых гаджетами. Атака работает путем проталкивания поддельной структуры sigcontext в стек вызовов, перезаписывая исходный адрес возврата местоположением гаджета, который позволяет злоумышленнику вызвать системный вызов sigreturn . Часто для успешной реализации этой атаки требуется всего лишь один гаджет. Этот гаджет может находиться в фиксированном месте, что делает эту атаку простой и эффективной, с настройкой, как правило, более простой и переносимой, чем та, которая требуется для простого возвратно-ориентированного программирования.
Sigreturn -ориентированное программирование можно рассматривать как странную машину, поскольку оно допускает выполнение кода за пределами исходной спецификации программы.
Sigreturn-ориентированное программирование (SROP) является аналогичной техникой в ориентированное на возврат (ROP) программирование, поскольку оно использует повторное использование кода для выполнения кода за пределами области исходного потока управления. В этом смысле злоумышленник должен иметь возможность выполнить атаку разбиения стека, обычно через переполнение стека буфера, чтобы перезаписать адрес возврата, содержащийся внутри стека вызовов ..
Если используются такие механизмы, как предотвращение выполнения данных, злоумышленник не сможет просто разместить шеллкод на стек и заставит машину выполнить его, перезаписав адрес возврата. С такой защитой машина не будет выполнять какой-либо код, присутствующий в областях памяти, отмеченных как доступные для записи и неисполняемые. Таким образом, злоумышленнику потребуется повторно использовать код, уже имеющийся в памяти.
Большинство программ не содержат функций, которые позволят злоумышленнику напрямую выполнить желаемое действие (например, получить доступ к оболочке ), но необходимые инструкции часто разбросаны по памяти.
Ориентированное на возврат программирование требует, чтобы эти последовательности инструкций, называемые гаджетами, заканчивались инструкцией RET
. Таким образом, злоумышленник может записать последовательность адресов для этих гаджетов в стек, и как только в одном гаджете будет выполнена инструкция RET
, поток управления перейдет к следующему гаджету в списке..
Эта атака возможна благодаря тому, как сигналы обрабатываются в большинстве POSIX -подобные системы. Каждый раз, когда сигнал доставляется, ядру необходимо переключить контекст на установленный обработчик сигнала. Для этого ядро сохраняет текущий контекст выполнения в кадре в стеке. Структура, помещенная в стек, является архитектурно-зависимым вариантом структуры sigcontext, которая хранит различные данные, составляющие содержимое регистров в момент переключения контекста. Когда выполнение обработчика сигнала завершается, вызывается системный вызов sigreturn ()
.
Вызов системного вызова sigreturn означает возможность легко установить содержимое регистров с помощью одного гаджета, который можно легко найти в большинстве систем.
Есть несколько факторов, которые характеризуют эксплойт SROP и отличают его от классического эксплойта, ориентированного на возврат.
Во-первых, ROP зависит от доступных гаджетов, которые могут сильно отличаться в разных двоичных файлах, таким образом изготовление цепочек гаджетов непереносными. Рандомизация разметки адресного пространства (ASLR) затрудняет использование гаджетов без утечки информации для получения их точных позиций в памяти.
Хотя существуют полные по Тьюрингу компиляторы ROP, обычно нетривиально создать цепочку ROP.
Эксплойты SROP обычно переносятся между различными двоичными файлами с минимальным или нулевым усилия и позволяют легко настраивать содержимое регистров, что может быть нетривиальным или невыполнимым для эксплойтов ROP, если необходимые гаджеты отсутствуют. Кроме того, SROP требует минимального количества гаджетов и позволяет создавать эффективные шелл-коды путем объединения системных вызовов. Эти гаджеты всегда присутствуют в памяти, а в некоторых случаях всегда находятся в фиксированных местах:
ОС | ASLR | Гаджет | Карта памяти | Местоположение фиксированной памяти |
---|---|---|---|---|
Linux i386 | sigreturn | [vdso] | ||
Linux < 3.11 ARM | sigreturn | [векторы] | 0xffff0000 | |
Linux < 3.3 x86-64 | системный вызов и возврат | [vsyscall] | 0xffffffff600000 | |
Linux ≥ 3.3 x86-64 | системный вызов и возврат | Libc | ||
Linux x86-64 | sigreturn | Libc | ||
FreeBSD 9.2 x86-64 | sigreturn | 0x7ffffffff000 | ||
Mac OSX x86-64 | sigreturn | Libc | ||
iOS ARM | sigreturn | Libsystem | ||
iOS ARM | syscall return | Libsystem |
Пример гаджета, необходимого для эксплойтов SROP, всегда можно найти в области памяти VDSO в системах x86- Linux :
__kernel_sigreturn proc near: pop eax mov eax, 77h int 80h; LINUX - sys_sigreturn nop lea esi, [esi + 0] __kernel_sigreturn endp
В некоторых версиях ядра Linux ASLR можно отключить, установив ограничения на размер стека до неограниченного, эффективно обходя ASLR и обеспечивая легкий доступ к гаджету, присутствующему в VDSO.
Для ядер Linux до версии 3.3 также можно найти подходящий гаджет на странице vsyscall, который является механизмом для ускорения доступа к определенным системным вызовам, часто используемым устаревшими программами, и всегда находится в фиксированное местоположение.
Можно использовать гаджеты для записи в содержимое фреймов стека, тем самым создавая самомодифицирующуюся программу. Используя эту технику, можно разработать простую виртуальную машину, которую можно использовать в качестве цели компиляции для полного по Тьюрингу языка. Пример такого подхода можно найти в статье Босмана, в которой демонстрируется построение интерпретатора для языка, подобного языку программирования Brainfuck. В языке есть счетчик программ PC
, указатель памяти P
и временный регистр, используемый для 8-битового сложения A
. Это означает, что также могут быть разработаны сложные бэкдоры или замаскированные атаки.
Существует ряд методов для смягчения атак SROP, основанных на адресе рандомизация компоновки пространства, канареек и куки или теневые стеки.
рандомизация компоновки адресного пространства затрудняет использовать подходящие гаджеты, делая их местоположение непредсказуемым.
Было предложено смягчение последствий для SROP, называемое сигнальными куки-файлами. Он состоит из способа проверки того, что структура sigcontext не была изменена с помощью случайного файла cookie XORed с адресом места стека, в котором он должен быть сохранен. Таким образом, системному вызову sigreturn просто необходимо проверить наличие файла cookie в ожидаемом месте, эффективно уменьшая SROP с минимальным влиянием на производительность.
В версиях ядра Linux выше 3.3, интерфейс vsyscall эмулируется, и любая попытка прямого запуска гаджетов на странице приведет к исключению.
Grsecurity - это набор исправлений для ядра Linux для усиления и повышения безопасности системы. Он включает так называемую защиту обратного адреса (RAP) для защиты от атак повторного использования кода.
Начиная с 2016 года Intel разрабатывает Технология Control-Flow Enforcement (CET), чтобы помочь смягчить и предотвратить эксплойты со скачкообразным изменением стека. CET работает путем реализации теневого стека в ОЗУ, который будет содержать только адреса возврата, защищенных блоком управления памятью ЦП.