suid 실행 파일은 권한을 상승시키지 않지만 "sudo"는 권한을 상승시킵니다.

suid 실행 파일은 권한을 상승시키지 않지만 "sudo"는 권한을 상승시킵니다.

나는 암호나 확인을 요구하지 않고 랩톱을 빠르게 종료할 수 있는 프로그램을 작성하려고 합니다. 노트북은 Linux, 특히 Manjaro를 실행합니다.

이를 위해 고정 인수로 실행되고 셸도 생성 하는 setuid실행 파일을 만들려고 합니다 . 나는 프로그램을 짧게 유지하기 위해 이것을 사용하고 있습니다 . 보안 관점에서 보면 나쁜 생각입니다.downnowshutdownsystem

// downnow.c
#include <stdlib.h>

int main() {
  system("shutdown --no-wall --halt now");
  return 0;
}

그런 다음 를 컴파일하고 downnow로 이동한 다음 /bin소유자를 변경하고 setuid 및 setgid 권한을 부여했습니다.

$ sudo chown root /bin/downnow 

$ sudo chgrp root /bin/downnow 

$ sudo chmod u+s /bin/downnow 

$ sudo chmod g+s /bin/downnow 

그러나 권한이 없는 사용자로 실행하려고 하면 downnowsystemd와 통신하지 못합니다.

$ downnow 
Failed to halt system via logind: Interactive authentication required.
Failed to talk to init daemon.

ing 전후에 동일한 메시지가 나타납니다 ch{own,grp,mod}.

stat/bin/downnow보고서에는 와 동일한 권한이 있습니다 /usr/bin/sudo.

$ stat /bin/downnow 
  File: /bin/downnow
  Size: XXXX        Blocks: XX         IO Block: XXXX   regular file
Device: XXXXX/XXXXX Inode: XXXXXX     Links: 1
Access: (6755/-rwsr-sr-x)  Uid: (    0/    root)   Gid: (    0/    root)

$ stat /usr/bin/sudo
  File: /usr/bin/sudo
  Size: XXXXXX      Blocks: XXX        IO Block: XXXX   regular file
Device: XXXXX/XXXXX Inode: XXXXXXX     Links: 1
Access: (4755/-rwsr-xr-x)  Uid: (    0/    root)   Gid: (    0/    root)

완벽하게 작동하는데 왜 downnow권한을 높이지 못할 수 있습니까?sudo

답변1

권한 비트를 설정하면 애플리케이션에서 해당 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;
}

답변2

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.

관련 정보