Linux Dosya Sistemi İzinleri ve Güvenlik Açıkları

Yıllar içinde şunu fark ettim: sistemlerin büyük çoğunluğu dışarıdan değil, içeriden çöküyor. Yanlış yapılandırılmış dosya izinleri, unutulmuş SUID bitleri, herkesin yazabildiği kritik dizinler… Bunlar penetrasyon testlerinde defalarca karşılaştığım ve “nasıl bu kadar süre fark edilmedi” diye hayrete düştüğüm sorunlar. Linux dosya sistemi izinleri, doğru kullanıldığında güçlü bir güvenlik katmanı oluşturur; ama yanlış yapılandırıldığında saldırganlara kırmızı halı serer.

Linux İzin Modeli: Temel Kavramlar

Linux’ta her dosya ve dizin üç temel izin grubuna sahiptir: owner (sahip), group (grup) ve others (diğerleri). Her grup için de üç farklı izin tipi vardır:

  • r (read – 4): Dosyayı okuma veya dizin içeriğini listeleme
  • w (write – 2): Dosyayı değiştirme veya dizine dosya ekleme/silme
  • x (execute – 1): Dosyayı çalıştırma veya dizine girme

ls -la çıktısında gördüğünüz -rwxr-xr-- gibi ifadeler bu üç grubun kombinasyonundan oluşur. İlk karakter dosya tipini gösterir (- normal dosya, d dizin, l sembolik link). Geri kalan 9 karakter ise sırasıyla owner, group ve others izinleridir.

# Dosya izinlerini detaylı görme
ls -la /etc/passwd
ls -la /etc/shadow

# Sayısal izinleri görmek için stat kullan
stat /etc/shadow
stat -c "%a %n" /etc/shadow

Üretim ortamında bir sunucuya ilk bağlandığımda her zaman bu iki dosyanın izinlerini kontrol ederim. /etc/shadow dosyası düzgün bir sistemde 640 veya 000 izinleriyle root:shadow sahipliğinde olmalıdır. Eğer 644 görüyorsanız, o sistemde ciddi bir sorun var demektir.

Özel İzin Bitleri: SUID, SGID ve Sticky Bit

İşte gerçek tehlikelerin başladığı yer burası. Çoğu sysadmin temel rwx izinlerini biliyor ama özel bitleri yeterince anlamıyor.

SUID Biti

SUID (Set User ID) biti, bir program çalıştırıldığında dosyanın sahibinin yetkileriyle çalışmasını sağlar. passwd komutu bunun en bilinen örneğidir; sıradan bir kullanıcı /etc/shadow dosyasını değiştirmesi gerekir ama bunu doğrudan yapamaz. passwd binary’si SUID bit ile root yetkisiyle çalışır ve bu işlemi güvenli biçimde gerçekleştirir.

# SUID bitli dosyaları bul - bu komut her sysadmin'in ezberinde olmalı
find / -perm -4000 -type f 2>/dev/null

# Daha kapsamlı, sadece belirli dizinleri tara
find /usr /bin /sbin -perm -4000 -type f -ls 2>/dev/null

# SGID bitli dosyaları bul
find / -perm -2000 -type f 2>/dev/null

Sorun şurada: bir sistemde beklenmedik SUID binary’leri varsa, saldırgan bunları privilege escalation için kullanabilir. GTFOBins (gtfobins.github.io) sitesine bakarsanız, vim, find, bash, python gibi araçların SUID bitli olduğunda nasıl root yetkisi elde etmek için kullanılabileceğini görebilirsiniz.

Gerçek bir senaryo: Bir müşterinin sunucusunu denetlerken /usr/bin/find üzerinde SUID biti aktif buldum. Bunu tespit etmek ve sömürmek çocuk oyuncağı:

# Eğer find binary'si SUID ise, saldırgan bunu yapabilir:
find . -exec /bin/sh -p ; -quit
# Bu komut root shell açar!

# Güvenli sistemde find'ın iznini kontrol et
ls -la /usr/bin/find
# Çıktı şöyle olmalı: -rwxr-xr-x (SUID yok)

SGID Biti ve Sticky Bit

SGID, SUID’e benzer ama grup üzerinde çalışır. Dizinlere uygulandığında ise o dizinde oluşturulan tüm dosyaların dizinin grubunu miras almasını sağlar. /tmp dizinindeki sticky bit ise klasik bir güvenlik mekanizmasıdır; bu bite sahip dizinlerde kullanıcılar yalnızca kendi oluşturdukları dosyaları silebilir.

# Sticky bit kontrolü
ls -la /tmp
# Çıktıda "t" harfini görmeli: drwxrwxrwt

# Sticky bit olmayan world-writable dizinleri bul - kritik güvenlik açığı!
find / -type d -perm -0002 ! -perm -1000 2>/dev/null

# SUID/SGID bitlerini kaldırma
chmod u-s /path/to/suspicious/binary
chmod g-s /path/to/suspicious/binary

Tehlikeli İzin Yapılandırmaları

Gerçek dünyada karşılaştığım en yaygın hataları şöyle sıralayabilirim:

World-Writable Dosyalar

Herkesin yazabildiği dosyalar (chmod 777 ile oluşturulanlar), özellikle sistem dizinlerinde felakete davetiye çıkarır. Bunları bulmak için:

# World-writable dosyaları bul (dizinler hariç)
find / -type f -perm -o+w 2>/dev/null | grep -v proc | grep -v sys

# World-writable ve sahipsiz dosyalar - daha tehlikeli!
find / -type f ( -perm -o+w ) -nouser 2>/dev/null

# Kritik sistem dizinlerinde world-writable dosyaları kontrol et
find /etc /usr /bin /sbin -perm -o+w -type f 2>/dev/null

Sahipsiz Dosyalar

Silinmiş kullanıcılara ait dosyalar sistemde kalabilir. Bu dosyalar hem bir temizlik sorunudur hem de potansiyel güvenlik açığıdır:

# Sahipsiz dosya ve dizinleri bul
find / -nouser -o -nogroup 2>/dev/null | head -50

# Daha güvenli bir tarama
find / -xdev ( -nouser -o -nogroup ) -print 2>/dev/null

Kritik Dosyaların İzin Denetimi

# Temel güvenlik denetimi scripti
#!/bin/bash
echo "=== Kritik Dosya İzin Denetimi ==="

# /etc/passwd kontrolü
PASSWD_PERM=$(stat -c "%a" /etc/passwd)
echo "/etc/passwd izni: $PASSWD_PERM"
[ "$PASSWD_PERM" != "644" ] && echo "UYARI: /etc/passwd izni yanlış!"

# /etc/shadow kontrolü  
SHADOW_PERM=$(stat -c "%a" /etc/shadow)
echo "/etc/shadow izni: $SHADOW_PERM"
[ "$SHADOW_PERM" != "640" ] && [ "$SHADOW_PERM" != "000" ] && echo "UYARI: /etc/shadow izni tehlikeli!"

# /etc/sudoers kontrolü
SUDOERS_PERM=$(stat -c "%a" /etc/sudoers)
echo "/etc/sudoers izni: $SUDOERS_PERM"
[ "$SUDOERS_PERM" != "440" ] && echo "UYARI: /etc/sudoers izni yanlış!"

echo "=== Tarama Tamamlandı ==="

Umask: Varsayılan İzinlerin Önemi

umask değeri, yeni oluşturulan dosya ve dizinlerin varsayılan izinlerini belirler. Çoğu sistem yöneticisi bunu göz ardı eder, ama üretim ortamında kritik öneme sahiptir.

Hesaplama şöyle çalışır: Dosyalar için maksimum izin 666, dizinler için 777‘dir. Umask bu değerden çıkarılır. Varsayılan 022 umask’ı ile dosyalar 644, dizinler ise 755 ile oluşturulur.

# Mevcut umask değerini görme
umask
umask -S  # Sembolik format

# Güvenli umask ayarı (özellikle root için)
# /etc/profile veya /etc/bashrc dosyasına ekle
umask 027  # Dosyalar: 640, Dizinler: 750

# Çok sıkı güvenlik gerektiren ortamlar için
umask 077  # Dosyalar: 600, Dizinler: 700

# Servis kullanıcıları için /etc/systemd/system/myservice.service içinde
# [Service]
# UMask=0027

Bir web sunucusu yapılandırmasında umask’ı unuttuğum için uygulama loglarının world-readable olduğunu ve bu loglarda hassas kullanıcı bilgileri bulunduğunu hatırlıyorum. Küçük bir gözden kaçırma, büyük veri sızıntısına yol açabilir.

ACL ile Granüler İzin Yönetimi

Standart Unix izinleri bazen yetersiz kalır. Birden fazla kullanıcıya farklı izin seviyeleri vermek gerektiğinde Access Control List (ACL) devreye girer.

# ACL desteğini kontrol et
mount | grep acl

# Bir dosyaya ACL ekle
setfacl -m u:ahmet:rw /var/www/html/config.php
setfacl -m g:developers:rx /var/www/html/

# ACL'yi görüntüle
getfacl /var/www/html/config.php

# Belirli bir kullanıcının ACL'sini kaldır
setfacl -x u:ahmet /var/www/html/config.php

# Varsayılan ACL ayarla (dizin içindeki yeni dosyalar için)
setfacl -d -m g:webadmin:rwx /var/www/html/uploads/

# Tüm ACL'leri kaldır
setfacl -b /var/www/html/config.php

Örneğin bir web projesinde hem geliştirme ekibine (developers grubu) hem de yedekleme servisine (backup kullanıcısı) farklı izinler vermek gerektiğinde ACL kullanmak standart chmod’dan çok daha temiz bir çözüm sunar.

Pratik Güvenlik Sertleştirme Adımları

Teoriden pratiğe geçelim. Bir sunucuyu sertleştirirken uyguladığım adımlar:

SUID/SGID Temizliği

# Önce mevcut SUID binary listesini kaydet
find / -perm -4000 -type f 2>/dev/null > /root/suid_baseline.txt

# Meşru SUID binary'leri (genellikle bunlar olmalı)
# /usr/bin/passwd
# /usr/bin/sudo
# /usr/bin/su
# /bin/ping (bazı sistemlerde)
# /usr/bin/newgrp
# /usr/bin/gpasswd

# Beklenmedik bir binary varsa SUID bitini kaldır
chmod u-s /usr/bin/at        # at komutu genellikle gerekmez
chmod u-s /usr/bin/traceroute6

# Periyodik kontrol için cron job ekle
echo "0 2 * * * root find / -perm -4000 -type f 2>/dev/null | diff /root/suid_baseline.txt - | mail -s 'SUID Degisikligi!' [email protected]" >> /etc/cron.d/security-check

Kapsamlı Güvenlik Tarama Scripti

#!/bin/bash
# linux_perm_audit.sh - Dosya izin güvenlik denetimi

RED='33[0;31m'
YELLOW='33[1;33m'
GREEN='33[0;32m'
NC='33[0m'

echo "========================================"
echo "  Linux Dosya İzin Güvenlik Denetimi"
echo "  Tarih: $(date)"
echo "========================================"

# 1. SUID dosyaları
echo -e "n${YELLOW}[!] SUID Bitli Dosyalar:${NC}"
find / -perm -4000 -type f 2>/dev/null | while read f; do
    echo -e "${RED}  SUID: $f${NC}"
done

# 2. World-writable dosyalar
echo -e "n${YELLOW}[!] World-Writable Dosyalar:${NC}"
find / -type f -perm -o+w 2>/dev/null | grep -v "/proc|/sys|/dev" | head -20

# 3. Sahipsiz dosyalar
echo -e "n${YELLOW}[!] Sahipsiz Dosyalar:${NC}"
find / -xdev ( -nouser -o -nogroup ) 2>/dev/null | head -20

# 4. .ssh dizin izinleri
echo -e "n${YELLOW}[!] SSH Dizin İzinleri:${NC}"
for home in /home/*/; do
    ssh_dir="${home}.ssh"
    if [ -d "$ssh_dir" ]; then
        perm=$(stat -c "%a" "$ssh_dir")
        if [ "$perm" != "700" ]; then
            echo -e "${RED}  HATA: $ssh_dir izni $perm (700 olmalı)${NC}"
        else
            echo -e "${GREEN}  OK: $ssh_dir${NC}"
        fi
    fi
done

echo -e "n${GREEN}Denetim tamamlandı.${NC}"

SSH Anahtar Dosyaları ve İzinler

SSH güvenliği söz konusu olduğunda dosya izinleri kritik öneme sahiptir. SSH servisi izinler yanlışsa anahtar dosyalarını reddeder.

# Doğru SSH izin yapısı
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_rsa
chmod 644 ~/.ssh/id_rsa.pub
chmod 600 ~/.ssh/authorized_keys
chmod 600 ~/.ssh/config

# Tüm kullanıcıların SSH dizin izinlerini toplu düzelt
for user_home in /home/*/; do
    username=$(basename "$user_home")
    ssh_dir="${user_home}.ssh"
    
    if [ -d "$ssh_dir" ]; then
        chown -R "$username:$username" "$ssh_dir"
        chmod 700 "$ssh_dir"
        chmod 600 "$ssh_dir"/* 2>/dev/null
        chmod 644 "$ssh_dir"/*.pub 2>/dev/null
        echo "Düzeltildi: $ssh_dir"
    fi
done

# authorized_keys dosyasını yanlış izinler için tara
find /home -name "authorized_keys" -not -perm 600 2>/dev/null

Chattr ile Değiştirilemez Dosyalar

İzinlerin ötesinde bir güvenlik katmanı olarak chattr komutu, root dahil hiç kimsenin değiştiremeyeceği dosyalar oluşturmanızı sağlar:

# Dosyayı değiştirilemez yap
chattr +i /etc/passwd
chattr +i /etc/shadow
chattr +i /etc/sudoers

# Sadece eklenebilir yap (log dosyaları için ideal)
chattr +a /var/log/auth.log
chattr +a /var/log/syslog

# Özellikleri görüntüle
lsattr /etc/passwd
lsattr /var/log/

# Değiştirilemez bayrağını kaldır (önce bunu yapman gerekir)
chattr -i /etc/passwd

Dikkat: Sistem güncellemelerinden önce chattr +i uygulanmış dosyaları geçici olarak serbest bırakmanız gerekebilir. Ben genellikle kritik konfigürasyon dosyalarına bunu uygularım ama /etc/passwd gibi sistem güncellemelerinde değişebilecek dosyalara uygulamayı önermem, aksi halde sistem güncellemeleriniz başarısız olabilir.

Systemd Servis İzolasyonu

Modern Linux sistemlerinde servis güvenliğini dosya izinleriyle birlikte systemd üzerinden de güçlendirebilirsiniz:

# /etc/systemd/system/myapp.service
[Unit]
Description=My Application Service

[Service]
User=myapp
Group=myapp
UMask=0027
# Dosya sistemi izolasyonu
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/var/lib/myapp /var/log/myapp
PrivateTmp=true
NoNewPrivileges=true
# Gereksiz yetenek kısıtlaması
CapabilityBoundingSet=CAP_NET_BIND_SERVICE

[Install]
WantedBy=multi-user.target
# Servis izolasyon ayarlarını uygula
systemctl daemon-reload
systemctl restart myapp

# Servis güvenlik skorunu kontrol et
systemd-analyze security myapp.service

Bu yapılandırma, servis ele geçirilse bile saldırganın dosya sisteminde hareket alanını ciddi ölçüde kısıtlar.

Sonuç

Linux dosya sistemi izinleri, kulağa teknik ve sıkıcı gelebilir ama bu alandaki bir ihmal gerçek dünyada ciddi sonuçlar doğurabilir. Yıllardır sysadminlik yapan biri olarak şunu söyleyebilirim: En iyi güvenlik duvarı bile içeride bırakılan açık bir kapıya karşı sizi koruyamaz.

Bugün yapabileceğiniz en değerli şey şu: Sunucularınızda SUID bitli dosyaların bir baseline listesini çıkarın, world-writable dosyaları tarayın ve kritik konfigürasyon dosyalarınızın izinlerini doğrulayın. Bu taramayı düzenli aralıklarla yapacak basit bir cron job bile sizi büyük saldırılardan koruyabilir.

Güvenlik bir kez yapılıp unutulan bir şey değil, sürekli izlenmesi ve güncellenmesi gereken bir süreçtir. Umask değerlerinizi gözden geçirin, ACL kullanmayı düşünün, systemd servis izolasyonunu uygulayın ve her yeni servis kurulumunda “bu servise gerçekten bu kadar izin gerekli mi?” diye sorun. En az ayrıcalık prensibi, sadece bir güvenlik teorisi değil; her gün uygulamanız gereken bir alışkanlıktır.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir