Переполнение кучи
Переполнение кучи (англ. heap overflow, также встречаются названия heap overrun и heap smashing) — разновидность переполнения буфера, возникающая в области данных кучи. В отличие от переполнения стека, методы эксплуатации переполнения кучи отличаются. Память в куче выделяется динамически во время исполнения программы и обычно содержит данные приложения. Вредоносная эксплуатация заключается в специфическом повреждении этих данных с целью заставить приложение перезаписать внутренние структуры, такие как связанные списки и указатели. Классическим примером является перезапись связей динамического распределения памяти (например, метаданных malloc) с использованием получившейся подмены указателей для изменения указателя на функцию.
Например, в более ранних версиях Linux два буфера, выделенных рядом в куче, могли привести к тому, что первый буфер перезаписывал метаданные второго буфера. Установив бит «занятости» второго буфера в ноль и задав его длину малым отрицательным значением (что позволяет копировать нулевые байты), при вызове free() для первого буфера программа попытается объединить эти два буфера в один. При этом освобождаемый буфер должен содержать два указателя FD и BK в первых 8 байтах ранее выделенного блока. Значение BK записывается в FD и может быть использовано для подмены указателя.
Последствия
Случайное переполнение кучи может привести к повреждению данных или к неожиданному поведению любого процесса, получающего доступ к затронутой области памяти. На операционных системах без защиты памяти это может быть любой процесс в системе.
Например, переполнение буфера JPEG в GDI+ корпорации Microsoft позволяло удалённое выполнение кода на атакуемом компьютере[1].
Jailbreak iOS часто использует переполнение кучи для получения произвольного выполнения кода.
Обнаружение и предотвращение
В случае переполнений буфера существует три основных способа защиты от переполнения кучи. Современные операционные системы, такие как Windows и Linux, реализуют все три подхода:
- Предотвращение выполнения вредоносного кода путём разделения кода и данных, обычно с помощью аппаратных средств, таких как NX-бит
- Введение случайности в расположение кучи, чтобы её адрес не был фиксированным, например с помощью функций ядра, таких как рандомизация расположения в адресном пространстве
- Введение проверок целостности в менеджер кучи
Начиная с версии 2.3.6, glibc включает механизмы защиты, способные обнаруживать переполнение кучи постфактум, например, посредством проверки согласованности указателей при вызове unlink. Однако было показано, что эти меры защиты могут обходиться злоумышленниками[2][3]. Кроме того, поддержка ASLR присутствует в Linux с 2005 года, хотя PaX реализовал подобные функции задолго до этого. Также поддержка NX-бита реализована в Linux с 2004 года.
Microsoft также реализовала защиту от переполнения буферов в куче с апреля 2003 года в Windows Server 2003 и с августа 2004 года в Windows XP (начиная с Service Pack 2). Эти меры включают безопасную обработку unlink и использование cookie в заголовках блоков кучи. В более поздних версиях Windows (таких как Vista, Server 2008 и Windows 7) реализованы: удаление часто используемых для атак структур данных, рандомизация метаданных кучи, расширение использования cookie, случайное смещение базового адреса кучи, кодирование указателей на функции, немедленное завершение работы при обнаружении повреждения кучи и вариации алгоритма выделения. Обычная DEP и ASLR также помогают снижать эффективность подобных атак[4].
Наиболее распространённым методом обнаружения переполнения кучи является динамический анализ во время выполнения. Такой подход позволяет выявлять уязвимости по признакам нарушения безопасности в процессе работы приложения[5].
Примечания
Ссылки
- Vudo malloc tricks
- Статья о переполнении кучи на Heise Security
- Defeating Microsoft Windows XP SP2 Heap protection and DEP bypass. Дата обращения: 28 июня 2024. Архивировано 1 ноября 2013 года.