CVE-2026-41651 — PackageKit TOCTOU 로컬 권한 상승
분류: 퍼플 팀 평가 산출물
승인된 용도로만 사용하십시오. 이 문서와 첨부된 테스트 스크립트는 서면 승인을 받은 시스템에서의 내부 보안 검증 목적으로만 사용됩니다.
악용 증명

목차
- 취약점 개요
- 기술 분석
- 테스트 스크립트 설명
- 침해 지표
- 탐지 로직
- 영향을 받는 시스템 및 버전
- 수정 조치
- 참고 자료
취약점 개요
PackageKit은 시스템 패키지 관리를 위한 D-Bus 추상화 계층으로, Debian, Ubuntu, Fedora, RHEL, SUSE, Arch Linux의 GNOME 기반 데스크톱에 기본으로 포함되어 있습니다. 권한 없는 사용자를 대신하여 권한이 필요한 패키지 작업을 중재하기 때문에, 인증 흐름의 결함은 시스템 전체에 root 수준의 영향을 미칩니다.
기술 분석
근본 원인
pk-transaction.c(1.3.5 이전)는 액션 메서드 재호출에 대한 상태 가드를 적용하지 않았습니다. D-Bus 클라이언트는 트랜잭션이 이미 PK_TRANSACTION_STATE_NEW 상태를 벗어난 후에도 동일한 트랜잭션 객체에 대해 InstallFiles(또는 다른 액션 메서드)를 여러 번 호출할 수 있었습니다.
공격 체인
공격자 (권한 없음)
│
├─① CreateTransaction() → PackageKit이 트랜잭션 객체 경로(tid) 반환
│
├─② InstallFiles(tid, FLAG_SIMULATE=4, [dummy.pkg])
│ PackageKit이 dummy.pkg에 대한 polkit 인증 확인을 대기열에 추가.
│ 아직 설치가 발생하지 않음 — SIMULATE는 건식 실행만 의미.
│
├─③ InstallFiles(tid, FLAG_NONE=0, [payload.pkg]) ← TOCTOU 창
│ 인증이 해결되기 전에 동일한 tid에 대해 재호출.
│ 취약한 버전은 대기열에 있던 매개변수를 payload.pkg로 덮어씀.
│
└─④ polkit이 인증 부여 (사용자 승인 또는 자동 인증)
packagekitd가 payload.pkg를 root로 설치.
payload postinst/post 스크립트: install -m 4755 /bin/bash /tmp/.suid_bash
공격자가 /tmp/.suid_bash -p 실행 → root 셸.
경쟁 조건이 성공하는 이유
②와 ③ 단계는 동일한 연결에서 비차단 비동기 D-Bus 호출로 전송되며 단일 쓰기로 플러시됩니다. 두 메시지는 packagekitd가 ②를 처리하고 상태 머신을 진행시키기 전에 도착하므로 TOCTOU 창이 열린 상태로 남습니다. 1.3.5의 수정은 PK_TRANSACTION_STATE_NEW 이후의 모든 재호출에 대해 PK_TRANSACTION_ERROR_INVALID_STATE를 반환하는 명시적 상태 검사를 추가합니다.
테스트 스크립트 설명
파일: cve-2026-41651-purpleteam.py
언어: Python 3
의존성: python3-gi (GObject introspection / GLib/Gio 바인딩)
목적
준비된 테스트 시스템에서 CVE-2026-41651의 악용 가능성을 입증하며, 다음 목적을 위해 사용됩니다:
- 설치된 PackageKit 버전이 취약한지 검증
- SIEM/EDR 튜닝을 위한 현실적인 IOC 텔레메트리 생성
- 패치 적용 전후의 탐지 범위 테스트
동작
강화된 환경 지원
기본적으로 강화된 시스템은 두 가지 독립적인 지점에서 악용을 차단할 수 있습니다. 스크립트는 두 경우 모두 자동으로 처리합니다.
1. 제한적인 umask (027 / 077)
프로세스에서 상속된 umask 027 또는 077은 mkdir()이 750 또는 700 디렉터리를 생성하게 합니다. dpkg-deb와 rpmbuild 모두 전체 빌드 트리를 탐색해야 하며, 디렉터리 중 하나라도 읽을 수 없으면 빌드가 조용히 실패합니다.
적용된 수정: os.umask(0o022)가 파일이나 디렉터리가 생성되기 전에 시작 시 호출됩니다. 또한 빌드 트리의 모든 디렉터리와 파일은 생성 직후 명시적 chmod를 받습니다(디렉터리와 스크립트는 0o755, 데이터 파일은 0o644). 따라서 상속된 umask와 관계없이 올바른 권한이 보장됩니다.
2. /tmp의 nosuid / noexec 마운트 플래그
| 플래그 | 악용에 미치는 영향 |
|---|
nosuid | 커널이 해당 파일 시스템에 저장된 모든 파일에서 SUID 비트를 조용히 제거 — 복사된 bash는 root가 되지 않음 |
noexec | SUID 바이너리를 전혀 실행할 수 없음 |
적용된 수정: 시작 시 _find_suid_dir()가 /proc/mounts를 읽고 두 플래그가 모두 설정되지 않은 파일 시스템을 찾을 때까지 우선순위 순서로 후보 디렉터리를 테스트합니다. 결정된 경로는 페이로드의 사후 설치 스크립트에 포함되고 폴링 및 실행에 사용됩니다.
모든 후보가 차단되면 스크립트는 조용히 실패하는 대신 명확한 오류와 함께 종료됩니다.
호환성
| 배포판 계열 | 패키지 도구 | 테스트됨 |
|---|
| Debian / Ubuntu | dpkg-deb | ✓ |
| RHEL / Fedora | rpmbuild |
침해 지표
IOC는 일반/인프라 수준에서 스크립트 특정 산출물 순으로 나열됩니다. 일반 지표를 기반으로 구축된 탐지는 사용된 PoC 변형과 관계없이 이 CVE를 탐지합니다.
파일 시스템
프로세스 및 실행
D-Bus 활동
감사 로그 패턴
활성화: auditctl -a always,exit -F arch=b64 -S all -F path=/usr/bin/packagekitd
또는 아래 규칙을 /etc/audit/rules.d/에 사용:
# 모든 후보 드롭 디렉터리에서 SUID 파일 생성 탐지
-a always,exit -F arch=b64 -S chmod,fchmod,fchmodat -F a2&04000 -F dir=/tmp -k suid_drop
-a always,exit -F arch=b64 -S chmod,fchmod,fchmodat -F a2&04000 -F dir=/var/tmp -k suid_drop
-a always,exit -F arch=b64 -S chmod,fchmod,fchmodat -F a2&04000 -F dir=/dev/shm -k suid_drop
# 비-root에 의한 dpkg-deb / rpmbuild 탐지
-w /usr/bin/dpkg-deb -p x -k pkg_build_nonroot
-w /usr/bin/rpmbuild -p x -k pkg_build_nonroot
# 모든 후보 드롭 디렉터리에서 SUID bash 실행 탐지
-a always,exit -F arch=b64 -S execve -F dir=/tmp -F uid!=0 -F euid=0 -k priv_esc_drop
-a always,exit -F arch=b64 -S execve -F dir=/var/tmp -F uid!=0 -F euid=0 -k priv_esc_drop
-a always,exit -F arch=b64 -S execve -F dir=/dev/shm -F uid!=0 -F euid=0 -k priv_esc_drop
패키지 관리자 산출물
권한 상승 산출물
탐지 로직
SIEM 의사 규칙 (일반 — 모든 CVE-2026-41651 변형 포함)
(
event.category == "process"
AND process.name IN ("dpkg-deb", "rpmbuild")
AND process.user.id != "0"
AND NOT process.parent.name IN ("apt", "apt-get", "dpkg", "rpm", "dnf", "yum", "zypper", "mock", "koji")
)
OR
(
event.category == "file"
AND file.path LIKE "/tmp/%" OR file.path LIKE "/var/tmp/%" OR file.path LIKE "/dev/shm/%"
AND file.owner == "root"
AND (file.mode LIKE "04%")
)
OR
(
event.category == "process"
AND process.name == "bash"
AND process.real_user.id != "0"
AND process.effective_user.id == "0"
AND NOT process.parent.name IN ("sudo", "su", "sshd", "login", "pam")
)
EDR 동작 체인
packagekitd
└─ sh / bash (cwd 또는 인수가 /tmp, /var/tmp, /dev/shm 또는 $HOME과 일치)
└─ install / cp / chmod (대상에 SUID + 소유자 root)
전체 체인에 플래그를 지정합니다. 개별 단계만으로는 양성일 수 있습니다. packagekitd를 통한 부모-자식 관계에서 SUID 설정 명령까지의 관계는 선택된 드롭 디렉터리와 관계없이 신뢰도가 높습니다. 네 후보 모두를 포함하도록 경로 기반 규칙을 확장하십시오.
영향을 받는 시스템 및 버전
설치된 버전 확인: pkcon backend-details 또는 packagekit --version
보고된 버전이 ≤ 1.3.4이면 취약합니다.
수정 조치
기본: PackageKit을 1.3.5로 업그레이드하거나 공급업체별 백포트를 적용합니다.
# Debian / Ubuntu
apt update && apt install --only-upgrade packagekit
# Fedora / RHEL
dnf upgrade packagekit
# SUSE
zypper update packagekit
완화 조치 (즉시 패치가 불가능한 경우):
참고 자료
생성일: 2026-04-24 | 업데이트일: 2026-04-25 | 퍼플 팀 평가 | 내부 전용