IT/시스템 보안

[SetUID] 임시적 권한 상승과 이로 인한 취약점

kykyky 2024. 3. 27. 08:45

 

 


Mode

 

먼저 파일이나 디렉토리에 대한 권한을 이해해보자.

 

 

출처: 고려대학교 CSL

 

User:

파일의 소유자

 

Group:

한 Group에 속한 다수의 User는 동일한 permission을 가질 수 있다. 특정 파일에 대한 동일한 접근 권한을 여러 User에게 줘야 하는 경우 Group을 활용하면 효율적이다. 

 

Other:

User나 Group에 속하지 않는 모든 User

 


SetUID의 개념

 

필요성

 

예를 들어 /usr/bin/passwd (계정의 비밀번호를 변경하는 명령어 실행파일)의 경우, /etc/shadow 파일에 접근하여 비밀번호를 변경한다.  

이 passwd 실행파일을 소유자인 root 이외의 사용자가 실행할 경우, 이 사용자는 /etc/shadow(root만 접근 가능함)에 대한 접근 권한이 없기 때문에 오류가 발생하여, 비밀번호를 변경할 수 없게 된다...

이때 만일! passwd 실행파일을 실행하는 사용자라면 모두 실행 동안에는 소유자인 root의 권한을 얻게 된다면, 위같은 문제가 해결될 것이다.

 

SetUID의 역할

 

SetUID가 설정된 프로그램의 경우, 실행 동안에는 프로그램 소유자의 권한을 가진 채로 실행하게 되어 임시적 권한 상승이 일어난다. 

 

RUID(Real UID) = 프로세스의 실제 소유자
EUID(Effective UID) = 프로세스의 권한

일반 프로그램:
RUID = EUID = 프로그램을 실행하는 사용자의 ID

SetUID 프로그램:
RUID = 프로그램을 실행하는 사용자의 ID != EUID = 프로그램 소유자의 ID

 


프로그램을 SetUID 프로그램으로 전환하는 법

 

i) root 혹은 파일의 소유자로 로그인한다. 

SetUID 설정은 root 혹은 파일의 소유자만 가능하기 때문이다.

 

ii) chmod u+s <프로그램 파일명> 실행

 

 


SetUID의 Attack Surface

 

출처: 고려대학교 CSL

 

 


Attacks via User Inputs: Invoking Programs

 

출처: 고려대학교 CSL

 

위 코드의 프로그램 이름을 myprog라 하면,

셸에 myprog <파일명>을 입력함으로써 myprog를 실행할 수 있다.  

(<파일명>은 argv[1]으로 들어간다.)

 

그럼 command라는 변수는 "/bin/cat <파일명>"이 될 것이고,

 

이것이 system 함수에 그대로 들어가서, 

최종적으로는 /bin/cat <파일명>이 실행됨으로써

<파일명>이라는 이름의 파일이 화면에 출력된다.

 

그렇다면 이때!

셸에 예를 들어 myprog "aa;/bin/sh"을 입력한다면??!!

최종적으로 /bin/cat aa;/bin/sh가 실행된다:

/bin/cat aa --> aa라는 이름의 파일을 화면에 출력 (근데 이런 파일은 없어서, 이런거 없는데요? 라고 뜬다.)

그 다음 /bin/sh --> 셸이 실행되고 만다.

출처: 고려대학교 CSL

 

위에 대한 Mitigations

 

system 함수 대신 execve 함수를 사용하면 위 취약점이 해결된다.

출처: 고려대학교 CSL

 

system 함수는 argument 하나로서 입력을 받아들이므로 (int system(const char *string);), 위와 같이 Principle of Isolation (: code와 data를 섞어놓지 말라.)을 어기는 사태가 발생한다.  

그러나 execve 함수는 code와 data가 확실히 분리되므로 (int execve(const char *pathname, char *const _Nullable argv[], char *const _Nullable envp[]);), 사용자의 임의의 입력 중 일부가 코드 실행으로 이어질 일이 없다.

 

출처: 고려대학교 CSL

위처럼 공격이 실패한다.

execve 함수는 사용자의 입력 전체를 덩어리째 data로 취급하기 때문이다.

 


Attacks via Environment Variables

 

환경 변수를 조작하여 공격할 수 있다.

 

 

예시로, PATH 환경 변수를 조작하여 shell을 실행하는 과정을 알아보자.

 

vul은 정상적인 경우엔 system함수를 통해 shell에 cal을 입력하여 cal 프로그램 (그냥 달력 띄워줌)을 실행한다.

출처: 고려대학교 CSL

 

 

PATH 환경 변수는 셸 프로세스가 프로그램을 실행할 때 그 프로그램을 찾을 위치를 말하는데 (만약 프로그램 디렉토리가 full path가 아닐 때 말이다),

이 환경 변수를 특정 디렉토리로 조작한 뒤,

그 특정 디렉토리에 똑같이 "cal'이라는 이름의 프로그램을 만든다면

vul이 실행될 때 나의 "cal"이 실행될 것이다!

출처: 고려대학교 CSL

 

 

이때 만약 나의 "cal"이 셸을 실행할 수 있는 놈이라면?!

나는 최종적으로 셸을 얻을 수 있다!

출처: 고려대학교 CSL

 

 

심지어, 만약 vul이 SetUID가 설정되어 있다면?!

내가 얻을 셸은 무려 root shell일 것이다!!

출처: 고려대학교 CSL
출처: 고려대학교 CSL

 

 

위에 대한 Mitigations

 

위와 같이, SetUID을 통해 권한이 상승된 외부 프로그램을 실행하는 경우애는 execve 함수로 대체하는 편이 좋다.  

system 함수와 달리 execve 함수는 셸을 실행하지 않기 때문에, 환경 변수에 영향받지 않으므로, 비교적 안전하기 때문이다.