Источник: https://github.com/AnaktaCTF/CTF/blob/main — PWN/Bypassing_ASLR_and_DEP_in_modern_exploits.md

С развитием технологий безопасности, такие механизмы, как ASLR (Address Space Layout Randomization) и DEP (Data Execution Prevention), значительно усложнили задачу для атакующих. Эти технологии защищают память от ряда популярных атак, таких как переполнение буфера, но всё же не делают систему неприступной. Злоумышленники по-прежнему разрабатывают новые методы обхода этих защит, что продолжает быть важной темой в области информационной безопасности.

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


image

Что такое ASLR?

ASLR (случайная организация адресного пространства) — это технология защиты, которая случайным образом меняет расположение важных структур в памяти, таких как стек, куча и динамически загружаемые библиотеки (например, libc в Linux или kernel32.dll в Windows). Это делает сложным предсказание точных адресов в памяти, что сильно затрудняет успешные атаки, основанные на знании этих адресов.

Как обходят ASLR?

Утечка адресов

Одна из самых распространённых техник обхода ASLR — это использование утечек памяти. Когда программа случайно выводит важные данные, такие как адреса или указатели, в логах или через другие каналы, атакующий может использовать эти данные для дальнейших действий.

image

Когда программа выводит в лог или консоль адрес памяти (например, через id или указатели), злоумышленник может использовать эту информацию, чтобы понять, где находятся важные данные, такие как функции или буферы, и атаковать систему. В случае с ASLR это помогает точно предсказать местоположение объектов в памяти.

Return-Oriented Programming (ROP)

Когда ASLR активирован, и атакующий не может полагаться на точные адреса памяти, он может использовать метод Return-Oriented Programming (ROP).

ROP — это техника, при которой вместо выполнения произвольного кода атакующий использует уже существующие инструкции, которые находятся в памяти программы. Эти инструкции называются гаджетами (gadgets) и представляют собой маленькие фрагменты кода, которые завершаются командой возврата (RET). Используя такие гаджеты, атакующий может построить цепочку команд, которые выполнят необходимые действия, например, вызов функции или выполнение системных команд.

Как работает ROP:

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

  2. Программе подставляются адреса инструкций (гаджетов), которые уже присутствуют в памяти.

  3. Эти гаджеты выполняются по очереди, выполняя произвольный код, даже если ASLR активирован.

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

image

Этот код выполняет атаку Return-Oriented Programming (ROP), используя существующие инструкции программы для выполнения произвольного кода.

Код использует 3 инструкции:

pop eax; ret — извлекает значение в регистр eax.

pop ebx; ret — извлекает значение в регистр ebx.

system — вызывает системную функцию для выполнения команд.

Заполняется буфер строкой "A" * 64 (для переполнения).

Затем вставляются гаджеты, чтобы установить значения в регистры eax и ebx как "/bin" и "sh".

Наконец, вызывается system("/bin/sh"), что открывает командную оболочку.

Запуск эксплойта:

С помощью subprocess.run() эксплойт запускает уязвимую программу, передавая ей подготовленный payload, который выполняет команду для открытия оболочки.

Результат: Открывается командная оболочка (/bin/sh), что позволяет атакующему выполнять команды в системе.

Brute Force / Перебор адресов

Если система использует ASLR с низким уровнем энтропии (например, 8 или 16 бит для адресации), атакующие могут применить метод перебора адресов.

• Это может быть полезно в случае, когда атакующему известно, что ASLR случайным образом меняет расположение объектов в памяти, но не на очень большой диапазон.

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

image

Этот код демонстрирует атаку методом перебора адресов:

Функция vulnerable_program переполняет буфер размером 64 байта, записывая в него данные пользователя, что может привести к перезаписи памяти.

Функция brute_force перебирает возможные адреса и создает payload из 64 байтов "A" (для переполнения) и текущего адреса. Затем пытается выполнить уязвимую программу с каждым payload.

Цель — найти правильный адрес, чтобы перезаписать память и выполнить вредоносный код.

JIT Spraying (Heap Spraying)

Это техника, которая активно используется для обхода ASLR в контексте браузеров и интерпретируемых языков программирования (например, JavaScript). Она включает в себя «засорение» кучи предсказуемыми паттернами (например, shellcode, NOP sled), что помогает атакующему обойти рандомизацию расположения данных в памяти.

Принцип работы:

  1. Атакующий заполняет кучу или область памяти предсказуемыми данными, такими как вредоносный код.

  2. Это делает трудным случайное распределение памяти, позволяя атакующему выполнить произвольный код в заранее подготовленной области.

image

Этот код демонстрирует метод Heap Spraying:

Создается серия байтов \x90, чтобы обойти DEP и направить выполнение к вредоносному коду.

Добавляется вредоносный код.

Затем вызывается уязвимая программа, передавая ей этот payload, чтобы заполнить кучу вредоносными данными.

Цель — разместить вредоносный код в куче и увеличить шанс его выполнения.

Использование неблокируемых модулей

Некоторые модули в операционной системе могут не поддерживать ASLR или поддерживать его слабо. Например, старые библиотеки или системные утилиты, которые не имеют защиты ASLR.

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

image

С помощью ctypes.CDLL("libc.so.6") загружается стандартная C-библиотека libc в Linux. Эта библиотека содержит функции, такие как system(), которые могут быть использованы для выполнения системных команд.

Используется функция libc.system(b"/bin/sh"), чтобы вызвать команду "/bin/sh", что открывает командную оболочку.

Этот подход используется для выполнения команд в системе через доступ к неблокируемым модулям, что позволяет обходить защиты и получать контроль над системой.


Что такое DEP?

DEP (Data Execution Prevention) — это технология безопасности, предназначенная для предотвращения выполнения кода в областях памяти, которые предназначены исключительно для хранения данных. Например, это может быть стек или куча.
DEP блокирует попытки выполнения кода в этих областях, что помогает предотвратить атаки, такие как переполнение буфера, при которых злоумышленник пытается выполнить вредоносный код, размещённый в этих областях памяти.

Как работает DEP?

Стек и куча - в обычной ситуации данные, такие как переменные или массивы, хранятся в памяти, но с использованием DEP эти области помечаются как только для данных. Таким образом, даже если злоумышленник сможет записать вредоносный код в эти области, система не позволит выполнить его как инструкцию.

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

Как обходят DEP?

Return-Oriented Programming (ROP)

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

JIT-компиляция

JIT (Just-In-Time) компиляция используется в некоторых приложениях, например, в браузерах, где код генерируется и выполняется на лету. Этот код может быть размещён в области памяти, где DEP не действует. В результате, злоумышленники могут использовать уязвимости в JIT-компиляторах для внедрения и выполнения произвольного кода, минуя защиту DEP. В случае JIT-компиляции исполнимый код генерируется в процессе работы программы и может быть размещён в таких областях памяти, где защиты от выполнения (DEP) нет. Это даёт злоумышленникам возможность использовать уязвимости JIT-компилятора, чтобы исполняемый код оказался в незащищённой области и смог выполнить произвольные инструкции.

Системные вызовы (System Calls)

Системные вызовы — это механизм, через который приложения могут запрашивать выполнение операций от имени операционной системы. Злоумышленники могут использовать системные вызовы, чтобы загрузить или выполнить код из области памяти, которая не защищена DEP. С помощью системных вызовов, таких как VirtualAlloc, можно выделить память, которая будет исполнимая, и затем записать в неё произвольный код. Системные вызовы могут помочь атакующим загрузить и выполнить вредоносный код из защищённой памяти, не нарушая DEP.

В некоторых случаях злоумышленники могут использовать уязвимости гипервизора (например, VMWare или Hyper-V) или техники виртуализации для обхода DEP. Это может быть связано с эксплуатацией слабых мест в виртуализированном окружении, где виртуальные машины или гипервизоры не обеспечивают такой же уровень защиты, как хостовая операционная система.


Комбинированные методы обхода ASLR и DEP

Современные эксплойты часто используют несколько техник сразу, чтобы обойти обе защиты.

Утечка адресов + ROP

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

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

JIT-компиляция + ROP

• В некоторых приложениях, таких как браузеры или интерпретируемые языки программирования, используется JIT-компиляция (Just-In-Time). Этот процесс позволяет выполнять код, который генерируется на лету и может быть размещён в памяти в местах, где DEP не применяется.

• Атакующие могут использовать уязвимости JIT-компилятора, чтобы внедрить вредоносный код или запустить цепочку ROP-гаджетов, обойдя как DEP, так и ASLR. В этом случае вредоносный код может быть выполнен в области памяти, не защищённой DEP, после того как адреса для ROP-цепочек будут получены через утечку.


Современные механизмы защиты

Задача по защите от атак становится всё сложнее, и в ответ на методы обхода ASLR и DEP были разработаны новые защитные технологии.

Control Flow Integrity (CFI)

CFI помогает предотвратить изменение потока выполнения программы. Даже если атакующий использует ROP, он не сможет выполнить несанкционированные инструкции, так как CFI строго ограничивает, где могут происходить переходы.

Stack Canaries

Это специальные "сторожевые" значения, которые вставляются между данными на стеке и адресами возврата. Если злоумышленник пытается перезаписать адрес возврата (например, при переполнении буфера), это значение будет повреждено, и программа распознает попытку атаки.

Реализация DEP

В некоторых системах защита от выполнения кода не ограничивается только куском памяти, но распространяется на весь процесс. Такой подход даёт дополнительные гарантии безопасности и усложняет использование техник вроде ROP.


Невзирая на постоянное улучшение механизмов безопасности, таких как ASLR и DEP, хакеры находят новые способы обойти эти защиты. Комбинированные методы, такие как использование утечек адресов и ROP, остаются важными инструментами в арсенале атакующих. Однако новые технологии защиты, такие как CFI и stack canaries, значительно усложняют процесс эксплуатации уязвимостей.
Этот постоянный процесс "обострения" между защитой и атакой требует от разработчиков и специалистов по безопасности постоянной работы над улучшением защиты и созданием новых методов для борьбы с современными угрозами.