Linux/Linux_programing

Linux - real id, effective id 사용자 id

sosal 2010. 1. 27. 07:34
반응형

/*
 http://sosal.tistory.com/
 * made by so_Sal
 */


setuid()
seteuid()
setreuid()

getuid()
geteuid()

getgid()
getegid()

주구장창 real id, effective id에 대해서 설명한 후에
위 함수들을 간단하게 정리하고 끝내려 합니다.
함수들이 어떤것인지 간단하게만 보고자 한다면
이 글의 맨 아래로 내려가 주세요.


사용자 id는 크게 2가지로 나뉜다.
real id, effective id.
정확하게 무엇인진 모르겠지만..
real id는 실제 id를 말하고
effective id는 현재 권한을 뜻한다고 일단 생각하자.

시스템 해킹 문제에 자주 쓰이는 setuid() 라는 함수의 man page를 확인해보자.

#include<unistd.h>
  int   setuid( uid_t uid );

setuid는 현재 프로세스의 effective UID를 설정한다.
 >> man page에 나와있는 설명인데 좀 잘못되었다.
 >> 예제를 보면 effective UID 뿐만아니라 real UID또한 바뀜을 알 수 있다.

유효사용자라고?? 일단 실제 사용자와 유효 사용자란 말이 있다는것을 알아두고,
setuid 함수를 사용해보는 예제를 한번 살펴보자.

/*
 * 프로그램을 만드는 사용자는 root로 한다.
 * Getuid는 real uid를 가져오고,
 * seteuid는 effective uid를 설정하는 역할을 한다.
 * 아래 프로그램에서 uid는 ruid를 뜻한다.
 */

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

int main(void){
        printf("-----Getuid() geteuid()-----\n");

        printf("uid ::  %3d    euid :: %3d\n",getuid(),geteuid());
        setuid(500);

        printf("uid ::  %3d    euid :: %3d\n",getuid(),geteuid());
}



일단 처음의 ruid는 당연히 root 이기 때문에 0이고, euid 역시 0이다.
여기서 uid는 real uid를 말하고, euid는 effective id를 말한다.

setuid() 함수는 현제 프로세스의 유효 사용자 ID 를 설정한다고 했듯,
실제로 ruid, euid가 모두 바뀌었다.

[root@localhost id]# chmod 4777 ./setuid

setuid라는 프로그램에 어떤 계정이든 실행시 루트의 권한을 흉내낼 수 있도록 설정해준 후
다른 아이디로 프로그램을 실행해보자.

7


여기서, chmod 4xxx ./filename 명령어로
파일에 setuid를 건다는것은, real uid를 바꾸는것으로 생각할 수 있다.
 //여기서 setuid를 건다는것은 setuid() 함수를 호출하는것이 아니다.

잠시 다른이야기로 빠졌지만, setuid는 real id, effective id (이하 ruid, euid)를
바꾸는 것이라는걸 예제를 통해서 알아냈는데, real ideffective id의 차이는 뭐냐?
를 설명하려 한다.

real id는 말그대로 실제 본인의 id라고 생각하면 좋겠다. (물론 함수를 통해 바꿀 수 있다.)
처음 접속을 했다면, 자신이 로그인한 id가 ruid가 될것이고,
자신의 권한이 곧 로그인한 id의 권한과 같으니 euid 역시 ruid와 같을것이다.

euid는 현재 계정이 당장 휘두를 수 있는 권한을 뜻한다.


프로그램이 chmod 를 이용하여 setuid가 걸려있다면
그 프로그램을 실행시켰을때 사용자는 프로그램의 uid로 사용자 ruid가 둔갑하게된다!
하지만 ruid가 바꼈다고 해서, 그의 권한으로 모든 일을 할 수 있는것은 아니다.
위의 chmod를 사용하여 파일의 setuid를 거는것은 euid를 바꾸지 못하는것을 보았고,
euid가 현재 계정이 가지고 있는 권한을 뜻한다고 했으므로
권한을 행세하지 못한다는 것이다.

하지만 ruid가 프로그램의 사용자 계정이 있다는 말은
프로그램 내에서 setuid() 함수를 호출하였을때
언제든지 그 계정 권한 내의 effective id 를 획득할 수 있다는 것을 뜻한다.

만일 real id가 root였다면 setuid로 어떤 계정이든 euid, ruid를 획득할 수 있고,
일반 계정이라면, 그 일반 계정이 가지고 있는 euid만 획득할 수 있다.
(일반 계정이 setuid() 함수를 이용하여 루트권한 uid:0을 획득하게 된다면 얼마나 혼란스럽겠는가?)

하여튼 느낌상으로 euid는 실제 행세, 휘두를 수 있는 권한을 뜻하고
guid는 신분 (언제든지 휘두를 수 있는 권한을 얻을 수 있는 신분!! ) 이랄까?
이 글을 읽는 여러분도 대충 감이 왔을거 생각한다.



일반적인 buffer over flow를 이용한 문제가 있다고 치자.
 :: bof에 대해서 정확하게 모르셔도 상관없다. 이 공격으로 내가 할 수 있는 일은
 :: 프로그램의 권한으로 무슨일이든지 다 할 수 있다는 것이다.

첫째로 setuid가 (chmod 4777같은) 걸려있는 파일을 노릴것이다.
만약 이 파일 내부적으로 setuid()함수를 호출하여 공격자가 원하는 euid로 바꿔준다면
사전 준비없이 쉘을 실행시키면 바로 프로그램의 사용자 권한을 획득하게 될 것이다.

하지만, setuid() 함수가 호출되지 않는다면 아무리 쉘을 실행시켜도
euid가 공격자의 uid와 같으므로 쉘을 실행시키더라도 프로그램의 권한의 쉘을 획득하지 못한다.
결국 ruideuid를 얻을 권리는 있지만, euid를 얻기 전까지는 당장에 아무것도 할 수 없음을 뜻한다.
이해 했는가?

그렇다면 setuid() 함수가 호출되지 않는 프로그램을 bof로 공격자가 공격하려면
setuid() 함수를 실행시킨 다음에야 쉘을 실행시켜야겠다.

euid, ruid 완벽하게 이해하셨으면 좋겠다.



아래는 함수에 대한 설명이다.
real uid = ruid
effective uid = euid 라고 간단하게 적었다.

setuid(uid_t uid)      :: 매개변수의 uid로 실행중인 프로세스 권한중 ruid, euid를 모두 바꾼다.
seteuid(uid_t euid)  :: 매개변수의 euid로 실행중인 프로세스의 권한중 euid만 바꾼다.
setreuid(uid_t ruid,uid_t euid) :: ruid, euid 각각 원하는데로 바꿀 수 있다.

   //setreuid(-1, euid)는 seteuid(euid)와 같다.

setegid(gid_t gid)  :: 매개변수의 gid로 실행중인 프로세스 권한중 rgid, egid를 모두 바꾼다.
setgid(gid_t egid)  :: 매개변수의 euid로 실행중인 프로세스의 권한중 euid만 바꾼다.
setregid(gid_t rgid,gid_t egid) :: ruid, euid 각각 원하는데로 바꿀 수 있다.

   //setregid(-1, egid)는 setegid(egid)와 같다.


getuid(void)   :: 현재 ruid를 리턴한다.
geteuid(void)  :: 현재 euid를 리턴한다.

getgid(void)   :: 현재 rgid를 리턴한다.
getegid(void) :: 현재 egid를 리턴한다.