[하루한줄] CVE-2021-4034: SUID 루트 프로그램 polkit의 권한 상승 취약점

URL

PwnKit: Local Privilege Escalation Vulnerability Discovered in polkit’s pkexec (CVE-2021-4034)

Target

  • polkit

Explain

지난 2021년 6월 공개된 polkit 의 로컬 권한 상승 취약점(CVE-2021-3560)에 이어 새로운 로컬 권한 상승 취약점 CVE-2021-40729의 세부 정보가 공개되었습니다.

polkit의 pkexec main() 함수는 command-line argument를 처리하는데, 절대 경로가 아닌 경우 PATH 환경변수 디렉터리에서 실행할 프로그램을 검색합니다.

main (int argc, char *argv[])
{
...
	for (n = 1; n < (guint) argc; n++){...}   // (1) command-line argument 처리
...
	path = g_strdup (argv[n]);   // (2)
...
	if (path[0] != '/')   // (3) 절대경로가 아닌 경우 PATH 환경변수 디렉터리에서 검색
	{
		s = g_find_program_in_path (path);
...
		argv[n] = path = s; // (4)
	}
...

프로그램이 실행될 때 커널은 argv(argument), envp(환경변수)를 스택에 연속적으로 배치하기 때문에 argc가 0이면 argv[0]이 NULL이 되고, 이는 argument list의 terminator가 되어 바로 뒤에 envp가 스택에 배치됩니다.

// argc가 0인 경우 스택
| argv[0] | envp[0] | envp[1] | ....
 
=> envp[0]은 argv[1] 포인터로 접근 가능

따라서 위 코드에서 n이 1부터 시작하므로 (2)와 (4)에서 argv[n], 즉 argv[1]이 범위를 벗어나 envp[0]을 참조하게 됩니다.

위 OOB Read 취약점은 아래와 같이 악용할 수 있습니다.

  1. (2)에서 실행될 프로그램의 경로는 argv[1], 실제로는 envp[0]을 참조합니다.
  2. (3)에서 envp[0]의 값은 절대경로를 의미하는 / 로 시작하지 않기 때문에 g_find_program_in_path() 함수로 전달됩니다.
  3. g_find_program_in_path() 함수는 PATH 환경 변수 디렉토리에서 envp[0]에 해당하는 실행 파일을 검색합니다.
  4. (4)에서 반환된 실행 파일의 전체 경로를 argv[1], 즉 첫 번째 환경변수 envp[0]에 덮어쓸 수 있습니다.

해커는 이를 악용해 환경 변수를 조작할 수 있고 root로 권한 상승을 트리거할 수 있습니다.