C/C++ setuid(2), setgid(2)
함수 기능
사용자 ID와 그룹 ID 를 변경하는 함수입니다.
setuid() 함수를 실행한 프로세스가 루트 권한을 갖고 있다면 Read User ID, Effective User ID, Saved User ID 모두를 uid 로 바꿉니다.
루트 권한은 갖고 있지 않으나 uid가 Real User ID 혹은 Saved User ID와 같다면 Effective User ID 만을 uid 로 바꿉니다.
setgid() 함수는 그룹 아이디를 제어한다는 점만 다르고 setuid() 와 동일하게 동작합니다.
함수 원형
#include <unistd.h>
#include <sys/types.h>
int setuid(uid_t uid);
int setgid(gid_t gid);
매개변수
uid
새로운 uid
gid
새로운 gid
반환값
성공 시 0 리턴
에러 시 -1 리턴하고 errno 설정
예제
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
int main(int argc, char *argv[]) {
char line[256];
FILE *fp;
int uid;
printf("Initially uid = %d and euid = %d\n", getuid(), geteuid());
// 파일을 한 번 열기
// argv[1]은 dongkyoo 계정의 파일이므로 dongkyoo 는 당연히 열리고
// unix-dongkyoo 계정에서는 열리지 않음
fp = fopen(argv[1], "r");
if (fp == NULL) {
fprintf(stderr, "first open error for %s\n", argv[1]);
exit(1);
}
printf("first open successful:\n");
// 파일 내용 읽고 출력
while (fgets(line, 255, fp) != NULL)
fputs(line, stdout);
fclose(fp);
// 일반 사용자로 실행할 것이므로 Effective user id 를 uid 로 변경
// dongkyoo 계정으로 Effective User id 를 변경
setuid(uid = getuid());
printf("after setuid(%d):\n uid = %d and euid = %d\n", uid, getuid(), geteuid());
fp = fopen(argv[1], "r");
if (fp == NULL) {
fprintf(stderr, "second open error for %s\n", argv[1]);
exit(1);
}
printf("second open successful:\n");
while (fgets(line, 255, fp) != NULL)
fputs(line, stdout);
fclose(fp);
exit(0);
}
결과
dongkyoo 계정에서 최초로 실행함
ssu_setuid_test 파일은 dongkyoo 계정의 소유이므로 정상적으로 동작하는 모습
unix-dongkyoo 계정에서 그 다음 실행함
ssu_setuid_test 파일은 dongkyoo 계정의 소유이므로 unix-dongkyoo 는 파일을 열지 못함
dongkyoo 계정에서 SUID 비트를 설정하고, 한 번 더 실행
unix-dongkyoo 계정에서 한 번 더 실행
SUID 비트가 설정되어 있었기 때문에 unix-dongkyoo 가 a.out 을 실행시켰지만 Effective User ID 는 501 (dongkyoo) 로 뜹니다.
덕분에 첫 번째 fopen 때에는 파일을 열 수 있었지만
이후 setuid() 함수를 통해 Effective User ID 를 다시 본인의 것으로 되돌렸기 때문에 두 번째 fopen 때에는 파일을 열 수 없습니다.
리눅스시스템프로그래밍 저자 : 홍지만
https://book.naver.com/bookdb/book_detail.nhn?bid=14623672
책에 기술된 예제 프로그램입니다. 책 내부에는 훨씬 더 많은 자료가 있습니다. (개인적으로 좋았습니다.)