system drop privilege when setuid

정말 고생했던 부분이다.

C
-rwsr-xr-x 1 root      root      17320 Dec 24  2021 dreamsanta_present

다음과 같은 setuid로 되어 있는 프로그램이 있다. 이때 이 dreamsanta_present 프로그램 내에서 system(”/bin/sh”) 이 실행될때 이 셸이 root로 실행될까? 정답은 아니다.

저 바이너리를 실행했을때 uid와 euid가 다르게 실행될 것이다.

/proc/self/status 파일을 보면,

C
Name:	dreamsanta_pres
Umask:	0022
State:	S (sleeping)
Tgid:	41
Ngid:	0
Pid:	41
PPid:	1
TracerPid:	0
Uid:	1000	0	0	0
Gid:	1000	1000	1000	1000
FDSize:	64
Groups:	 
NStgid:	41
NSpid:	41
NSpgid:	1
NSsid:	1

다음과 같은 것을 알 수 있는데, Uid: 1000 0 0 0

다음 필드에서 각각, real / effective / saved-set / fsuid 을 의미한다.

  • real UID = 1000: 이 프로세스를 시작한 실제 사용자(당신).
  • effective UID = 0: 현재 권한 판단은 루트로 이루어짐(특권 있음).
  • saved-set UID = 0: 한 번 루트가 된 이력을 저장. 필요 시 seteuid() 등으로 루트로 재상승 가능.
  • fsuid = 0: 파일 시스템 접근 권한 판단도 루트로 동작.

당연히 알겠지만, setuid 때문에 현재 real uid랑 effective UID 다르다.

이럴때 셸을 실행했을때 , root 셸을 딸 수 있게 된다면 너무 보안적으로 위험하게 된다.

따라서 리눅스는 다음과 같은 보안을 적용시켜났다.

바로 real UID ≠ effective UID 라면 실행되는 shell 프로세스의 uid를 real UID의 권한으로 drop을 하는 것이다.

따라서 셸을 실행해도,

C
id 
uid=1000(ctf) gid=1000(ctf) groups=1000(ctf)

다음과 같이 되게 된다.

이때 진행할 수 있는 추가 취약점은 capability leak 등이 있다.