
PackageKit में TOCTOU race condition के माध्यम से स्थानीय विशेषाधिकार वृद्धि।
CVSS 3.x : 7.8 HIGH
CWE : CWE-367 (Time-of-Check Time-of-Use)
Fix : PackageKit 1.3.5+
Affects : PackageKit 1.0.2 – 1.3.4
PackageKit के D-Bus ट्रांज़ैक्शन हैंडलर में TOCTOU रेस कंडीशन के ज़रिए लोकल प्रिविलेज एस्केलेशन।
कोई भी अनप्रिविलेज्ड लोकल यूज़र रूट के रूप में मनमाने पैकेज इंस्टॉल कर सकता है — एक लोकल सेशन होने के अलावा कोई ऑथेंटिकेशन आवश्यक नहीं।
केवल लैब / अधिकृत परीक्षण (HTB, CTF, लिखित स्कोप वाला एंगेजमेंट)।
python3 exploit.py
बस इतना ही। /tmp/.suid_bash ड्रॉप करता है, फिर रूट शेल में exec करता है।
कस्टम SUID पाथ या टाइमआउट:
SUID_BIN=/dev/shm/.sh TIMEOUT=90 python3 exploit.py
apt install python3-gi dpkg-dev
एक्सप्लॉइट रनटाइम पर दो .deb पैकेज बनाता है — किसी कंपाइलर की आवश्यकता नहीं।
src/pk-transaction.c में तीन बग एक श्रृंखला में जुड़ते हैं:
InstallFiles() cached_transaction_flags और cached_full_paths को बिना किसी स्टेट चेक के ओवरराइट करता है। उसी ट्रांज़ैक्शन पर दूसरा D-Bus कॉल उन्हें आँख बंद करके बदल देता है — तब भी जब ट्रांज़ैक्शन पहले से चल रहा हो।
pk_transaction_set_state() अवैध पश्चगामी ट्रांज़िशन (RUNNING→READY, आदि) को बिना बग 1 के ओवरराइट किए गए फ्लैग को वापस रोल बैक किए अस्वीकार करता है। दूषित फ्लैग बने रहते हैं।
pk_transaction_run() cached_transaction_flags को डिस्पैच समय (GLib idle) पर पढ़ता है, ऑथराइज़ेशन समय पर नहीं। बैकएंड हमलावर के फ्लैग देखता है।
PK_TRANSACTION_FLAG_SIMULATE (0x4) सेट करने से polkit ऑथराइज़ेशन चेक पूरी तरह स्किप हो जाता है। कॉल 1 बिना किसी यूज़र इंटरैक्शन के ऑथराइज़ हो जाता है।
Attacker packagekitd
│ │
│ CreateTransaction() │ state = NEW
│─────────────────────────────────►│
│ │
│ InstallFiles(SIMULATE, dummy) │ polkit skipped (SIMULATE)
│─────────────────────────────────►│ state = READY, idle queued
│ │
│ InstallFiles(NONE, payload) │ flags+paths overwritten
│─────────────────────────────────►│ set_state(WAITING_FOR_AUTH) rejected
│ │ state stays READY (BUG 2)
│ │
│ [idle fires]│
│ │ pk_transaction_run() reads NONE (BUG 3)
│ │ → dpkg installs payload as root
│ │ → postinst: chmod +s /tmp/.suid_bash
│ │
│ execv("/tmp/.suid_bash -p") │
│─────────────────────────────────►│ euid=0(root)
दोनों कॉल GLib idle फायर होने से पहले पहुँच जाते हैं — जीतने के लिए कोई रेस नहीं है, यह डिटर्मिनिस्टिक है।
Ubuntu Desktop 18.04–26.04, Debian Trixie, Fedora 43, RockyLinux 10.1, और कोई भी डिस्ट्रो जो डेमॉन सक्रिय होने पर PackageKit 1.0.2–1.3.4 शिप करती है।
systemctl mask packagekittransaction->state != PK_TRANSACTION_STATE_NEW → अस्वीकार करें