Зачем нужна рандомизация адресов памяти для загрузки библиотек? - PullRequest
2 голосов
/ 20 октября 2010

ldd отображает адреса памяти, по которым общие библиотеки связаны во время выполнения

$ cat one.c 
#include<stdio.h>

int main() {
    printf ("%d", 45);
}
$ gcc one.c -o one -O3
$ ldd one
    linux-gate.so.1 =>  (0x00331000)
    libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0x00bc2000)
    /lib/ld-linux.so.2 (0x006dc000)
$

С этот ответ на другой вопрос,

... Адреса в основном случайные числа.До разработки безопасных реализаций ldd последовательно указывал адреса памяти, куда были загружены программные разделы.Примерно пять лет назад многие разновидности Linux теперь намеренно рандомизируют адреса загрузки, чтобы расстроить потенциальных писателей вирусов и т. Д.

Я не до конца понимаю, как эти адреса памяти можно использовать для эксплуатации.

Является ли проблема чем-то вроде «Если адреса фиксированы, по этому адресу можно поместить некоторый нежелательный код, который будет связан, как если бы это была библиотека», или это нечто большее?

Ответы [ 4 ]

3 голосов
/ 21 октября 2010

Некоторые уязвимости позволяют перезаписывать некоторые адреса (переполнения стека позволяют перезаписывать адреса возврата, эксплойты для переполнения кучи обычно перезаписывают указатели SEH на Win32 и адреса (GOT-записи) динамически вызываемых функций в Linux, ...). Таким образом, злоумышленник должен сделать так, чтобы перезаписанный адрес указывал на что-то интересное. Чтобы сделать это более трудным, было принято несколько контрмер:

  • Неисполняемые стеки препятствуют тому, чтобы эксплойты просто переходили к некоторому коду, который злоумышленник поместил в стек.
  • W ^ X сегменты (сегменты, которые никогда не могут быть доступны для записи и выполнения одновременно) предотвращают то же самое для других областей памяти.
  • Рандомизированные адреса загрузки для библиотек и независимые от позиции исполняемые файлы уменьшают вероятность успешной эксплуатации с помощью методов возврата в libc и возврата-ориентированного программирования, ...
  • Рандомизированные адреса загрузки также не позволяют злоумышленникам заранее знать, где найти интересную функцию (например: представьте злоумышленника, который может перезаписать запись GOT и часть сообщения для следующего вызова регистрации, зная, что адрес system будет быть "интересным").

Итак, вы должны рассматривать рандомизацию адреса нагрузки как еще одну контрмеру среди многих (несколько уровней защиты и все такое).

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

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

И, наконец, я отмечу, что есть два способа рандомизировать адреса загрузки библиотеки:

  • Делайте это при каждой загрузке: это делает (некоторые) эксплойты менее надежными, даже если злоумышленник может получить информацию об адресах за один прогон и попытаться использовать эту информацию при другом прогоне.
  • Сделайте это один раз для системы: это то, что делает prelink -R. Это позволяет избежать использования злоумышленниками общей информации, например, для всех блоков Redhat 7.2. Очевидно, его преимущество в том, что он не мешает prelink:).
3 голосов
/ 20 октября 2010

"Если адреса фиксированы, по этому адресу можно поместить некоторый нежелательный код, который будет связан, как если бы это была библиотека" *

Да.

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

http://www.corewars.org/ Отличная иллюстрация принципа.

2 голосов
/ 21 октября 2010

Простой пример:

Если в популярной операционной системе стандартная библиотека C всегда загружалась по адресу 0x00100000, а последняя версия стандартной библиотеки C имела функцию system со смещением 0x00000100, тогда, если кто-то мог использовать уязвимость в программе, работающей на компьютере с этой операционной системой (такой как веб-сервер), который заставляет его записывать некоторые данные в стек (через переполнение буфера), они будут знать, что очень вероятно, что если они запишут 0x00100100 в место в стеке, где текущая функция ожидала, что ее адрес возврата будет таким, что они могли бы сделать так, чтобы при возврате из текущей функции была вызвана функция system. Хотя они все еще не сделали всего необходимого, чтобы заставить system выполнить то, что им нужно, они близки, и есть некоторые приемы, которые записывают больше вещей в стек по адресу, упомянутому выше, с высокой вероятностью получающегося результата. в действительном указателе строки и команде (или серии команд), выполняемой этим принудительным вызовом к system.

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

1 голос
/ 20 октября 2010

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

...