Saat tam 03:14’tü. Ekrandaki imleç, sanki bana bir şeyler anlatmaya çalışır gibi normalden daha hızlı yanıp sönüyordu. testCompany’nin ana veri merkezindeki bir uygulama sunucusundan gelen WAF (Web Application Firewall) alarmı telefonumun sessizliğini bozduğunda, bunun sıradan bir 'SQL Injection' denemesi olmadığını anlamıştım. Loglara baktığımda, daha önce hiçbir CVE (Common Vulnerabilities and Exposures) kaydında görmediğim, garip bir HTTP request dizisiyle karşılaştım. Payload, bilindik hiçbir imzaya uymuyordu ama sunucu 200 OK dönmekle kalmıyor, memory dump verilerini response gövdesine basıyordu. İşte o an, o soğuk gerçekle yüzleştim: Elimizde nur topu gibi bir zero-day vardı.
Siber güvenlik dünyasında zero-day, hani o filmlerdeki 'hayalet' gibidir. Kimse nerede olduğunu bilmez, kimse nasıl durdurulacağını henüz keşfetmemiştir ve en kötüsü, üreticinin bile bundan haberi yoktur. Yazılımcıların hatayı düzeltmek için 'sıfır günü' vardır, ismi de tam buradan gelir. Red Team tarafında biz bu açıkları bulmak için gecemizi gündüzümüze katarız ama savunma tarafındaki dostlarımız için bu durum tam bir kabus senaryosudur.
Bir Zero-Day Nasıl 'Kokar'?
Genelde bir saldırının zero-day olup olmadığını anlamak için 'aykırılık' (anomaly) tespiti yapmamız gerekir. Bilinen exploitler (N-day), antivirüsler veya IPS/IDS cihazları tarafından imzalar (signatures) sayesinde yakalanır. Ancak bir zero-day saldırısında imza yoktur. Sadece davranış vardır.
O gece gördüğüm payload'u biraz basitleştirerek (ve tabii ki zararsızlaştırarak) anlatayım. Saldırgan, uygulamanın kullandığı bir görüntü işleme kütüphanesindeki (hayali bir lib-image-process.so diyelim) bellek yönetim hatasını hedefliyordu.
Normal bir istek şuna benzer:
GET /process-image?url=http://example.com/logo.png
Ancak gelen istekte şöyle bir yapı vardı:
GET /process-image?url=http://127.0.0.1/A*5000 %ff%ff...
Buradaki olay, URL parametresine gönderilen aşırı uzun verinin (buffer overflow) ve ardından gelen özel hex karakterlerinin, kütüphanenin bellekteki pointer'larını kaydırarak rastgele kod çalıştırmasına (RCE) imkan tanımasıydı. Bu zafiyet henüz hiçbir yerde yayınlanmamıştı. Yani biz, karanlıkta ateş eden bir nişancıya karşı, elimizde fenerle hedefi bulmaya çalışıyorduk.
Red Team Gözüyle: Neden Zero-Day?
Bir sızma testinde veya Red Team operasyonunda genelde bilinen açıkları (misconfigurations) kullanmayı tercih ederiz. Çünkü zero-day pahalıdır, değerlidir ve bir kez kullanıldığında 'yanma' ihtimali çok yüksektir. Ancak hedefiniz gerçekten yüksek korumalı bir yapıysa (mesela testCompany gibi), o kapıyı açmak için kendi maymuncuğunuzu dövmeniz gerekir.
Bir zero-day'in anatomisi genellikle üç aşamadan oluşur:
- Discovery (Keşif): Fuzzing dediğimiz teknikle uygulamaya binlerce anlamsız veri gönderip nerede 'patladığını' buluruz.
- Weaponization (Silahlandırma): Bulduğumuz o çökme (crash) anını, bellekte kendi kodumuzu çalıştıracak bir payload haline getiririz.
- Exploitation (Sömürme): Ve sessizce içeri gireriz.
Şu sahte Python koduna bir bakın. Bu, bir API'deki mantıksal hatadan kaynaklanan ve henüz keşfedilmemiş bir 'logic bypass' zero-day örneği olabilir:
# Zafiyet barındıran (pseudo-code) API login fonksiyonu
def login_api(user_id, session_token):
# Geliştirici burada session_token'ın tipini kontrol etmeyi unutmuş
# 'True' boolean değeri gönderildiğinde bazı kütüphaneler
# bunu geçerli bir eşleşme olarak görebiliyor.
if validate_token_in_db(user_id, session_token):
return "Access Granted"
else:
return "Access Denied"
# Saldırı Payload'u (Zararsızlaştırılmış/Mock):
# curl -X POST http://example.com/api/login -d '{"user_id": "admin", "session_token": true}'
Yukarıdaki örnekte, eğer veritabanı sürücüsü veya validasyon kütüphanesi true değerini 'boş olmayan her şey geçerlidir' şeklinde yorumlarsa, şifre bilmeden içeri girebilirsiniz. İşte bu kadar basit görünüp bu kadar yıkıcı olabilirler.
Peki, Görünmeze Karşı Nasıl Savunma Yapılır?
"E Sedat abi, madem bunun yaması yok, imzası yok, biz ne yapacağız? Havlu mu atalım?" dediğinizi duyar gibiyim. Tabii ki hayır. Zero-day savunması bir teknoloji değil, bir felsefedir. Buna 'Defense-in-Depth' (Derinlemesine Savunma) diyoruz.
- Virtual Patching: Bir zero-day duyurulduğunda ama yaması henüz çıkmadığında, WAF üzerinden o saldırı paternine özel geçici kurallar yazılır. O gece bizim yaptığımız da buydu. Gelen garip hex dizilerini tespit eden bir regex kuralını anında yayına aldık.
- Behavioral Analysis (Davranışsal Analiz): EDR (Endpoint Detection and Response) araçları 'bu dosya kötü mü?' diye bakmaz. 'Bu işlem (process) neden normalde yapmadığı bir şeyi yapıyor?' diye bakar. Mesela
calc.exeneden internete çıkmaya çalışıyor? İşte bu davranış takibi, zero-day'i yakalayan en güçlü silahtır. - Least Privilege (En Az Yetki): Eğer uygulama sunucun sadece veri çekmek için yetkilendirilmişse, saldırgan bir zero-day ile içeri girse bile yanlara (lateral movement) gidemez. Kilitli bir odada mahsur kalır.
- Honeytokens: Sistemin içine sahte ve cazip veriler bırakın. Eğer kimsenin dokunmaması gereken bir veritabanı tablosuna bir 'select' atılırsa, bilin ki içeride bir yabancı var. Zero-day ile girmiş olsa bile iz bırakacaktır.
Gerçek Hayatta Hayatta Kalmak
O gece sabaha karşı 06:00 sularında saldırganın IP adreslerini bloklamış, uygulamayı izole etmiş ve kütüphanedeki o açığı geçici bir kod değişikliğiyle (monkey-patch) kapatmıştık. Yorgunduk ama keyfimiz yerindeydi. Çünkü bir siber güvenlik uzmanı için zero-day ile karşılaşmak, bir astronomun yeni bir gezegen keşfetmesi gibidir; korkutucudur ama bir o kadar da öğreticidir.
Unutmayın, hiçbir sistem %100 güvenli değildir. Önemli olan o 'sıfırıncı gün' geldiğinde ne yapacağınızı bilmektir. Loglarınızı sevin, anomali gördüğünüzde üstüne gidin ve en önemlisi, saldırgan gibi düşünmeyi asla bırakmayın. Çünkü onlar asla durmuyor.
Bir sonraki kriz anında (umarım olmaz ama siber dünyada 'eğer' değil 'ne zaman' sorusu vardır) görüşmek üzere. Kahveniz sert, firewall'unuz sağlam olsun.
