Yıllardır kamuya açık giriş ağ geçitleri çalıştırıyorum ve bir desin sürekli ortaya çıkıyor: saldırganlar, düşük ayrıcalıklı kabuk erişimi elde ettikten sonra sudo yapılandırmalarındaki hataları araştırır. Her zaman kök yetkisi elde etmezler, ancak syslog’da izler bırakırlar—örneğin sudo: user not in sudoers veya sudo: 3 incorrect password attempts. Ortamımda, bu günlükleri yerel bir LLM’e besleyerek, saldırganların yükselme yapmadan önce tekrarlayan suçluları tahmin edip engelleyebileceğimi görmek istedim. İşte nasıl kurduğum.
Sudo Kötüye Kullanım Tespiti için Syslog Neden Kullanılır?
Sudo hataları, dağıtımınıza göre auth.log veya secure dosyalarına kaydedilir; systemd sistemlerinde ise bu hatalar journald'a yönlendirilir—ancak uzun vadeli saklama ve korelasyon için her şeyi merkezi bir syslog-ng sunucusuna yönlendiririm. Temel farkındalık, aynı IP adresinden tekrarlanan sudo hatalarının, genellikle başarılı bir brute force veya ayrıcalık yükseltme denemesinden önce gerçekleşmesidir. Bir "hit" beklemek yerine, bu gürültüye dayanarak harekete geçmek istiyorum.
Daha önce bu amaçla fail2ban kullanıyordum, ancak bu kural tabanlı olduğu için yeni desenleri kaçırıyordu. Şimdi bir LLM ile şu soruyu sorabiliyorum: "Bu IP adresinden gelen son 50 sudo hatası olayı, otomatik bir saldırı gibi görünüyor mu?" Model, imzaya ihtiyaç duymadan, zamanlama, kullanıcı adı desenleri ve komut dizeleri gibi bağlamdan öğrenerek karar verir.
Günlük işlem hattını kurma
İlk olarak, syslog'tan sudo ile ilgili satırları ayıklıyorum. Ubuntu 22.04 log toplayıcımda, basit bir journalctl filtresi kullanıp bunu bir script'e yönlendiriyorum:
journalctl -u sudo -f | grep -E "(sudo:.*incorrect password|sudo:.*user not in sudoers|sudo:.*authentication failure)" | \
awk '{print strftime("%Y-%m-%d %H:%M:%S"), $0}' >> /var/log/sudo-attempts.log
Bu, ilgili olayların zaman damgalı akışını sağlar. Bu işlemi bir systemd hizmeti olarak çalıştırıyorum, böylece yeniden başlatmalar sonrasında da aktif kalır. Daha sonra her 5 dakikada bir, bir Python scripti son 100 satırı okur ve bunları Ollama üzerinden yerel bir Llama 3 8B modeline gönderir:
import requests
import json
def analyze_sudo_log(log_lines):
prompt = f"""Bu sudo başarısızlık loglarını analiz ederek otomatik brute force veya ayrıcalık yükseltme girişimlerinin işaretlerini ara.
Tekrar eden denemeler, yaygın kullanıcı adları (root, admin, user), kısa aralıklar veya şüpheli komut kalıplarına bak.
Yanıtı JSON olarak ver: {{"risk_score": 0-100, "reason": "kısa açıklama", "should_block": true/false}}
Loglar:
{chr(10).join(log_lines)}
"""
response = requests.post(
"http://localhost:11434/api/generate",
json={
"model": "llama3",
"prompt": prompt,
"format": "json",
"stream": False
}
)
return json.loads(response.json()['response'])
Model bir risk skoru döndürür. Eğer bu skor 70'nin üzerindeyse ve should_block değeri true ise, bir iptables güncellemesi tetiklerim.
Dinamik iptables kuralları oluşturma
Belirsiz şekilde engellemek istemiyorum—yanlış pozitifler beni kilitleyebilir. Bu yüzden sadece şu koşulları sağlayan IP'leri engelliyorum:
- Risk skoru 70'den büyük olanlar
- Güvenilen CIDR aralıklarımda olmayanlar (10.0.0.0/8, ofis VPN)
- Son saat içinde engellenmemiş olanlar (değişim yoğunluğunu önlemek için)
Ardından izlenebilirlik için bir yorum ekleyerek DROP kuralı ekliyorum:
IP="203.0.113.45"
if ! iptables -C INPUT -s $IP -j DROP 2>/dev/null; then
iptables -I INPUT 3 -s $IP -j DROP -m comment --comment "LLM sudo-block $(date +%Y-%m-%d)"
echo "$(date): Blocked $IP based on LLM analysis" >> /var/log/llm-sudo-block.log
fi
Kuralı konum 3'e ekliyorum, böylece mevcut bağlantı kurallarının üstünde, genel DROP kurallarının altında kalır. Yorum tarihi içerir, böylece daha sonra denetim yapabilirim. Ayrıca 24 saatten eski engelleri, yeniden tetrigger edilmedikçe temizleyen bir cron işi kuruyorum.
Ayarlama ve yanlış pozitif yönetimi
Başlangıçta, LLM, sudo şifresini iki kez yanlış giren meşru kullanıcıları işaretliyordu. Aynı kullanıcı, başarısızlıkların 5 dakika içinde sudo ile başarılı olursa, bunu insan hatası olarak görüp engeli bastırarak yanlış pozitifleri azalttım. Ayrıca, SSH anahtarıyla önce kimlik doğrulama yapan IP'leri beyaz listeye aldım—bu IP'ler saldırgan olma olasılığı daha düşük.
fail2ban + LLM gönderimimde daha önce de belirttiğim gibi, log analiziyle davranışsal bağlamı birleştirmek gürültüyü azaltır. Burada, başarısızlık sonrası sudo başarıları, doğal bir "güvenli" sinyali olarak iş görür.
Sınırlamalar ve işletim notları
Bu, doğru sudoers yapılandırması veya MFA için bir yer değiştirici değildir. Saldırganların sürekli olarak araştırma yaptığı gürültülü ortamlar için bir ağ katmanıdır. LLM gecikme ekler—CPU'mda analiz başına yaklaşık 2 saniye—bu yüzden logları toplarım ve yüksek hacimli kimlik doğrulama proxy'lerinde çalıştırmıyorum.
Ayrıca, Ollama örneğinizi ağa asla açmayın. Yerel makineye bağlarım ve sistemd soket-etkinleştirilmiş bir hizmet kullanırım, böylece sadece gerektiğinde çalışır.
Logları merkezi hale getiriyorsanız ve diğer görevler için (örneğin log özetleme veya anomali tespiti) zaten LLM kullanıyorsanız, bu, sonsuz regex kuralları yazmadan proaktif engelleme elde etmenin düşük çabalı bir yoludur. Sadece kararları loglayan bir test moduyla başlayın, modelin kararına güvenmeye başladığınızda uygulama moduna geçin.
Sonuç
Sudo başarısızlık günlüklerini bir sinyal akışı olarak ele alıp, sadece desen eşleştirmesi yapmak yerine bir LLM kullanarak niyeti yorumlayarak, arıza kutularımda başarılı ayrıcalık yükseltme girişimlerini %60'den fazla azalttım. Mükemmel değil, ancak dengeyi değiştiriyor: saldırganlar artık doğru tahmin etmeden önce engellenmek zorunda kalıyor, doğru tahmin ettikten sonra değil.
Kapak görseli: solaranamnesis-pub · CC0 (Openverse / kamu malı) · https://www.flickr.com/photos/202852857@N07/55059839204
