ptrace attack surface (TRACEME races, YAMA scope)¶
ptrace()tracer/tracee privilege boundary'si neden kırılgan: PTRACE_TRACEME + SUID-exec race'leri, daha yetkili process'lere PTRACE_ATTACH ve YAMAptrace_scopehardening ladder'ı.
Mechanism¶
ptrace() bir process'in (tracer) başka bir process'in (tracee) register, memory ve signal delivery'sini okumasına/yazmasına izin verir. Bu debug primitive'i tanım gereği güçlüdür: tracer, tracee'nin address space'ini yazabildiği ve syscall'ları redirect edebildiği için pratikte tracee'nin tüm privilege'larını devralır. Dolayısıyla kernel'in tek işi doğru: bir tracer'ın, kendisinden daha yetkili bir tracee'ye asla bağlanamamasını garanti etmek.
man7 ptrace(2)'nin "Ptrace access mode checking" algoritması bu invariant'ı uygular: aynı thread group her zaman serbest; aksi halde credential (real ya da filesystem UID/GID) match etmeli veya caller CAP_SYS_PTRACE taşımalı; ayrıca tracee'nin dumpable attribute'u 1 değilse yine CAP_SYS_PTRACE gerekir. Bir process set-user-ID/set-group-ID binary çalıştırdığında (execve()) kernel onu non-dumpable yapar — böylece unprivileged bir user, uid geçişi yapmış bir SUID process'i trace edemez.
Note
Bug class iki yerden çıkar. (1) PTRACE_TRACEME asimetrisi: TRACEME'de child, "parent'ım beni trace etsin" der ve kernel ptrace relationship'i parent'ın o anki credential'larına göre kurar. Eğer bir SUID/privileged parent sonradan privilege drop edip execve() yaparsa, önceden kaydedilmiş privileged relationship, attacker-controlled bir process'e miras kalabilir — bu tam olarak CVE-2019-13272'nin (Jann Horn) privilege-inheritance + object-lifetime bug'ıdır. (2) execve/attach race: klasik execve+ptrace race'lerinde (Linux 2.2.x, 2009'daki cred_exec_mutex hatası CVE-2009-1527) tracer, SUID exec'in credential geçişini tamamlamasıyla non-dumpable flag'in set edilmesi arasındaki pencerede ATTACH ederek, transition sonrası privileged image üzerinde kontrol kazanır. İki durumda da ihlal edilen invariant aynı: privilege transition'ı (execve) ile ptrace-erişim kararı atomik değildir.
Walkthrough¶
CVE-2019-13272 sınıfının cited public writeup'tan yüksek-seviye mantığı (fragment + adımlar; weaponize edilmiş kod değil):
-
Unprivileged bir process fork eder; child hemen kendini trace edilmeye işaretler:
-
Kernel ptrace linkini parent'ın o anki credential'larına göre kurar. Buradaki hata, RCU-korumalı parent credential'ının object lifetime kurallarına uyulmadan stabilize edilmesi ve relationship'in "parent initiator" gibi kaydedilmesidir.
-
SUID helper iş bittiğinde privilege drop eder / re-exec olur; sonuç: attacker'ın kontrol ettiği tarafta, privileged bir ptrace ilişkisi duran iki process kalır.
-
Bu privileged ilişki, bir root process'e/SUID image'a ptrace ile inject etmek için kaldıraç olur — böylece root'a ulaşılır.
Warning
Aynı sink'in yaşamayan varyantı execve/attach race'idir: SUID exec sırasında dar pencerede PTRACE_ATTACH denenip, credential commit ile non-dumpable set arasındaki sıralama tersine çevrilirse, tracer transition sonrası image'ı yönetir. Race pencereleri kernel sürümleri arasında evrildiği için (çoğu 2.6.29.3, 2.2.19 gibi noktalarda kapatılmıştır) mutlak varsayma; kendi kernel sürümünde davranışı doğrula.
Detection¶
- auditd:
ptracesyscall'ını audit rule ile yakala; özelliklePTRACE_ATTACH/PTRACE_SEIZE/PTRACE_TRACEMErequest'lerini logla. Örnek:-a always,exit -F arch=b64 -S ptrace -k ptrace_use. Farklı uid/parent olmayan bir hedefe attach anomali sinyalidir. - YAMA denial'ları:
ptrace_scope >= 1iken engellenen attach'lar kernel ring buffer'aptrace_scopereddi bırakabilir —dmesg/journal'da "ptrace" denial pattern'lerini izle. - EDR/telemetry tarafında: SUID binary'lerin (pkexec,
at, vb.) hemen ardından gelenPTRACE_TRACEME/PTRACE_ATTACHsekansları ve kısa ömürlü fork+exec+trace zincirleri yüksek-değerli davranışsal göstergelerdir.
Mitigation¶
-
YAMA
ptrace_scopeladder'ını yükselt (/proc/sys/kernel/yama/ptrace_scope):sysctl -w kernel.yama.ptrace_scope=1 # restricted: yalnız descendant'lar # 2 = admin-only (yalnız CAP_SYS_PTRACE); 3 = no-attach (geri alınamaz)Mode 1 default'tur ve non-descendant ATTACH'ı bloklar; whitelist gereken debugger'lar
prctl(PR_SET_PTRACER, pid, ...)ile açıkça declare eder. -
no_new_privs(prctl(PR_SET_NO_NEW_PRIVS)) SUID privilege elevation'ını kapatır, böylece TRACEME/execve inheritance zincirinin dayandığı privilege-gain ortadan kalkar; seccomp/container sandbox'larla birlikte uygula. - SUID minimization: gereksiz set-user-ID bit'lerini kaldır (
find / -perm -4000), pkexec gibi geniş yüzeyleri capability'lere ya da polkit-siz alternatiflere indir; SUID kümesini küçülterek TRACEME-inheritance sink'ini besleyen privileged parent'ları azalt. - Kernel'i patch'li tut: CVE-2019-13272 ve tarihsel execve/ptrace race'leri upstream'de kapatılmıştır.
Warning
Yeni bir user namespace oluşturmak YAMA korumasını efektif olarak kaldırabilir (man7 ptrace notu). Unprivileged user namespace açık olan sistemlerde ptrace_scope tek başına yeterli değildir; kernel.unprivileged_userns_clone=0 ya da namespace kısıtlaması ile birlikte değerlendir.