/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.

Другие вопросы по тегам