
이 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"에 속하게 됩니다.