setuid, setgid ve Sticky Bit: Özel Dosya İzin Bitleri ile Güvenli Yetki Yönetimi
Yıllar önce bir müşterinin sunucusunda ilginç bir sorunla karşılaştım. Geliştirici ekibi, uygulama loglarını temizlemek için bir script yazmıştı. Script çalışıyordu, ama sadece root olarak. Normal kullanıcılar çalıştırmak istediğinde “Permission denied” alıyordu. Çözüm basitti: setuid biti. Ama o gün fark ettim ki bu bitleri çoğu sysadmin yüzeysel biliyor, derinlemesine anlamıyor. Bugün o derinliğe iniyoruz.
Özel İzin Bitleri Nedir?
Linux’ta dosya izinlerini konuştuğumuzda genellikle rwxrwxrwx formatından bahsederiz. Sahip, grup ve diğerleri için okuma, yazma, çalıştırma. Ama bu tablonun önünde, çoğu zaman görmezden gelinen bir dördüncü oktet daha var.
Standart chmod 755 dediğimizde aslında chmod 0755 diyoruz. O baştaki sıfır, özel bitlerin alanı. Bu alan üç özel biti barındırıyor:
- setuid (SUID): Oktet değeri 4, sembolik gösterim
s(sahip çalıştırma bitinin yerine) - setgid (SGID): Oktet değeri 2, sembolik gösterim
s(grup çalıştırma bitinin yerine) - Sticky Bit: Oktet değeri 1, sembolik gösterim
t(diğerleri çalıştırma bitinin yerine)
Bu üçü birbirinden çok farklı amaçlara hizmet ediyor ve kullanım bağlamları da tamamen ayrı.
setuid Biti: “Benim Gibi Çalış”
setuid, bir dosyanın sahibinin kimliğiyle çalışmasını sağlar. Yani siz o dosyayı çalıştırdığınızda, kendi kullanıcı kimliğinizle değil, dosyanın sahibinin kimliğiyle process başlatılır.
En klasik örnek passwd komutu:
ls -la /usr/bin/passwd
Çıktı şuna benzer bir şey olacak:
-rwsr-xr-x 1 root root 59640 Mar 22 2023 /usr/bin/passwd
Görüyor musunuz? Sahip çalıştırma bitinin yerinde x yerine s var. Bu, passwd komutunu hangi kullanıcı çalıştırırsa çalıştırsın, root yetkileriyle çalıştığı anlamına gelir. Çünkü /etc/shadow dosyasını değiştirmek için root yetkisi gerekiyor.
# Başka setuid'li binary'leri bulmak için:
find / -perm -4000 -type f 2>/dev/null
Bu komut sistemdeki tüm setuid dosyalarını listeler. Güvenlik denetimleri yapıyorsanız bu çıktıyı düzenli kayıt altına almalısınız.
setuid Nasıl Uygulanır?
# Sayısal yöntem
chmod 4755 /usr/local/bin/myapp
# Sembolik yöntem
chmod u+s /usr/local/bin/myapp
# Sonucu doğrulamak için
ls -la /usr/local/bin/myapp
# -rwsr-xr-x 1 root root ...
Eğer çalıştırma biti olmayan bir dosyaya setuid koyarsanız, s yerine S (büyük harf) görürsünüz. Bu, setuid’in tanımlandığı ama aktif olmadığı anlamına gelir:
chmod 4644 /tmp/test_file
ls -la /tmp/test_file
# -rwSr--r-- ... (büyük S = çalıştırma biti yok, setuid işlevsiz)
Gerçek Dünya Senaryosu: Uygulama Log Rotasyonu
Diyelim ki uygulama logları /var/log/myapp/ altında ve root’a ait. Geliştirici kullanıcısının bu logları temizlemesi gerekiyor:
# Önce temizlik scriptini hazırlayalım
cat > /usr/local/bin/clean_applogs.sh << 'EOF'
#!/bin/bash
LOG_DIR="/var/log/myapp"
find "$LOG_DIR" -name "*.log" -mtime +30 -delete
echo "Loglar temizlendi: $(date)"
EOF
chmod 755 /usr/local/bin/clean_applogs.sh
chown root:root /usr/local/bin/clean_applogs.sh
# setuid uygula
chmod u+s /usr/local/bin/clean_applogs.sh
Önemli uyarı: setuid shell scriptleri üzerinde çoğu modern Linux dağıtımında güvenlik nedeniyle çalışmaz. Bash ve diğer shell’ler setuid scriptleri kasıtlı olarak görmezden gelir. Bu durumda C ile küçük bir wrapper binary yazmak gerekir, ya da sudo tercih edilmesi önerilir.
setuid Güvenlik Riskleri
setuid’i körü körüne uygulamak tehlikeli. Şunlara dikkat:
- setuid binary’leri, potansiyel privilege escalation vektörleridir
- Her yeni binary’ye setuid koymadan önce alternatif olarak
sudokurallarını değerlendirin - Periyodik olarak setuid dosya listesini denetleyin, beklenmedik bir dosya varsa alarm olsun
# Sistemdeki setuid dosyalarını bir baseline olarak kaydedin
find / -perm -4000 -type f 2>/dev/null | sort > /root/setuid_baseline.txt
# Sonraki denetimlerde farkları görmek için:
find / -perm -4000 -type f 2>/dev/null | sort > /tmp/setuid_current.txt
diff /root/setuid_baseline.txt /tmp/setuid_current.txt
setgid Biti: Grup Kimliğiyle Çalış ve Kalıt Al
setgid, setuid’in grup versiyonu gibi görünse de aslında iki farklı bağlamda çalışır: dosyalar üzerinde ve dizinler üzerinde.
Dosyalar Üzerinde setgid
Bir binary’e setgid uygulandığında, o program çalıştırıldığında dosyanın grup kimliğiyle çalışır. ls -la çıktısında grup çalıştırma bitinin yerinde s görürsünüz:
ls -la /usr/bin/write
# -rwxr-sr-x 1 root tty ... /usr/bin/write
write komutu tty grubuyla çalışır çünkü terminal cihazlarına erişmek için bu gruba üye olmak gerekir.
Dizinler Üzerinde setgid: Asıl Güç Burada
setgid’in en kullanışlı özelliği dizinler üzerinde. Bir dizine setgid uygulandığında, o dizin içinde oluşturulan tüm yeni dosyalar ve alt dizinler, oluşturan kullanıcının birincil grubunu değil, dizinin grubunu miras alır.
Bu özellik, paylaşımlı çalışma ortamlarında altın değerinde:
# Proje paylaşım dizini oluşturalım
mkdir /var/shared/proje-alfa
chown root:developers /var/shared/proje-alfa
chmod 770 /var/shared/proje-alfa
# setgid uygula
chmod g+s /var/shared/proje-alfa
# Sonucu kontrol et
ls -ld /var/shared/proje-alfa
# drwxrws--- 2 root developers ... /var/shared/proje-alfa
Şimdi developers grubundaki herhangi bir kullanıcı bu dizinde dosya oluşturduğunda, dosya otomatik olarak developers grubuna ait olur:
# developer1 kullanıcısı olarak:
touch /var/shared/proje-alfa/yeni_dosya.txt
ls -la /var/shared/proje-alfa/yeni_dosya.txt
# -rw-r--r-- 1 developer1 developers ... yeni_dosya.txt
Dosya developer1‘e ait ama grubu developers. Bu sayede gruptaki diğer herkes dosyaya erişebilir.
Gerçek Dünya Senaryosu: Git Repository Paylaşımı
Ekip içi bir bare git repository kurarken setgid olmazsa olmaz:
# Shared git reposu için dizin hazırlığı
mkdir -p /opt/repos/backend-api.git
chown -R git:git-team /opt/repos/backend-api.git
chmod -R 2775 /opt/repos/backend-api.git
# 2775 = setgid + rwxrwxr-x
# Bare repo initialize et
cd /opt/repos/backend-api.git
git init --bare --shared=group
# Mevcut alt dizinlerde setgid'i doğrula
ls -la /opt/repos/backend-api.git/
# Her dizinin yanında 's' biti olmalı
git init --shared=group zaten setgid ayarını yapıyor, ama elle de yapabilirsiniz.
# Alt dizinlere de setgid uygulamak için:
find /opt/repos/backend-api.git -type d -exec chmod g+s {} ;
Sticky Bit: “Kendininkini Sil”
Sticky bit, bugün neredeyse yalnızca dizinler üzerinde anlamlı bir işlev görüyor. Tarihsel olarak executable dosyalar üzerinde de kullanılırdı (programı RAM’de tutmak için), ama modern sistemlerde bu işlev ortadan kalktı.
Bir dizine sticky bit uygulandığında, o dizindeki dosyaları sadece dosyanın sahibi, dizinin sahibi veya root silebilir. Dizine yazma yetkisi olan herkes dosya oluşturabilir, ama başkasının dosyasına dokunamaz.
En bilinen örnek /tmp:
ls -ld /tmp
# drwxrwxrwt 20 root root ... /tmp
Sondaki t harfi sticky bit’i gösteriyor. Herkes /tmp‘ye yazabilir, ama sadece kendi dosyasını silebilir.
Sticky Bit Nasıl Uygulanır?
# Sayısal yöntem
chmod 1777 /shared/uploads
# Sembolik yöntem
chmod +t /shared/uploads
# Sonucu doğrula
ls -ld /shared/uploads
# drwxrwxrwt ... /shared/uploads
Gerçek Dünya Senaryosu: Çok Kullanıcılı Upload Dizini
Web sunucusunda birden fazla müşterinin dosya yüklediği bir senaryo düşünün:
# Upload dizini oluştur
mkdir /var/www/uploads
chown root:www-data /var/www/uploads
chmod 1777 /var/www/uploads
# Her müşteri kendi klasörünü görsün ama başkasının dosyasına dokunamasın
ls -ld /var/www/uploads
# drwxrwxrwt 2 root www-data ... /var/www/uploads
Bu yapıda client1 kullanıcısı /var/www/uploads/client2_file.txt dosyasını silemez. Ama kendi dosyalarını rahatlıkla yönetebilir.
Daha gerçekçi bir senaryo: CI/CD pipeline’ında artifact deposu:
# Build artifact dizini
mkdir /opt/artifacts
chown root:cicd-team /opt/artifacts
chmod 1775 /opt/artifacts
# 1775 = sticky + rwxrwxr-x
# Herkes okuyabilir, group yazabilir, ama sadece sahibi/root silebilir
Üç Biti Birlikte Anlamak
Sayısal değerleri kafanıza kazıyalım:
- 4000: setuid
- 2000: setgid
- 1000: sticky bit
Bunları birleştirmek de mümkün. Hem setuid hem setgid hem sticky bit istiyorsanız 7xxx, ikisini istiyorsanız toplayarak buluyorsunuz: setuid + setgid = 6xxx.
# Özel bir dizin için hem setgid hem sticky bit:
chmod 3755 /shared/proje
# 3 = 2 (setgid) + 1 (sticky)
ls -ld /shared/proje
# drwxr-sr-t ... /shared/proje
Özel Bitleri Kaldırmak
# setuid kaldır
chmod u-s /usr/local/bin/myapp
# veya
chmod 0755 /usr/local/bin/myapp
# setgid kaldır
chmod g-s /shared/directory
# veya sayısal: ilk oktet 0 olmalı
chmod 0755 /shared/directory
# Sticky bit kaldır
chmod -t /tmp/testdir
# veya
chmod 0777 /tmp/testdir
# Tüm özel bitleri kaldır (başa 0 ekle)
chmod 0755 /some/path
Güvenlik Denetimi: Sisteminizi Tarayın
Düzenli yapılması gereken güvenlik kontrolleri:
# Tüm setuid dosyaları bul
find / -xdev -perm -4000 -type f 2>/dev/null | xargs ls -la
# Tüm setgid dosyaları bul
find / -xdev -perm -2000 -type f 2>/dev/null | xargs ls -la
# Her ikisi de olan dosyalar
find / -xdev -perm -6000 -type f 2>/dev/null | xargs ls -la
# World-writable sticky bit olmayan dizinler (potansiyel tehlike)
find / -xdev -type d -perm -0002 ! -perm -1000 2>/dev/null | xargs ls -ld
-xdev parametresi mount noktalarını geçmez, NFS veya proc gibi dosya sistemlerinde takılı kalmamak için önemli.
Özel Bitleri nosuid ile Devre Dışı Bırakmak
Belirli bir mount noktasında setuid ve setgid’i tamamen kapatabilirsiniz:
# /etc/fstab'da:
/dev/sdb1 /data ext4 defaults,nosuid,noexec 0 2
# Çalışan sisteme anında uygulamak için:
mount -o remount,nosuid /data
nosuid seçeneği, o partition’da hiçbir dosyanın setuid veya setgid ile çalışmamasını garanti eder. Kullanıcı home dizinlerini ayrı partition’a aldıysanız bunu mutlaka uygulayın.
Sık Yapılan Hatalar
Yıllar içinde gördüğüm klasik hatalar:
- Dizin yerine dosyaya sticky bit koymak: Dosyalarda sticky bitin bugün bir etkisi yok, ama kafa karışıklığı yaratıyor.
- setuid shell script yazmak: Daha önce söylediğim gibi, modern Linux’ta çalışmaz. C wrapper veya sudo kullanın.
- setgid’siz paylaşımlı dizin açmak: Ekip çalışmalarında “neden dosyama erişemiyorum” sorularının %80’i buradan geliyor.
- Büyük S ve büyük T’yi fark etmemek:
svetküçük harf = ilgili bit + çalıştırma biti var.SveTbüyük harf = ilgili bit var ama çalıştırma biti yok. Büyük harfler genellikle hatalı bir konfigürasyona işaret eder.
# Bu farkı görmek için:
chmod 4644 /tmp/test1 # setuid var ama çalıştırma biti yok
chmod 4755 /tmp/test2 # setuid var ve çalıştırma biti de var
ls -la /tmp/test1 /tmp/test2
# -rwSr--r-- ... test1 (büyük S - işlevsiz setuid)
# -rwsr-xr-x ... test2 (küçük s - aktif setuid)
Sonuç
setuid, setgid ve sticky bit, Linux güvenlik modelinin en ince noktalarından biri. Doğru kullanıldığında hayat kurtarır: paylaşımlı geliştirme ortamları, sistem araçları, geçici dosya dizinleri. Yanlış kullanıldığında ise privilege escalation için kapı aralar.
Pratikte önerim şu: önce sudo ile çözüp çözemeyeceğinize bakın. sudo, setuid’den çok daha denetlenebilir ve loglama açısından çok daha zengin. Ama setgid’li dizinler ve sticky bit için gerçek alternatif yok, bu iki özelliği doğru senaryolarda çekinmeden kullanın.
Sisteminizde hangi dosyaların setuid’li olduğunu biliyor musunuz? Bilmiyorsanız, bu yazıdaki find komutlarıyla hemen bir baseline oluşturun. Güvenlik denetimlerinin en temel adımlarından biri bu, ve çoğu zaman görmezden gelinir.
