Вероятно, из-за отсутствия вызова setuid(2)
. Вот до и после такого звонка:
#include <err.h>
#include <stdio.h>
#include <unistd.h>
#define GETUIDS(p) (p[0]=getuid(),p[1]=geteuid())
int main(void)
{
uid_t ids[2];
GETUIDS(ids);
fprintf(stderr, "real %lu effective %lu\n", (unsigned long) ids[0],
(unsigned long) ids[1]);
if (setuid(0) == -1)
err(1, "setuid failed");
GETUIDS(ids);
fprintf(stderr, "real %lu effective %lu\n", (unsigned long) ids[0],
(unsigned long) ids[1]);
return 0;
}
Кроме того, ваша оболочка не совсем безопасна; будем надеяться, что он не сбежит на многопользовательские -системы. Вероятно, было бы намного безопаснее избегать ненужного вызова оболочки (, если вам не нравятся уязвимости типа shellshock или странная обработка повторяющихся переменных среды, скажем, bash
... )и вместо этого использовать вызов exec(3)
чтобы заменить ваш процесс на shutdown
напрямую:
#include <err.h>
#include <unistd.h>
int main()
{
if (setuid(0) == -1)
err(1, "setuid failed");
//execl("/usr/bin/echo", "echo", "--no-wall", "--halt", "now",
execl("/usr/sbin/shutdown", "shutdown", "--no-wall", "--halt", "now",
(char *) 0);
err(1, "exec failed");
return 1;
}
Несколько случайных отключений позже...
centos7# make badcode
cc badcode.c -o badcode
centos7# mv badcode /badcode
centos7# chmod u+s /badcode
centos7# su - jhqdoe
Last login: Thu Jan 10 01:39:03 UTC 2019 on pts/0
[jhqdoe@centos7 ~]$ /badcode
Connection to 192.168.99.2 closed by remote host.
Connection to 192.168.99.2 closed.
Установка бита разрешения позволяет вашему приложению использовать только вызов setuid
и сама по себе не изменяет ваши разрешения. Для этого вам нужно установить uid с помощью setuid(uid_t uid)
. Подробности смотрите на справочной странице:https://linux.die.net/man/2/setuid
Вы можете использовать geteuid()
для получения текущего эффективного uid (, то есть владельца файла с разрешением setuid ). См. справочную страницу:https://linux.die.net/man/2/geteuid
Пример:
// downnow.c
#include <stdlib.h>
#include <unistd.h>
int main() {
setuid(geteuid());
system("shutdown --no-wall --halt now");
return 0;
}