setuid가 표준 사용자 계정에서 작동하지 않습니다

setuid가 표준 사용자 계정에서 작동하지 않습니다

이 C 프로그램을 보세요:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main()
{
    printf("UID:  %d\n", getuid());
    printf("EUID: %d\n", geteuid());
    system("id");

    printf("res=%d\n", setuid(1001));

    printf("UID:  %d\n", getuid());
    printf("EUID: %d\n", geteuid());
    system("id");
    return 0;
}

내 사용자 계정은 "test"(ID 1000)입니다. 두 번째 사용자 계정인 "test2"(ID 1001)가 있습니다.

내가 한 일은 다음과 같습니다.

gcc test.c -o ./a.out
sudo chown test2 ./a.out
sudo chmod u+s ./a.out

이제 ./a.out을 실행하면 다음과 같은 일이 발생합니다.

UID:  1000
EUID: 1001
uid=1000(test) gid=1000(test) groups=1000(test),...
res=0
UID:  1000
EUID: 1001
uid=1000(test) gid=1000(test) groups=1000(test),...
          

왜 두 번째 부분에 uid=1001이 표시되지 않는지 이해할 수 없습니다...

나는 이것을 시도했습니다 :

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main()
{
    printf("UID:  %d\n", getuid());
    printf("EUID: %d\n", geteuid());
    system("id");

    printf("res=%d\n", setuid(0));  // <- Here is the change

    printf("UID:  %d\n", getuid());
    printf("EUID: %d\n", geteuid());
    system("id");
    return 0;
}
          
gcc test.c -o ./a.out
sudo chown root ./a.out
sudo chmod u+s ./a.out

./a.out을 실행할 때 얻는 결과는 다음과 같습니다.

UID:  1000
EUID: 0
uid=1000(test) gid=1000(test) groups=1000(test),...
res=0
UID:  0
EUID: 0
uid=0(root) gid=1000(test) groups=1000(test),...
           

이제 작동합니다.

그래서 setuid가 test2 사용자와 작동하지 않고 루트 사용자와 작동하는 이유를 이해할 수 없습니다 ...

어떤 아이디어?

감사해요

답변1

여기에는 몇 가지 일이 발생하여 이러한 혼란이 발생합니다. Setuid는 두 경우 모두 작동하지만 생각한 대로 작동하지 않습니다. 첫째, 실제적이고 유효한 사용자 ID의 문제가 있습니다. 에 따르면setuid(2) 매뉴얼 페이지

호출 프로세스에 권한이 있는 경우(보다 정확하게는 프로세스의 CAP_SETUID사용자 네임스페이스에 기능이 있는 경우) 실제 UID 및 저장된 set-user-ID도 설정됩니다.

이는 또한 호출 프로세스가 수행하는 작업을 의미합니다.~ 아니다CAP_SETUID(일반 사용자의 경우) 기능이 있으면 UID는~ 아니다변경하면 EUID만 변경됩니다.

그래서 우리는 통화로 넘어갑니다 system(). 호출은 system("anything")다음을 호출하는 것과 동일합니다.

execl("/bin/sh", "sh", "-c", "anything", (char *) NULL);

따라서 /bin/sh새로운 쉘이 명령을 실행할 수 있도록 인수를 제공하여 생성됩니다. bash가 작동하기 때문에 bash를 쉘로 사용한다고 가정합니다.

실제 사용자(그룹) ID와 다른 유효 사용자(그룹) ID로 쉘을 시작하고 -p 옵션을 지정하지 않으면 (...) 유효 사용자 ID가 실제 사용자 ID로 설정됩니다.

따라서 프로세스에 해당 기능이 없으면 CAP_SETUID실제 사용자 ID는 변경되지 않고 유효 UID만 변경됩니다. 그런 다음 bash가 생성되면 UID가 EUID와 같지 않기 때문에 유효한 UID가 삭제됩니다. 전화로 확인하시면 됩니다

system("touch /tmp/blah")

그리고 추가

FILE *file = fopen("/tmp/blah2", "w+");
fclose(file);

귀하의 프로그램에. 의 소유자는 /tmp/blah"test"이지만(EUID는 쉘 실행 시 삭제되므로) /tmp/blah2"test2"에 속하게 됩니다.

관련 정보