Поскольку отладочный вывод динамического компоновщика/загрузчика ld
подтверждает, что обе программы victim
и spy
загружают правильный входной файл, следующим шагом будет проверка того, действительно ли ядро настроило физический файл. страницы, где libmyl.so
загружаются в память для совместного использования victim
и spy
.
В Linux это можно проверить, начиная с версии ядра 2.6.25, через интерфейсpagemap
в ядре, который позволяет программам пользовательского пространства проверять таблицы страниц и соответствующую информацию, читая файлы в /proc
.
Общая процедура использования карты страниц для определения того, разделяют ли два процесса память, выглядит следующим образом:
/proc//maps
для обоих процессов, чтобы определить, какие части пространства памяти каким объектам сопоставляются. libmyl.so
. /proc//pagemap
. pagemap
состоит из 64 -битовых дескрипторов карты страниц, по одному на страницу. Сопоставление между адресом страницы и адресом ее дескриптора в pagemap
равно адресу страницы/размеру страницы *размеру дескриптора . Найдите дескрипторы страниц, которые вы хотите изучить. pagemap
. libmyl.so
для victim
и spy
. Если PFN совпадают, два процесса совместно используют одни и те же физические страницы. В следующем примере кода показано, как можно получить доступ к pagemap
и распечатать его внутри процесса. Он используетdl_iterate_phdr()
для определения виртуального адреса каждой совместно используемой библиотеки, загруженной в пространство памяти процессов, затем ищет и печатает соответствующий pagemap
из /proc/
.
#define _GNU_SOURCE
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define E_CANNOT_OPEN_PAGEMAP 1
#define E_CANNOT_READ_PAGEMAP 2
typedef struct __attribute__ ((__packed__)) {
union {
uint64_t pmd;
uint64_t page_frame_number : 55;
struct {
uint64_t swap_type: 5;
uint64_t swap_offset: 50;
uint64_t soft_dirty: 1;
uint64_t exclusive: 1;
uint64_t zero: 4;
uint64_t file_page: 1;
uint64_t swapped: 1;
uint64_t present: 1;
};
};
} pmd_t;
static int print_pagemap_for_phdr(struct dl_phdr_info *info,
size_t size, void *data)
{
struct stat statbuf;
size_t pagesize = sysconf(_SC_PAGESIZE);
char pagemap_path[BUFSIZ];
int pagemap;
uint64_t start_addr, end_addr;
if (!strcmp(info->dlpi_name, "")) {
return 0;
}
stat(info->dlpi_name, &statbuf);
start_addr = info->dlpi_addr;
end_addr = (info->dlpi_addr + statbuf.st_size + pagesize) & ~(pagesize-1);
printf("\n%10p-%10p %s\n\n",
(void *)start_addr,
(void *)end_addr,
info->dlpi_name);
snprintf(pagemap_path, sizeof pagemap_path, "/proc/%d/pagemap", getpid());
if ((pagemap = open(pagemap_path, O_RDONLY)) < 0) {
error(E_CANNOT_OPEN_PAGEMAP, errno,
"cannot open pagemap: %s", pagemap_path);
}
printf("%10s %8s %7s %5s %8s %7s %7s\n",
"", "", "soft-", "", "file /", "", "");
printf("%10s %8s %7s %5s %11s %7s %7s\n",
"address", "pfn", "dirty", "excl.",
"shared anon", "swapped", "present");
for (unsigned long i = start_addr; i < end_addr; i += pagesize) {
pmd_t pmd;
if (pread(pagemap, &pmd.pmd, sizeof pmd.pmd, (i / pagesize) * sizeof pmd) != sizeof pmd) {
error(E_CANNOT_READ_PAGEMAP, errno,
"cannot read pagemap: %s", pagemap_path);
}
if (pmd.pmd != 0) {
printf("0x%10" PRIx64 " %06" PRIx64 " %3d %5d %8d %9d %7d\n", i,
(unsigned long)pmd.page_frame_number,
pmd.soft_dirty,
pmd.exclusive,
pmd.file_page,
pmd.swapped,
pmd.present);
}
}
close(pagemap);
return 0;
}
int main()
{
dl_iterate_phdr(print_pagemap_for_phdr, NULL);
exit(EXIT_SUCCESS);
}
Вывод программы должен выглядеть следующим образом:
$ sudo./a.out
0x7f935408d000-0x7f9354256000 /lib/x86_64-linux-gnu/libc.so.6
soft- file /
address pfn dirty excl. shared anon swapped present
0x7f935408d000 424416 1 0 1 0 1
0x7f935408e000 424417 1 0 1 0 1
0x7f935408f000 422878 1 0 1 0 1
0x7f9354090000 422879 1 0 1 0 1
0x7f9354091000 43e879 1 0 1 0 1
0x7f9354092000 43e87a 1 0 1 0 1
0x7f9354093000 424790 1 0 1 0 1
...
где:
address
— виртуальный адрес страницы pfn
— номер кадра страницы soft-dirty
указывает, установлен ли программный -грязный бит в записи таблицы страниц (PTE ). excl.
указывает, отображается ли страница исключительно (, т. е. страница отображается только для этого процесса ). file / shared anon
указывает, является ли страница файловой страницей или общей анонимной страницей. swapped
указывает, что страница в данный момент заменена. (означает, что present
равно нулю ). present
указывает, присутствует ли страница в данный момент в резидентном наборе процессов. (означает, что swapped
равно нулю ). (Примечание :Я запускаю пример программы с sudo
, так как начиная с Linux 4.0 только пользователи с возможностью CAP_SYS_ADMIN
могут получать PFN из /proc/
. Начиная с Linux 4.2 поле PFN обнуляется, если у пользователя нет CAP_SYS_ADMIN
. Причина этого изменения заключается в том, чтобы затруднить использование другой уязвимости, связанной с памятью, атаки Rowhammer , с использованием информации о физическом отображении виртуального -в -, раскрываемом PFN.)
Если вы запустите пример программы несколько раз, вы должны заметить, что виртуальный адрес страницы должен измениться (из-за ASLR ), но PFN для разделяемых библиотек, которые используются другими процессами должно остаться прежним.
Если PFN для libmyl.so
совпадают между программами victim
и spy
, я бы начал искать причину неудачи атаки в самом коде атаки. Если PFN не совпадают, дополнительные биты могут подсказать, почему страницы не настроены для совместного использования. Биты pagemap
указывают следующее:
present file exclusive state:
0 0 0 non-present
1 1 0 file page mapped somewhere else
1 1 1 file page mapped only here
1 0 0 anonymous non-copy-on-write page (shared with parent/child)
1 0 1 anonymous copy-on-write page (or never forked)
Копировать -на -страницы записи в области (MAP_FILE | MAP_PRIVATE)
в этом контексте являются анонимными.
Бонус:Чтобы получить количество раз отображения страницы, можно использовать PFN для поиска страницы в /proc/kpagecount
. Этот файл содержит 64-битное число -числа отображений каждой страницы, проиндексированных PFN.
Предположим, рассматриваемая система является веб-сервером. Предположим также, что администратор сервера предоставляет некоторое программное обеспечение, установленное в системе, для широкой публики (или корпоративной интрасети )через веб-страницу. Это может быть так же просто, как изменение размера изображения, калькулятор или словарь.
Если программное обеспечение имело справочные страницы, связанные с ним при установке, то администратор — будучи добрым и внимательным человеком — мог бы решить, что сделать эти справочные страницы доступными для пользователей веб-службы также будет хорошая идея.
Итак, значок «Справка» на веб-странице запускает сценарий, который захватывает одну или несколько — кэшированных — справочных страниц и отправляет их в браузер пользователя.
Любой человек или код, имеющий доступ на запись к каталогу кеша, может изменить эти файлы на:
Любой человек с воображением и распущенной моралью/этикой может злоупотреблять любым из вышеперечисленных способов множеством различных способов.
Большинство современных дистрибутивов предварительно -кэшируют справочные страницы (путем обработки с помощью troff ), когда установлен соответствующий пакет. Это не проблема.
Проблема возникает, когда исходные справочные файлы присутствуют, но кеш пуст (, т. е. файлы кеша не были предварительно -сгенерированы ).
Есть два способа справиться с этим:
Для запуска от имени root man должен иметь setuid. Если в что-нибудь были какие-либо недостатки безопасности, например. синтаксический анализ командной строки, злоумышленник может получить повышенные привилегии
Вот соответствующий источник:https://git.savannah.gnu.org/cgit/man-db.git/tree/src/man.c
К счастью, все основные дистрибутивы теперь предварительно -кэшируют справочные страницы, так что не о чем беспокоиться
Каждый раз, когда каталог становится доступным для глобальной записи, возникает брешь в системе безопасности. Игнорирование того, какова предполагаемая цель каталога и как это можно подорвать, просто сделать его доступным для записи - проблема.
Вот несколько возможных проблем, не связанных с функцией каталога:
Уместной здесь концепцией является поверхность атаки .
Поверхность атаки — это диапазон мест, где злоумышленник может искать и потенциально находить уязвимость.
Каталог, в который может производить запись скомпрометированная учетная запись, представляет собой поверхность атаки, которую можно использовать для попытки скомпрометировать другие учетные записи, используя ошибки в программном обеспечении, запущенном этими другими учетными записями, и то, как это программное обеспечение анализирует содержимое этот каталог.
Использование каталогов общего кэша требует, чтобы другие пользователи, имеющие доступ на запись к этому каталогу, доверяли запись содержимого в этот каталог только в ожидаемой форме. Если инструменты, задействованные в рендеринге справочных страниц, имеют уязвимости, доверять им может быть глупо.
(Другой формой атаки на общие каталоги является создание там символических ссылок, указывающих на файл, содержимое которого злоумышленник хотел бы перезаписать, но не имеет на это прав; когда другая учетная запись пользователя пытается обновить запись кэша, связанную с файлом, на который указывает символическая ссылка, инструмент, который не был тщательно написан, может перезаписать целевой файл вместо символической ссылки ).
Учтите, что необходимо нейтрализовать поверхность атаки , даже если в настоящее время не известны открытые уязвимости в части программного обеспечения , потому что этот процесс снижает вероятность будущего успешного использования атаки. против вашей системы.
Другой риск :Переполнение буфера. Что, если поддельная справочная страница содержит смехотворно длинную строку, которая выходит за пределы буфера строк вашего пейджера и каким-то образом запускает выполнение escape-последовательности? Подобные проблемы все еще обнаруживаются направо и налево; похоже, что не раньше, чем исправлена одна ошибка, обнаруживается другая.
Или это может быть не переполнение буфера, а какая-то другая атака, основанная на неверном вводе. Открытие «справочных страниц», созданных ненадежными пользователями, похоже на открытие всех вложений, пришедших с подозрительными электронными письмами :. В этом случае злоумышленник может использовать любую известную уязвимость программы, читающей файл (., ваш пейджер. )Может ли он безопасно обрабатывать любой мыслимый ввод? Нет никакого способа узнать наверняка.