Saat gece üçte telefonunuza izleme uyarısı düşüyor: iki çekirdekli sunucunuzda yük ortalaması 9'a çıkmış. Bağlanıp top çalıştırıyorsunuz ve listenin başında adını hiç duymadığınız bir süreç duruyor, CPU'nun yüzde 190'ını yemiş. Ya da sağlayıcınızdan bir kötüye kullanım bildirimi geliyor: sunucunuzun IP'si, başka makinelere SSH kaba kuvvet denemesi yaptığı için şikâyet edilmiş. Belki de daha sessiz bir şey oldu; sadece last çıktısında tanımadığınız bir IP'den başarılı bir giriş gördünüz.
Bu üç senaryonun ortak noktası şu: elinizde bir şüphe var ama kanıt yok. Ve bu aşamada yapılan en yaygın iki hata birbirinin zıddıdır. Birincisi, hiçbir şey doğrulamadan sunucuyu formatlayıp yeniden kurmak; bu, saldırının nasıl girdiğini asla öğrenememek ve aynı açıkla iki hafta sonra tekrar girilmesi demektir. İkincisi ise "muhtemelen bir şey yoktur" deyip devam etmek; oysa ele geçirilmiş bir sunucu her geçen saat başkalarına da zarar verir.
Doğru yol, sırayla ilerleyen bir teşhis listesidir. Bu yazı web sitesi seviyesine değil, sunucu seviyesine odaklanıyor: hangi süreçler çalışıyor, hangi portlar dinleniyor, dışarıya nereye bağlantı kuruluyor, kim ne zaman giriş yapmış, sistem yeniden başlasa saldırgan geri gelir mi. Her adımda ne aradığınızı, bulduğunuz şeyin ne anlama geldiğini ve bulgu doğrulanırsa ne yapmanız gerektiğini ayrı ayrı vereceğiz.
İlk Karar: Sunucuyu Kapatmalı mıyım?#
Kontrol listesine başlamadan önce bir karar vermeniz gerekiyor ve bu kararın geri dönüşü zordur.
Sunucuyu kapatmak çalışan kötü amaçlı süreçleri durdurur ama RAM'deki tüm kanıtı da yok eder: çalışan sürecin bellek görüntüsü, açık bağlantılar, şifresi çözülmüş yapılandırmalar. Diskten silinip yalnızca bellekte çalışan bir zararlıyı bir daha asla göremezsiniz.
Sunucuyu açık bırakmak kanıtı korur ama saldırganın zarar vermeye devam etmesine izin verir; üstelik sizi izliyorsa iz temizleyebilir.
Pratikte en dengeli seçenek üçüncüsüdür: ağ seviyesinde izole edip açık bırakmak. Sunucuyu kapatmadan, sağlayıcının paneli veya güvenlik grubu üzerinden yalnızca kendi IP'nizden gelen yönetim erişimine izin verin, diğer tüm trafiği kesin. Böylece süreçler ayakta kalır, siz inceleme yaparsınız, saldırgan ise dışarıyla konuşamaz.
Bu ayarı sunucunun içindeki firewall'dan değil, mümkünse dışarıdan yapın; çünkü sunucuya kök erişimi olan biri içerideki kuralları geri alabilir. İçeriden yapmak zorundaysanız kendinizi kilitlememek için firewall kuralı yüzünden sunucuya giremediğiniz durumun çıkışlarını önceden bilin.
İncelemeye başlamadan önce, mümkünse diskin snapshot'ını alın. Sonradan "şu dosyanın eski hali neydi?" diye sorduğunuzda tek cevabınız o olacak.
Adım 1: Şüpheli Süreçleri Tespit Etme#
Ele geçirilmiş sunucuların büyük çoğunluğunda ilk belirti CPU'dur, çünkü en yaygın saldırı amacı kripto madenciliğidir.
# CPU'ya göre sıralı ilk 15 süreç
ps -eo pid,ppid,user,%cpu,%mem,etime,comm --sort=-%cpu | head -15
# Süreç ağacını üst-alt ilişkisiyle gör
ps auxf
# Sürekli izleme
top -o %CPU
Şüpheli bir PID bulduğunuzda asıl bilgi /proc altındadır. Süreç adı kolayca taklit edilebilir; ikilinin gerçekte nerede durduğu edilemez:
PID=12345
ls -l /proc/$PID/exe # Çalışan ikilinin gerçek yolu
ls -l /proc/$PID/cwd # Sürecin çalışma dizini
tr '\0' ' ' < /proc/$PID/cmdline; echo # Tam komut satırı
cat /proc/$PID/environ | tr '\0' '\n' # Ortam değişkenleri
Bulgularınızı şöyle okuyun:
| Bulgu | Ne anlama gelir | Aciliyet |
|---|---|---|
/proc/PID/exe -> /tmp/.x (deleted) | İkili silinmiş, süreç bellekte çalışıyor. Klasik zararlı davranışı. | Çok yüksek |
İkili /tmp, /dev/shm, /var/tmp altında | Bu dizinler normalde çalıştırılabilir dosya barındırmaz | Yüksek |
Süreç adı kdevtmpfsi, kinsing, xmrig, rastgele harfler | Bilinen madenci ve bot aileleri | Çok yüksek |
Sistem sürecine benzer ad ama yanlış yol (/usr/bin/crond yerine /tmp/crond) | Kasıtlı kamuflaj | Çok yüksek |
www-data kullanıcısı altında kabuk süreci | Web uygulaması üzerinden komut çalıştırılmış | Yüksek |
Yüksek CPU ama meşru servis (mysqld, php-fpm) | Muhtemelen performans sorunu, saldırı değil | Düşük |
Son satır önemlidir: her yüksek CPU saldırı değildir. Süreç izleme araçlarının normal kullanımı ve yük yorumlama için süreç izleme: ps, top, htop yazısı iyi bir referanstır.
Şüpheli süreci hemen öldürmeyin. Kalıcılık mekanizmasını bulmadan süreci sonlandırmak yalnızca birkaç dakika kazandırır; cron veya systemd onu geri getirir. Önce nereden başlatıldığını tespit edin, sonra hepsini birlikte temizleyin. Sinyal seçimi ve süreç sonlandırma detayları için süreç sonlandırma ve kill sinyalleri yazısına bakabilirsiniz.
Adım 2: Dinlenen Portlar ve Dışa Giden Bağlantılar#
İkinci adım, sunucunun ağ üzerinden kiminle konuştuğuna bakmaktır. Burada iki ayrı soru var: dışarıya hangi kapıları açtınız ve sunucu kendi isteğiyle nereye bağlanıyor?
# Dinlenen TCP ve UDP portları, süreç adlarıyla
ss -tulnp
# Kurulu (established) dışa giden bağlantılar
ss -tnp state established
# Aynı bilgiyi eski araçla
netstat -tulnp
Dinleyen port listesini kafanızdaki "olması gerekenler" listesiyle karşılaştırın. Tipik bir web sunucusunda 22, 80, 443 ve belki 3306'nın yerelde dinlemesi beklenir. Bunun dışında bir şey varsa açıklaması olmalıdır.
Dışa giden bağlantılar genellikle daha ele verici olur:
| Gözlem | Yorum |
|---|---|
| Bilinmeyen IP'lere 3333, 4444, 5555, 14444 portlarından bağlantı | Madencilik havuzu bağlantısı |
| Rastgele yüksek portta sürekli açık tek bir bağlantı | Komuta-kontrol kanalı olabilir |
| Çok sayıda hedefe giden 22 numaralı port bağlantısı | Sunucunuz kaba kuvvet taraması yapıyor |
| Çok sayıda hedefe giden 25 numaralı port bağlantısı | Sunucunuz spam gönderiyor |
| Bilinmeyen bir sürecin 0.0.0.0 üzerinde dinlemesi | Arka kapı dinleyicisi |
Bir bağlantının hangi sürece ait olduğunu ss çıktısındaki users: alanından okuyabilir, ardından o PID için Adım 1'deki /proc kontrollerini tekrarlayabilirsiniz. Komutların bayrakları ve çıktı biçimleri hakkında ayrıntı için açık portları listeleme: ss ve netstat ve hangi portların açık kalması gerektiği için sunucuda hangi portlar açık olmalı yazıları işinizi görür.
Adım 3: Kullanıcı Hesapları, UID 0 ve sudo Yetkileri#
Saldırganın kalıcı olmak için en sevdiği yollardan biri, kendine bir hesap açmak ya da mevcut bir hesabı yükseltmektir. Buradaki kontroller hızlıdır ve çok net cevap verir.
# UID 0 olan (yani root yetkili) tüm hesaplar
awk -F: '$3 == 0 { print $1, $3, $7 }' /etc/passwd
# Kabuk erişimi olan hesaplar
awk -F: '$7 !~ /(nologin|false)$/ { print $1, $7 }' /etc/passwd
# Şifresi olmayan hesaplar
awk -F: '$2 == "" { print $1 }' /etc/shadow
# sudo/wheel grubu üyeleri
getent group sudo wheel
# Ek sudo kuralları
ls -la /etc/sudoers.d/
grep -r 'NOPASSWD' /etc/sudoers /etc/sudoers.d/ 2>/dev/null
/etc/passwd içinde root dışında UID 0 olan bir hesap görürseniz burada tartışacak bir şey yoktur: sistem ele geçirilmiştir. Aynı şekilde /etc/sudoers.d/ altında sizin koymadığınız, NOPASSWD: ALL içeren bir dosya kesin bulgudur.
Hesapların ne zaman oluşturulduğunu dosya zaman damgalarından çıkarabilirsiniz:
# Kullanıcı veritabanı dosyaları en son ne zaman değişti?
stat -c '%n %y' /etc/passwd /etc/shadow /etc/group /etc/sudoers
# Giriş kayıtları
last -a | head -30 # Başarılı girişler
lastb -a | head -30 # Başarısız girişler
lastlog # Her hesabın son giriş zamanı
stat çıktısındaki değişim tarihi, sizin bilerek kullanıcı eklemediğiniz bir güne denk geliyorsa bu tek başına araştırılması gereken bir işarettir. lastlog çıktısında yıllardır kullanılmayan bir servis hesabının yakın tarihli girişi de öyle. Kullanıcı ve grup yönetiminin normal işleyişi için Linux kullanıcı ve grup yönetimi, sudo kurallarının doğru yazımı için sudo ve sudoers yapılandırması yazılarına bakabilirsiniz.
Adım 4: SSH Anahtarları ve Giriş Kayıtları#
Yeni bir kullanıcı açmak fark edilir; mevcut bir kullanıcının authorized_keys dosyasına bir satır eklemek çok daha sessizdir ve şifre değiştirseniz bile erişimi sürdürür. Bu yüzden bu adım atlanmamalıdır.
# Sistemdeki tüm authorized_keys dosyalarını bul
find / -name 'authorized_keys*' -not -path '/proc/*' -ls 2>/dev/null
# İçeriklerini gör
for h in /root /home/*; do
echo "== $h"
cat "$h/.ssh/authorized_keys" 2>/dev/null
done
Her satırın sonundaki yorum alanına bakın: kendi anahtarlarınız genellikle kullanici@makine biçiminde tanınabilir bir etiket taşır. Tanımadığınız bir etiket veya hiç etiketi olmayan bir anahtar, doğrulanması gereken bir bulgudur. Anahtarların nasıl üretilip yönetildiğini hatırlamak için SSH anahtarı nasıl oluşturulur yazısına göz atabilirsiniz.
SSH sunucusunun yapılandırmasında da değişiklik yapılmış olabilir:
# Yapılandırma ne zaman değişti?
stat -c '%y %n' /etc/ssh/sshd_config
# Etkin ayarları oku (yorumlar hariç)
sshd -T | grep -Ei 'permitrootlogin|passwordauthentication|port|authorizedkeysfile'
PermitRootLogin yes veya PasswordAuthentication yes değerleri sizin tercihiniz değilse, birisi kapıyı geri açmış olabilir.
Son olarak giriş günlüklerini okuyun. Hangi IP'lerden başarılı giriş yapılmış, bakılması gereken en net kayıt budur:
# systemd günlüğünden başarılı girişler
journalctl -u ssh --since '7 days ago' | grep 'Accepted'
# Dağıtıma göre servis adı sshd olabilir
journalctl -u sshd --since '7 days ago' | grep -E 'Accepted|Failed password' | tail -50
Günlük dosyalarının tamamen boş olması veya belirli bir tarihten öncesinin kaybolmuş olması da bir bulgudur: saldırganlar iz temizler. Günlükleri okuma ve filtreleme yöntemleri için journalctl ile log yönetimi yazısı ayrıntılı bir başvuru kaynağıdır.
Adım 5: Kalıcılık Mekanizmaları — Cron, systemd ve Başlangıç Dosyaları#
Bu adım, "süreci öldürdüm ama geri geliyor" şikâyetinin cevabıdır. Zararlının yeniden başlatılmasını sağlayan mekanizmayı bulmadan temizlik yapmış olmazsınız.
Zamanlanmış görevler:
# Her kullanıcının kişisel cron tablosu
for u in $(cut -f1 -d: /etc/passwd); do
echo "== $u"; crontab -l -u "$u" 2>/dev/null
done
# Sistem geneli cron tanımları
cat /etc/crontab
ls -la /etc/cron.d/ /etc/cron.hourly/ /etc/cron.daily/
ls -la /var/spool/cron/crontabs/ 2>/dev/null
Zararlı cron satırları genellikle tanınabilir: curl veya wget ile bir adresten betik indirip doğrudan kabuğa boru ile veren, base64 kodlanmış uzun bir dizeyi çözüp çalıştıran, ya da /tmp altındaki bir dosyayı her dakika tetikleyen satırlar. Cron söz diziminin normal hali için Linux cron görevleri yazısına bakın.
systemd tarafı:
# Çalışan servisler
systemctl list-units --type=service --state=running
# Zamanlayıcılar
systemctl list-timers --all
# Son değiştirilen birim dosyaları
ls -lat /etc/systemd/system/ /usr/lib/systemd/system/ | head -20
# Kullanıcı seviyesindeki birimler de unutulmasın
ls -la /home/*/.config/systemd/user/ 2>/dev/null
Kullanıcı seviyesindeki systemd birimleri sıkça atlanır; root yetkisi olmadan da kalıcılık sağlarlar. Birim dosyalarının yapısı ve nasıl okunduğu için systemd servis yönetimi yazısı yardımcı olur.
Diğer klasik kalıcılık noktaları:
grep -r . /etc/ld.so.preload 2>/dev/null # Kütüphane enjeksiyonu
cat /etc/rc.local 2>/dev/null
tail -5 /root/.bashrc /root/.profile /home/*/.bashrc 2>/dev/null
ls -la /etc/profile.d/
/etc/ld.so.preload dosyası normal bir sistemde ya yoktur ya da boştur. İçinde bir .so yolu varsa bu, çalışan tüm programlara kod enjekte eden bir rootkit tekniğidir ve çok ciddi bir bulgudur.
Adım 6: Değişen Dosyalar ve Paket Bütünlüğü#
Buraya kadar bulduklarınızı tamamlayan son teknik kontrol, sistem dosyalarının değişip değişmediğidir. Paket yöneticileri kurulum sırasında her dosyanın özetini saklar; bu sayede dağıtımdan gelen bir ikilinin değiştirilip değiştirilmediğini kesin olarak söyleyebilirsiniz.
# Debian/Ubuntu: paketlerden gelen dosyaların bütünlüğü
apt install -y debsums
debsums -c
# RHEL/AlmaLinux/Rocky: beklenenden farklı dosyaları listele
rpm -Va | grep -v '^\.\{8\}'
debsums -c çıktısındaki her satır, paketten geldiği halde içeriği değişmiş bir dosyadır. ps, ls, netstat, sshd gibi bir ikili bu listede çıkıyorsa güçlü bir rootkit şüphesi vardır ve bu noktadan sonra sunucudaki komutların çıktısına güvenemezsiniz.
Zaman aralığına göre değişen dosyaları taramak da işe yarar:
# Son 3 günde değişen dosyalar (sistem dizinlerinde)
find /etc /usr/bin /usr/sbin /bin /sbin -newermt '3 days ago' -type f -ls 2>/dev/null
# Yazılabilir dizinlerde çalıştırılabilir dosyalar
find /tmp /var/tmp /dev/shm -type f -executable -ls 2>/dev/null
# Beklenmeyen setuid dosyaları
find / -perm -4000 -type f -ls 2>/dev/null
Bir dosyayı silemiyorsanız veya değiştiremiyorsanız değişmez (immutable) bayrağı konmuş olabilir; bu da kasıtlı bir korumadır:
lsattr /tmp /var/tmp /etc/crontab 2>/dev/null
chattr -ia /yol/dosya # Bayrağı kaldır
rkhunter veya chkrootkit gibi araçlar hızlı bir ikinci görüş verir, ancak imza tabanlı çalıştıkları için yalancı pozitif üretmeye eğilimlidirler ve yeni bir zararlıyı kaçırabilirler. Kesin sonuç için paket bütünlüğü daha güvenilirdir. Bundan sonrası için sistem çağrısı seviyesinde izleme kurmak istiyorsanız auditd ile sistem denetimi doğru başlangıçtır.
Adım 7: Sunucu mu Ele Geçti, Yoksa Sadece Site mi?#
Bu ayrım müdahalenin ölçeğini belirlediği için önemlidir. Web uygulaması seviyesindeki bir ihlal, genellikle web sunucusu kullanıcısının (www-data, nginx, apache) yetkileriyle sınırlıdır: site dosyalarına PHP arka kapıları yazılır, sayfalara yönlendirme kodu eklenir, ama sistem dosyalarına dokunulamaz.
Ayrımı şöyle yapabilirsiniz:
| Gözlem | Sonuç |
|---|---|
Şüpheli dosyalar yalnızca site dizininde, sahibi www-data | Uygulama seviyesi ihlal |
Cron, systemd, /etc ve UID 0 kontrolleri temiz | Uygulama seviyesi ihlal |
Sistem ikilileri değişmiş, yeni root kullanıcı, ld.so.preload dolu | Sunucu seviyesi ihlal |
| Kök dizin dışında, farklı kullanıcıların dizinlerinde de bulgular | Sunucu seviyesi ihlal |
Bulgular yalnızca uygulama katmanındaysa iş çok daha yönetilebilirdir; o senaryonun tam akışı için hacklenmiş site kurtarma ve dosya tarama tarafı için malware tarama ve temizleme yazıları izlenmelidir. Sunucu seviyesinde bulgu varsa aşağıdaki müdahale sırası geçerlidir.
Bulgular Doğrulandıysa: Müdahale Sırası#
- Kanıtı dondurun. Disk snapshot'ı alın,
ss -tnp,ps auxf,crontabçıktılarını ve ilgili günlükleri sunucu dışına kopyalayın. Temizlik sırasında bunları kaybedersiniz. - Ağı kesin. Sunucuyu dışarıya kapatın; hem zararın yayılmasını hem de saldırganın iz temizlemesini durdurur.
- Kimlik bilgilerini geçersiz kılın. Tüm SSH anahtarlarını, veritabanı şifrelerini, API anahtarlarını, uygulama gizli anahtarlarını ve panel şifrelerini yenileyin. Sunucuda okunabilir durumda duran her sır ele geçmiş sayılır.
- Temizlemek yerine yeniden kurmayı tercih edin. Sunucu seviyesinde ihlal doğrulandıysa güvenilir tek yol temiz kurulumdur. Rootkit varlığında sistemin size doğru bilgi verdiğinden emin olamazsınız. Verileri geri yüklerken çalıştırılabilir dosyaları değil, yalnızca içeriği taşıyın.
- Giriş noktasını bulun. Yeniden kurulum, aynı açık kapalı değilse hiçbir işe yaramaz. En sık kapılar şunlardır: güncellenmemiş bir uygulama veya eklenti, zayıf ya da yeniden kullanılmış bir SSH şifresi, dışarıya açık bir veritabanı portu, sızmış bir yönetim paneli şifresi.
- Yeniden sertleştirin. SSH'ta şifreli girişi kapatıp anahtara geçin, kaba kuvvet için Fail2ban kurun, gereksiz portları kapatın ve otomatik güvenlik güncellemelerini etkinleştirin. Dosya izinlerini gözden geçirmek de bu aşamanın parçasıdır; başlangıç için Linux dosya izinleri yazısı yeterlidir.
- İzleme kurun. Bu olayın tekrarını erken görmek için CPU, dışa giden bağlantı ve başarısız giriş sayısı üzerinde uyarı tanımlayın. İlk sefer üç ay sürebilir; ikinci sefer üç dakikada fark edilmelidir.
Sıkça Sorulan Sorular#
CPU'nun sürekli yüzde 100 olması kesin olarak hacklendiğim anlamına gelir mi?#
Hayır, ama en sık sebeplerden biridir. Ele geçirilmiş sunucularda kripto madencileri CPU'yu tamamen doldurur ve genellikle sizin kurmadığınız, /tmp gibi dizinlerden çalışan bir süreç olarak görünür. Öte yandan yanlış yapılandırılmış bir veritabanı sorgusu, sonsuz döngüye giren bir cron görevi veya trafik artışı da aynı belirtiyi verir. Ayrımı, sürecin /proc/PID/exe yolundan ve kim tarafından başlatıldığından yaparsınız.
Şüpheli süreci hemen sonlandırmalı mıyım?#
Kalıcılık mekanizmasını bulmadan sonlandırmayın. Cron görevi, systemd birimi veya .bashrc satırı yerinde durduğu sürece süreç dakikalar içinde geri gelir ve siz sadece kanıtı kaybetmiş olursunuz. Önce sürecin yolunu, çalışma dizinini ve komut satırını kaydedin, ardından onu başlatan mekanizmayı bulun. Temizliği tek seferde, hepsini birlikte yapın.
Sunucuyu formatlamadan temizlemek mümkün mü?#
Uygulama seviyesindeki ihlallerde genellikle evet: web dizinini temiz yedekten geri yükleyip açığı kapatmak yeterli olur. Ancak sistem ikilileri değişmişse, root yetkili yeni bir hesap açılmışsa veya ld.so.preload gibi çekirdek düzeyi bir teknik kullanılmışsa temizlik güvenilir değildir. Bu durumda tek doğru yol temiz kurulum ve verilerin dikkatle taşınmasıdır.
Günlük dosyalarım boş, bu tek başına kanıt sayılır mı?#
Güçlü bir işarettir ama tek başına kesin kanıt değildir. Yanlış yapılandırılmış bir log döndürme kuralı veya dolan bir disk de günlükleri kaybettirebilir. Kanıta yaklaşmak için diğer kaynaklara bakın: last ve lastb çıktıları, dosya değişim tarihleri, paket bütünlüğü sonuçları. Birden fazla bağımsız kaynakta aynı zaman aralığına işaret eden anormallik varsa şüphe bulguya döner.
Sağlayıcımdan kötüye kullanım bildirimi aldım, ne yapmalıyım?#
Bu bildirimler genellikle sunucunuzun başkalarına saldırdığını gösterir: spam gönderimi, kaba kuvvet taraması veya DDoS trafiği. Yani ihlal büyük olasılıkla doğrudur. Önce ağ erişimini kısıtlayıp zararı durdurun, sonra bildirimdeki hedef port ve zaman damgasıyla ss ve günlük çıktılarını eşleştirin. Sağlayıcıya incelemeye başladığınızı bildirmek, hizmetin askıya alınmasını çoğu zaman önler.
İnceleme yaparken sunucudaki komutların çıktısına güvenebilir miyim?#
Rootkit varsa güvenemezsiniz; ps, ls ve netstat gibi araçlar saldırganın süreçlerini ve dosyalarını gizleyecek şekilde değiştirilmiş olabilir. Bu yüzden paket bütünlüğü kontrolü önemlidir. Şüphe sürüyorsa sunucuyu rescue moda alıp diski dışarıdan bağlayarak inceleyin: o zaman dosyaları okuyan araçlar ele geçirilmiş sistemin değil, kurtarma ortamının araçları olur.
Bu kontrolleri düzenli olarak yapmalı mıyım?#
Tamamını her hafta çalıştırmak gerekmez ama bir kısmını otomatikleştirmek çok değerlidir. Dinlenen port listesindeki değişiklik, yeni bir UID 0 hesabı, authorized_keys dosyalarındaki satır sayısı ve /etc altındaki değişiklikler basit bir betikle günlük olarak karşılaştırılabilir. Böyle bir temel çizgiye sahip olmak, bir sonraki şüphede saatler süren incelemeyi dakikalara indirir.