/etc/shadow и suid дилемма
Я наткнулся на проблему с доступом к системным файлам с suid
исполняемые файлы.
Я написал этот короткий POC:
#include <unistd.h>
#include <stdio.h>
int main()
{
if (access("/etc/shadow", W_OK) == 0)
printf("shadow writable!\n");
else
printf("shadow not writable\n");
return 0;
}
Затем я собрал и дал ему suid с chown root:root
а также chmod u+s
(выполняется по корню)
это результирующий исполняемый файл
-rwsrwxr-x 1 root root 4847 Apr 14 08:40 a.out
целевой файл имеет эти права
-rw------- 1 root root 1836 Oct 8 2014 /etc/shadow
Когда я запустил программу, она выдала такой вывод:
[d.berra@srvr ~]$ ./a.out
shadow not writable
Почему это происходит? Я имею в виду... Я обращаюсь к файлу как root
а также root
МОЖЕТ написать на этот файл!
Замечания: selinux
выключен
идеи?
3 ответа
От access
:
Проверка выполняется с использованием реальных UID и GID вызывающего процесса, а не действующих идентификаторов, как это делается при фактической попытке операции (например, open(2)) над файлом. Это позволяет программам set-user-ID легко определять полномочия вызывающего пользователя.
Таким образом, вы можете успешно открыть этот файл для записи, потому что ваш эффективный UID и UID файловой системы теперь равны 0, но доступ по-прежнему будет возвращать ошибку.
Как заметил @nos, вы забыли сменить владельца исполняемого файла на root
:
$ sudo chown root:root ./a.out
Но даже если вы сделаете это, вы все равно получите "не для записи" из-за access
поведение:
$ ls -l ./a.out
-rwsr-xr-x 1 root root 12651 Apr 14 09:53 ./a.out
$ ./a.out
shadow not writable
Вы устанавливаете бит suid, что означает, что исполняемый файл будет работать как пользователь, владеющий исполняемым файлом. Исполняемый файл будет работать как d.berra
, который не может написать /etc/shadow
,
Если вы хотите, чтобы исполняемый файл запускался от имени пользователя root независимо от пользователя, который его запускает, исполняемый файл должен принадлежать пользователю root в дополнение к установке бита suid.
Попробуй это:
#include <unistd.h>
#include <stdio.h>
int main()
{
setuid(0);
if (access("/etc/shadow", W_OK) == 0)
printf("shadow writable!\n");
else
printf("shadow not writable\n");
return 0;
}
Он устанавливает идентификатор пользователя в root для возможности доступа к файлу. setuid(0) работает только в том случае, если эффективный идентификатор пользователя также равен 0.