InfinitumIT
Analiz Raporu

CVE-2026-41651 — Pack2TheRoot: PackageKit Üzerinden Root'a Giden Yarış Koşulu

Linux'ta varsayılan gelen PackageKit servisinde tespit edilen Pack2TheRoot zafiyeti — üç ayrı bug (koşulsuz bayrak üzerine yazma, sessiz state reddi, geç bayrak okuma) bir araya gelince sıradan kullanıcı root yetkisiyle paket kurabiliyor. Time-of-Check / Time-of-Use yarış koşulunun teknik analizi.

04.06.2026 · 9 dk okuma · InfinitumIT
CVE-2026-41651 — Pack2TheRoot: PackageKit Üzerinden Root'a Giden Yarış Koşulu

PackageKit, Linux masaüstü ortamlarında yaygın olarak kullanılan bir paket yönetim aracıdır. Bu yazıda, polkit ve D-Bus üzerinden işleyen yetkilendirme zincirinde tespit edilen CVE-2026-41651 — Pack2TheRoot zafiyetinin teknik analizini; üç ayrı bug'ın (koşulsuz bayrak üzerine yazma, sessiz state reddi, geç bayrak okuma) birleşerek nasıl root yetkisiyle keyfi paket kurulumuna dönüştüğünü, Time-of-Check / Time-of-Use yarış koşulunu ve önerilen yamayı ele alıyoruz.

PackageKit, Linux masaüstü ortamlarında yaygın olarak kullanılan bir paket yönetim aracıdır. Sistem üzerinde daemon olarak çalışır, D-Bus üzerinden gelen istekleri dinler ve grafik arayüzden yapılan paket yönetimi işlemlerini alttaki paket yöneticisine iletir. Ubuntu ve Debian sistemlerinde APT, Fedora ve RHEL sistemlerinde DNF, Arch Linux'ta ise pacman gibi birbirinden farklı paket yöneticileri kullanılır. PackageKit bu farklı altyapıları ortak bir API altında birleştirerek uygulamaların tek bir standart arayüz üzerinden paket kurma, kaldırma, güncelleme ve sorgulama işlemlerini gerçekleştirmesini sağlar.

Modern masaüstü Linux sistemleri, kullanıcı deneyimini iyileştirirken güvenliği korumak için çok katmanlı bir yetkilendirme mimarisi kullanır. Bu mimarinin merkezinde üç bileşen yer alır: süreçler arası iletişimi sağlayan D-Bus IPC sistemi, paket işlemlerini yöneten PackageKit servis katmanı ve yetkilendirme kararlarını veren polkit mekanizması. Bir kullanıcı grafik arayüzden paket kurmak istediğinde istek önce D-Bus üzerinden PackageKit daemon'una ulaşır, PackageKit bu isteğin yetki gerektirip gerektirmediğini polkit'e sorar ve ancak onay alındıktan sonra işlemi root yetkileriyle gerçekleştirir. Pack2TheRoot zafiyeti, tam olarak bu güven zincirindeki bir boşluktan doğmaktadır.

Paket kurulum katmanları

CVE-2026-41651 figure 1

GUI Application / pkcon Katmanı : Bu katman, Kullanıcının paket kurma, güncelleme veya kaldırma işlemlerini başlattığı bölümdür. GNOME Software, KDE Discover ve pkcon gibi araçlar bu katmanda yer alır. Bu uygulamalar doğrudan root yetkisiyle çalışmaz, yalnızca kullanıcı isteğini üretir ve ilgili sistem servislerine iletir. Böylece kullanıcı arayüzü katmanındaki olası bir güvenlik açığının doğrudan sistem seviyesinde yetki yükseltmeye dönüşmesi engellenmiş olur.

D-Bus Katmanı: D-Bus, Linux kullanıcı alanında çalışan process’ler arasında iletişim sağlayan standart IPC (Inter-Process Communication) mekanizmasıdır. GUI uygulamaları PackageKit ile doğrudan socket veya shared memory üzerinden değil, D-Bus üzerinden haberleşir. Bu yapı RPC benzeri method çağrıları ile çalışır. Örneğin GUI uygulaması: InstallPackages() çağrısını D-Bus üzerinden gönderir.

PackageKit Katmanı: PackageKit, Linux sistemlerinde dağıtımdan bağımsız paket yönetimi sağlayan merkezi bir servis katmanıdır. Linux ekosisteminde Debian tabanlı sistemler apt, Fedora tabanlı sistemler dnf, Arch Linux ise pacman kullanmaktadır. Bu farklılıklar nedeniyle masaüstü uygulamalarının her paket yöneticisi için ayrı geliştirilmesi yerine, ortak bir arayüz sağlayan bir soyutlama katmanına ihtiyaç duyulmuştur. PackageKit bu ihtiyacı karşılamak amacıyla geliştirilmiştir.

Authorization Granted Katmanı: Authorization Granted aşaması, polkit tarafından yapılan değerlendirme sonucunda kullanıcının ilgili işlemi gerçekleştirmesine izin verildiği noktayı ifade eder. Bu aşamada sistem, kullanıcının gerekli yetkilere sahip olduğunu ve başlatılan işlemin güvenilir olduğunu kabul eder. PackageKit, polkit tarafından döndürülen olumlu yetkilendirme kararını aldıktan sonra işlemi gerçekleştirmek üzere bir sonraki aşamaya geçer. Bu aşamadan sonra sistem, authorization sürecinde değerlendirilen işlem ile execution aşamasında gerçekleştirilecek işlemin aynı olduğunu varsayar. Modern Linux sistemlerinde bu nokta authorization boundary olarak adlandırılır. Pack2TheRoot zafiyetinin temelinde de tam olarak bu güven varsayımının ihlal edilmesi yer almaktadır. Yetkilendirilen işlem ile çalıştırılan işlem arasındaki bütünlük bozulduğunda ciddi yetki yükseltme zafiyetleri ortaya çıkarır.

apt / dnf / rpm Backend Katmanı: Bu katman, gerçek paket yöneticilerinin çalıştığı ve sistem üzerinde doğrudan değişiklik yaptığı execution katmanıdır. Kullanılan Linux dağıtımına bağlı olarak bu görev Debian ve Ubuntu sistemlerinde apt, Fedora ve Red Hat tabanlı sistemlerde dnf, Arch Linux sistemlerinde ise pacman tarafından yerine getirilir. Backend paket yöneticileri root yetkisiyle çalışır. Bu nedenle paketlerin indirilmesi, bağımlılıkların çözülmesi, dosyaların sistem dizinlerine yerleştirilmesi ve paket veritabanlarının güncellenmesi gibi işlemler bu aşamada gerçekleştirilir ve paketlerin içerisinde bulunan kurulum sonrası betikler (post-install scripts), trigger mekanizmaları ve bakım betikleri de yine bu aşamada çalıştırılır. Bu scriptler root yetkisiyle execute edildiğinden dolayı backend katmanı doğrudan ayrıcalıklı kod çalıştırma yüzeyi olarak değerlendirilmektedir.

Package Installation Katmanı Paket dosyaları ilgili dizinlere yazılır, uygulamaya ait servisler oluşturulur, yapılandırma dosyaları güncellenir ve gerekli sembolik bağlantılar oluşturulur. Kurulum işlemi tamamlandığında paket yöneticisi kendi veritabanını günceller ve transaction durumu tamamlandı olarak işaretlenir. Bu aşama doğrudan root yetkisiyle gerçekleştirildiği için Linux paket yönetim mimarisindeki en yüksek ayrıcalık seviyesini temsil eder. Sistemde yapılan tüm kalıcı değişiklikler bu aşamada uygulanır ve paket kurulum süreci sonlandırılır.

CVE-2026-41651- Pack2TheRoot Vulnerability

Pack2TheRoot, Linux'ta varsayılan gelen PackageKit servisinde tespit edilen bir zafiyettir. Saldırgan önce "simülasyon" bayrağıyla şifresiz geçiş alır, ardından aynı işlem üzerinde bayrağı "gerçek kurulum"a çevirir, sistem bu değişikliği fark etmez. Sonuç olarak sıradan bir kullanıcı root olarak istediği paketi kurar.

::BUG ANALİZİ

1.Koşulsuz bayrak üzerine yazma

CVE-2026-41651 figure 2

CVE-2026-41651 figure 3

Satır 4036-4037 Bu iki satır zafiyetin köküdür. InstallFiles() her çağrıldığında, transaction'ın mevcut state'ini kontrol etmeden bayrakları ve dosya yollarını koşulsuz olarak üzerine yazar. Transaction NEW, READY, RUNNING fark etmez. İkinci bir D-Bus çağrısıyla saldırgan SIMULATE bayrağını kaldırıp gerçek paket yolunu yerleştirebilir.

Olması gereken Bu fonksiyonun ilk satırında şu kontrol olmalıydı:

CVE-2026-41651 figure 4

2. Sessiz state geçişi reddi

CVE-2026-41651 figure 5

Satır 876–881 State machine geriye dönük geçişleri engeller (READY ->NEW). Ama sorunumuz şu: InstallFiles()'daki bayrak üzerine yazma (Bug 1, satır 4036) bu fonksiyon çağrılmadan önce gerçekleşir. Dolayısıyla state geçişi reddedildiğinde bayraklar zaten bozulmuştur.

Satır 878: g_warning() sadece bir log mesajı yazar, işlemi durdurmaz, exception fırlatmaz, bozulmuş state'i temizlemez.

3. Geç bayrak okuma

CVE-2026-41651 figure 6

Satır 2276–2277 Scheduler, bayrakları ve dosya yollarını dispatch anında okur yetkilendirme anında değil. Bug 1 nedeniyle bu değerler saldırganın ikinci D-Bus çağrısıyla değiştirilmiştir. SIMULATE bayrağı artık yok -> pk_backend_install_files() gerçek bir kurulum başlatır -> root yetkileriyle paket kurulur.

Time-of-Check, Time-of-Use

CHECK zamanı: Polkit, SIMULATE bayrağına bakarak güvenli olduğunu varsayar.

USE zamanı: Scheduler idle callback'te bayrakları okur ama artık NONE (gerçek kurulum)

[Check ile Use arasındaki zaman penceresinde bayraklar değiştirilmiştir. Check'in kararı artık geçersizdir ama Use bunu bilmemektedir].

Polkit Bypass Mekanizması

CVE-2026-41651 figure 7

Satır 2895-2902 SIMULATE (bit 2 = 0x4) veya ONLY_DOWNLOAD bayrakları ayarlıysa, polkit yetkilendirmesi tamamen atlanır. Bu tasarım kararı kendi başına mantıklıdır. simülasyonlar sistemi değiştirmez. Ama Bug 1 ile birleştiğinde tehlikeli olur çünkü saldırgan ilk çağrıda SIMULATE ile polkit'i atlar, ikinci çağrıda bayrakları gerçek kuruluma çevirir.

Bu kod bloğu tek başına bir zafiyet değildir. Ama Bug 1 (koşulsuz üzerine yazma) + Bug 2 (sessiz red) + Bug 3 (geç okuma) ile birleştiğinde, saldırganın hiçbir yetkilendirme olmadan root olarak paket kurmasını mümkün kılar.

Assertion Crash

CVE-2026-41651 figure 8

Satır 508 Exploit başarılı olduktan sonra, iki farklı kod yolu aynı transaction için Finished sinyali göndermeye çalışır: (1) polkitd'nin NOT_AUTHORIZED yanıtı ve (2) backend'in gerçek kurulumu tamamlaması. İkinci çağrıda emitted_finished zaten TRUE olduğu için g_assert() tetiklenir -> SIGABRT -> daemon crash.

Bu crash exploit başarılı olduktan sonra gerçekleşir. Paket zaten kurulmuştur. Crash, saldırıyı engellemez ama journalctl'de kalıcı bir iz bırakmış olur. Güvenlik ekipleri bu assertion failure'ı IOC olarak kullanabilir.

Exploit sonrasında packagekitd sürecinde emitted_finished assertion failure hatası gözlemlenebilir. Bu durum tek başına exploit'in başarılı olduğunun kesin kanıtı olarak değerlendirilmemelidir. Benzer crash'ler farklı yazılım hataları nedeniyle de oluşabilir. Bununla birlikte, şüpheli paket kurulumları, anormal transaction kayıtları veya yetki yükseltme belirtileri gibi ek bulgularla birlikte değerlendirilmelidir.

Transaction struct'ı - cached alanları

CVE-2026-41651 figure 9

GObject parent: GObject, GLib'in nesne sistemi altyapısını sağlayan temel yapıdır. C dilinde built-in inheritance ve diğer nesne yönelimli programlama özellikleri bulunmadığından, GObject bu özellikleri (classes, inheritance, virtual methods, runtime type information (RTTI) vb.) simüle etmek için kullanılır. GObject'ten türetilen yapıların ilk üyesi genellikle GObject parent_instance olur. Bu sayede üst sınıfın verileri alt sınıf yapısının başında yer alır ve kalıtım benzeri bir davranış elde edilir.

PkRoleEnum role: Transaction'ın hangi tür işlemi gerçekleştirdiğini belirtir. Bu alan, işlemin paket INSTALL, REMOVE, UPDATE veya SEARCH gibi hangi kategoriye ait olduğunu tanımlar. Bir enum tipidir ve önceden tanımlanmış sabit değerlerden birini içerir.

Enum (Enumeration), C dilinde belirli, sınırlı sayıda sabit değerleri isimlendirmek ve gruplamak için kullanılan özel bir veri tipidir.

PkStatusEnum status: İşlemin o anki çalışma durumunu tutar. İşlem bekleme aşamasında WAITING, RUNNING veya DOWNLOADING olabilir. Bu alan genellikle kullanıcı arayüzüne ilerleme ve durum bilgisi aktarmak için kullanılır.

PkTransactionState state: Transaction'ın durum makinesi (state machine) içindeki mevcut aşamasını gösterir. Bir transaction genellikle NEW -> WAITING_FOR_AUTH -> READY -> RUNNING -> FINISHED sıralamasını izler. İşlemin hangi aşamada olduğunun belirlenmesi ve geçişlerin doğru yönetilmesi açısından kritik öneme sahiptir. İncelenen Bug #2 doğrudan bu alanın yönetimiyle ilişkilidir.

gboolean emitted_finished: finished sinyalinin daha önce gönderilip gönderilmediğini takip eden bir bayraktır. Aynı transaction için finished sinyalinin yalnızca bir kez gönderilmesini garanti etmek amacıyla kullanılır. Exploit sonrasında g_assert() tarafından kontrol edilen alanlardan biridir. Sinyalin ikinci kez gönderilmeye çalışılması durumunda assertion hatası oluşabilir ve süreç beklenmedik şekilde sonlanabilir.

gboolean allow_cancel: İşlemin kullanıcı tarafından iptal edilip edilemeyeceğini belirtir. Değer TRUE ise kullanıcı işlemi durdurabilir, FALSE ise işlem tamamlanana kadar devam etmek zorundadır.

gboolean waiting_for_auth: Transaction'ın Polkit'ten gelecek authorization yanıtını bekleyip beklemediğini gösterir. Bu değer TRUE olduğunda işlem geçici olarak duraklatılır ve gerekli yetki kontrolünün tamamlanması beklenir. Polkit'ten yanıt geldikten sonra transaction normal durum akışına devam eder. Yetki gerektiren işlemlerin güvenli şekilde yürütülmesinde önemli bir rol oynar.

Saldırganın Hedeflediği Alanlar

PkBitfield cached_transaction_flags: Transaction sırasında kullanılan işlem bayraklarını tutar. Bu bayraklar işlemin nasıl çalışacağını belirler; örneğin SIMULATE, ONLY_DOWNLOAD gibi seçenekler bu alan üzerinden kontrol edilir. PkBitfield bir bit alanı (bit field) yapısıdır ve her bit farklı bir bayrağı temsil eder. Böylece birden fazla bayrak aynı değişken içinde saklanabilir. Bug #1 kapsamında bu alanın koşulsuz şekilde üzerine yazılması, transaction'ın çalışma davranışının değiştirilmesine neden olabilir.

gchar *cached_package_id: tek bir pakete ait kimlik bilgisini tutan string pointer’dır. Bu alan genellikle belirli bir paket üzerinde işlem yapılacağı zaman kullanılır. Pointer olduğu için doğrudan verinin kendisini değil, bellekteki string’in adresini tutar.

gchar **cached_package_ids: birden fazla pakete ait kimlik bilgisini tutan string dizisi pointer’ıdır. Buradaki ** ifadesi pointer’a pointer anlamına gelir ve C dilinde genellikle string array yapısını temsil etmek için kullanılır. Birden fazla paket üzerinde işlem yapılacaksa bu alan üzerinden paket listesi taşınır.

gchar **cached_full_paths: kurulacak veya işlenecek dosyaların tam dosya yollarını tutar. Bu alan da string dizisi pointer’ı şeklindedir. Bug 1 kapsamında bu alanın üzerine yazılabilmesi, saldırganın işlemde kullanılacak dosya yollarını değiştirmesine neden olabilir. Böylece saldırgan, zararlı paketin yolunu bu alana yerleştirerek transaction’ın beklenmeyen bir dosya üzerinde çalışmasını sağlayabilir.

Zafiyet Adımları

CVE-2026-41651 figure 10

Adım 1: Saldırgan CreateTransaction() ile yeni bir transaction objesi oluşturur. Transaction NEW state'inde doğar.

Adım 2: İlk InstallFiles(SIMULATE, test.deb) çağrısı gelir. Kod akışı şöyle ilerler: Satır 4036'de cached_transaction_flags = SIMULATE yazılır. Ardından satır 2895–2902 'deki polkit kontrolüne gelinir. SIMULATE bayrağı görülür ve polkit sorgusu tamamen atlanır. Transaction doğrudan READY state'ine geçer. GLib event loop'a g_idle_add() ile bir idle callback eklenir (İleride uygun zamanda bu transaction'ı çalıştırılacak), scheduler bu callback üzerinden transaction'ı çalıştıracak ama Idle callback henüz çalışmadan saldırgan ikinci isteği gönderir.

Adım 3: İkinci InstallFiles(NONE, malicious.rpm) çağrısı gönderilir. GLib'in önceliklendirmesi nedeniyle bu D-Bus mesajı (G_PRIORITY_DEFAULT = 0) scheduler'ın idle callback'inden (G_PRIORITY_DEFAULT_IDLE = 200) garantili olarak önce işlenir.

GLib'de küçük öncelik değeri daha yüksek öncelik anlamına gelir. Bu nedenle önceliği 0 olan D-Bus mesajları, önceliği 200 olan idle callback'lerden her zaman önce işlenir. Bu durum, callback çalışmadan önce yeni D-Bus isteklerinin transaction verilerini değiştirebilmesine olanak tanır.

CVE-2026-41651 figure 11

Sonuç olarak event loop hem bir D-Bus isteği hem de bir idle callback bulunduğunda, GLib önce önceliği 0 olan D-Bus isteğini çalıştırır -- InstallFiles(NONE, malicious.rpm)--

InstallFiles() koşulsuz olarak cached_transaction_flags ve cached_full_paths'i hiçbir state kontrolü yapmadan üzerine yazar. pk_transaction_set_state() ise geriye dönük state geçişlerini sessizce reddeder. bayraklar zaten üzerine yazılmıştır ama state olduğu yerde kalır.

cached_transaction_flags = NONE;

cached_full_paths = malicious.rpm;

Adım 4: Idle callback son olarak tetiklendiğinde, pk_transaction_run() satır 2279'da cached_transaction_flags'ı okur. Artık SIMULATE değil NONE görür -> gerçek kurulum yoluna girer -> pk_backend_install_files() root yetkileriyle saldırganın paketini kurar.

Çözüm

SetHints ve Cancel dışındaki TÜM D-Bus method çağrılarının önüne bir state guard eklenir. Transaction NEW state'inde değilse çağrı PK_TRANSACTION_ERROR_INVALID_STATE hatası ile reddedilir, InstallFiles() dahil hiçbir method'a ulaşılamaz. Bayrak üzerine yazma engellenir.

Yama, pk_transaction_method_call() fonksiyonuna yani tüm D-Bus method çağrılarının giriş noktasına bir state guard ekler. Transaction NEW state'inde değilse çağrı hata ile reddedilir, cached parametreler değiştirilemez.

Bu yama sorunu en erken noktada keser: ikinci InstallFiles() çağrısı pk_transaction_method_call()'a ulaştığında, transaction artık NEW değil READY state'indedir çağrı hemen reddedilir satır 4036'daki bayrak üzerine yazma işlemine asla ulaşılmaz. Üç bug'ın tamamı tek bir giriş kontrolüyle etkisiz hale gelir.

Kritik mimari ders

Bu zafiyet, güvenlik mühendisliğinde üç klasik anti-pattern'in birleşiminden doğuyor: mutable shared state'in koşulsuz yazılabilmesi (Bug 1), hataların sessizce yutulması (Bug 2), ve güvenlik kararlarının geç binding ile uygulanması (Bug 3).

Etkilenen Sürümler

  1. PackageKit 1.0.2 – 1.3.4 arası tüm sürümler – 1.3.5 veya üzeri sürüme yükseltilmelidir.
  2. Ubuntu Desktop 18.04 (EOL), 24.04 LTS, 26.04 (beta)
  3. Ubuntu Server 22.04 – 24.04 LTS
  4. Debian 13.x (Trixie)
  5. Fedora 43 (Desktop/Server)
  6. Rocky Linux 10.1
  7. RHEL (Cockpit / PackageKit aktif ise)

Önerilen Aksiyonlar

PackageKit sürümü kontrol edilerek 1.3.5 veya daha yeni bir sürüme güncellenmelidir.

Güncellemenin kısa sürede gerçekleştirilemediği durumlarda, /etc/polkit-1/rules.d/00-block-packagekit.rules dosyası kullanılarak root olmayan kullanıcıların PackageKit erişimi engellenmelidir.

Sunucu üzerinde PackageKit kullanım gereksinimi bulunmuyorsa ilgili paket sistemden kaldırılmalıdır.

Olası istismar izlerinin tespiti amacıyla journalctl -u packagekit | grep -E "killed|signal|crash" komutu ile log kayıtları incelenmelidir.

Sistemde son kurulan paketler gözden geçirilmeli, beklenmeyen veya doğrulanamayan paketler detaylı olarak incelenmelidir.

Sistemde Cockpit kurulu ise PackageKit ile birlikte ek saldırı yüzeyi oluşturabileceği değerlendirilmeli, operasyonel ihtiyaç bulunmaması halinde kaldırılması düşünülmelidir.

Servis durdurulmuş olsa bile D-Bus aktivasyon dosyasını kontrol edilmelidir. Mevcut olduğu sürece daemon otomatik olarak tetiklenebilir.

PackageKit logları merkezi log yönetimi veya SIEM altyapısına yönlendirilmeli ve şüpheli aktiviteler için izleme mekanizmaları oluşturulmalıdır.

Meryem Nazım BEYOĞLU

Cyber Security Engineer

Bu yazı, PackageKit kaynak kodu üzerinde yapılan birebir analize ve resmi yama kayıtlarına dayanmaktadır.

Bu içeriği faydalı buldunuz mu?

Tehdit bültenlerimiz ve MDR Insights raporları ilk siz alın.

Ekip sertifikalarımız

SANS, Offensive Security, EC-Council, CompTIA, ISACA, CREST ve INE tarafından akredite uzmanlarımız.

SANS GPEN
SANS GWAPT
SANS GICSP
SANS GRTP
SANS GCIH
SANS GSEC
Offensive Security OSCP
Offensive Security OSWP
EC-Council CEH
CompTIA Security+
ISACA CISM
ISACA CISA
CREST CRT
INE eWPTX
Fortinet FCP Secure Networking
Fortinet FCP Cloud Security
Fortinet FCP Security Operations
Fortinet FCSS Secure Networking
Fortinet FCSS SASE
Fortinet FCSS Cloud Security
Fortinet FCSS Security Operations
IBM QRadar Admin
SANS GPEN
SANS GWAPT
SANS GICSP
SANS GRTP
SANS GCIH
SANS GSEC
Offensive Security OSCP
Offensive Security OSWP
EC-Council CEH
CompTIA Security+
ISACA CISM
ISACA CISA
CREST CRT
INE eWPTX
Fortinet FCP Secure Networking
Fortinet FCP Cloud Security
Fortinet FCP Security Operations
Fortinet FCSS Secure Networking
Fortinet FCSS SASE
Fortinet FCSS Cloud Security
Fortinet FCSS Security Operations
IBM QRadar Admin

Çerez kullanımı

Sitemizde sadece zorunlu oturum ve dil tercihi çerezleri kullanıyoruz; üçüncü taraf izleme çerezi yoktur. Detay için Çerez Politikası ve KVKK Aydınlatma Metni'ni inceleyin.