2026년 4월, Deutsche Telekom Security 연구팀이 PackageKit에서 12년 넘게 존재해온 로컬 권한상승(local privilege escalation) 취약점을 공개했다. “Pack2TheRoot”라는 이름이 붙은 이 취약점(CVE-2026-41651, CVSS 8.8)은 일반 사용자 권한만 있으면 우분투, 데비안, 페도라, Rocky Linux 등 PackageKit이 기본 설치된 대부분의 배포판에서 root 권한을 얻을 수 있게 한다. 원격 공격 표면은 없지만, 다중 사용자 서버나 공유 워크스테이션, 혹은 컨테이너 이탈 이후의 권한 상승 체인에서는 그대로 치명적인 취약점이다. 이 글에서는 취약점의 기술적 메커니즘과, 실제로 내 시스템이 영향을 받는지 확인·패치하는 방법을 다룬다.
핵심 개념: PackageKit 구조와 TOCTOU 레이스 컨디션
PackageKit은 apt, dnf, zypper 등 배포판마다 다른 패키지 관리자를 하나의 통일된 D-Bus 인터페이스로 감싸는 데몬이다. GNOME Software나 KDE Discover 같은 GUI 패키지 관리 도구가 배포판에 상관없이 동작할 수 있는 것도 이 추상화 계층 덕분이다. PackageKit은 root 권한으로 상주하는 D-Bus 시스템 서비스이며, 실제로 패키지를 설치하거나 삭제하는 민감한 작업은 polkit(PolicyKit)에 인증을 위임한다.
클라이언트가 패키지를 설치하려면 D-Bus로 트랜잭션 객체를 만들고 InstallFiles(flags, [path]) 메서드를 호출한다. 이때 flags에는 SIMULATE(실제 설치 없이 시뮬레이션만)나 ONLY_DOWNLOAD(다운로드만 수행) 같은 값이 들어갈 수 있다. Pack2TheRoot의 핵심은, 트랜잭션 핸들러가 새로운 InstallFiles 호출이 들어올 때마다 트랜잭션의 현재 상태를 확인하지 않고 캐시된 플래그를 무조건 덮어쓴다는 것이다.
공격 흐름은 다음과 같은 순서로 진행된다.
- 안전한 플래그(
SIMULATE등)로InstallFiles를 호출해 polkit 인증을 통과시킨다. - 인증이 완료된 직후, 같은 트랜잭션에 대해 플래그를 제거한 두 번째
InstallFiles호출을 경쟁적으로 발생시킨다. - 플래그 덮어쓰기가 트랜잭션의 상태 전이(state transition) 검증보다 먼저 처리된다.
- 스케줄러가 이 시점의 플래그 값을 읽어 실제 설치 작업을 그대로 수행한다.
이 경쟁이 신뢰성 있게 이기는 이유는 GLib 이벤트 루프의 우선순위 구조에 있다. D-Bus 메시지 디스패치는 유휴(idle) 콜백보다 우선순위가 높게 처리되므로, 두 번째 호출의 플래그 덮어쓰기가 항상 실제 작업 실행 전에 완료된다. 즉 타이밍을 정교하게 맞출 필요 없이 매번 안정적으로 재현되는 레이스 컨디션이라, 익스플로잇 난이도가 낮다. 영향받는 버전은 PackageKit 1.0.2부터 1.3.4까지로, 2014년 초반 릴리즈부터 2026년 패치 전까지 약 12년치 버전이 전부 해당된다.
실전코드: 취약 여부 확인과 패치
가장 먼저 할 일은 설치된 PackageKit 버전을 확인하는 것이다. Ubuntu/Debian 계열에서는 다음 명령으로 확인한다.
$ dpkg -l packagekit packagekit-tools 2>/dev/null | tail -3
실제 Ubuntu 24.04(Noble) 환경에서 위 명령을 실행하면 다음과 같이 나온다.
ii packagekit 1.2.8-2ubuntu1.5 amd64 Provides a package management service
ii packagekit-tools 1.2.8-2ubuntu1.5 amd64 Provides PackageKit command-line tools
pkcon 도구로도 버전을 바로 확인할 수 있다.
$ pkcon --version
1.2.8
주의할 점은, 배포판 패키지 버전 번호(1.2.8-2ubuntu1.5)와 업스트림 PackageKit 버전(1.2.8)이 다르게 표시된다는 것이다. Pack2TheRoot는 업스트림 CVE라 배포판이 자체적으로 백포트 패치를 붙였을 수 있으므로, 단순히 버전 번호가 1.3.5 미만이라고 해서 취약하다고 단정할 수 없다. 가장 확실한 확인 방법은 배포판의 보안 공지를 직접 찾아보는 것이다.
# Ubuntu: CVE-2026-41651로 보안 공지 검색
$ apt-cache policy packagekit
# 후보 버전에 -security 저장소가 포함돼 있으면 보안 패치가 반영된 상태
$ apt list --all-versions packagekit 2>/dev/null
패치가 필요하다면 일반적인 업데이트 절차로 해결된다.
$ sudo apt update
$ sudo apt install --only-upgrade packagekit packagekit-tools libpackagekit-glib2-18
Fedora/RockyLinux 계열은 dnf로 동일하게 확인·업데이트한다.
$ rpm -q PackageKit
$ sudo dnf update PackageKit
패치를 바로 적용할 수 없는 상황이라면, PackageKit 서비스 자체를 비활성화하는 것도 유효한 임시 대응이다. 서버 환경에서는 GUI 패키지 관리자를 쓸 일이 없으므로 대부분 안전하게 끌 수 있다.
$ systemctl status packagekit
$ sudo systemctl disable --now packagekit
서비스가 실제로 사용 중인지, 비활성화 후 문제가 없는지는 D-Bus activation 로그로 확인할 수 있다.
$ journalctl -u packagekit --since "1 hour ago"
주의사항
- PoC는 공개되지 않았다. Deutsche Telekom Security는 책임 있는 공개(responsible disclosure) 차원에서 익스플로잇 코드를 공개하지 않았다. 다만 여러 보안 매체가 “수 초 내 신뢰성 있게 재현 가능”하다고 보고했으므로, PoC 부재가 안전하다는 뜻은 아니다.
- 배포판 버전 번호만으로 안전을 판단하지 말 것. 위에서 본 것처럼 배포판 패키지 버전과 업스트림 버전 표기가 다르고, 백포트 패치가 버전 번호에 반영되지 않는 경우도 있다. 배포판별 보안 공지(USN, DSA 등)를 직접 확인하는 편이 안전하다.
- EOL(수명 종료) 배포판은 백포트가 없을 수 있다. 오래된 LTS나 지원이 끝난 배포판을 아직 쓰고 있다면 패치가 제공되지 않으므로, 서비스 비활성화나 배포판 업그레이드를 고려해야 한다.
- 미니멀/컨테이너 환경은 상대적으로 영향이 적다.
PackageKit은 주로 데스크톱 배포판이나 GUI 소프트웨어 관리 도구를 쓰는 환경에 기본 설치되며, 미니멀 서버 이미지나 대부분의 컨테이너 베이스 이미지에는 애초에 포함되지 않는다. 위dpkg -l명령이 아무것도 출력하지 않으면 해당 시스템은 이 취약점과 무관하다. - 로컬 취약점이라고 위험도를 과소평가하지 말 것. 다중 사용자 서버, 공유 개발 서버, 혹은 다른 취약점으로 이미 낮은 권한을 획득한 공격자가 있는 환경에서는 이런 로컬 권한상승 취약점이 공격 체인의 마지막 단계로 활용된다.
마무리
Pack2TheRoot가 12년 동안 발견되지 않은 이유는 역설적으로 그 안정성에 있다. 타이밍을 맞추기 까다로운 일반적인 레이스 컨디션과 달리, GLib 이벤트 루프의 우선순위 구조 덕분에 매번 같은 순서로 재현되는 “결정론적인” 레이스였고, 그만큼 코드 리뷰나 퍼징으로 우연히 발견되기 어려웠다. 이 사례는 D-Bus 기반 시스템 서비스에서 트랜잭션 상태를 다룰 때 “인증된 시점의 상태”와 “실행 시점의 상태”가 같다고 가정하면 안 된다는 교훈을 남긴다. 당장 익스플로잇이 공개되지 않았다고 안심할 수는 없으니, PackageKit이 설치된 시스템이라면 위의 확인 명령으로 패치 여부를 점검하고, 서버처럼 GUI 패키지 관리자가 필요 없는 환경이라면 서비스 자체를 꺼두는 것이 가장 확실한 대응이다.