Önceki derslerimizde, bir verinin kaynaktan (source) hedefe (sink) olan yolculuğunu hem açık (explicit) hem de örtük (implicit) kanallar üzerinden takip etme becerisi kazandık. Artık verinin bir sistem içinde nasıl hareket ettiğini ve nerelere "ışınlanabildiğini" biliyoruz. Ancak, bir güvenlik analistinin görevi verinin yolunu çizmekle bitmez. Yol boyunca veriye ne olduğu, hangi dönüşümlerden geçtiği ve bu dönüşümlerin veriyi gerçekten "güvenli" kılıp kılmadığı, en kritik zafiyetlerin gizlendiği yerdir.
Bu derste, veri akış analizinin en önemli aşamasına odaklanacağız: temizleme (sanitization), kodlama (encoding) ve doğrulama (validation) mekanizmalarının etkinliğini değerlendirmek. Öğrenme hedefimiz, kirli bir veriye uygulanan bir güvenlik kontrolünün, verinin ulaşacağı hedef (sink) için bağlamsal olarak doğru ve yeterli olup olmadığını sorgulamaktır. Bir temizleyicinin varlığı, bir zafiyetin olmadığı anlamına gelmez. Uzman bir göz, bu temizleyicinin bağlamını yanlış anladığını veya kolayca atlatılabileceğini fark edebilir.
"Temiz" Veri Yanılsaması: Bağlamsal Doğruluk Prensibi
Güvenli kodlamanın temel prensiplerinden biri, dışarıdan gelen her veriye şüpheyle yaklaşmak ve onu kullanmadan önce doğrulamaktır. Ancak "doğrulama" tek bir eylem değildir; verinin kullanılacağı bağlama göre şekil değiştiren karmaşık bir süreçtir. Örneğin, bir kullanıcı adını HTML içinde göstermek için gereken temizleme (HTML entity encoding) ile aynı adı bir SQL sorgusunda kullanmak için gereken temizleme (parametreli sorgu veya titiz bir escaping) tamamen farklıdır.
Bu temel prensipleri ve en iyi uygulamaları özetleyen bir makaleyi inceleyerek konuya giriş yapalım.
OWASP GÜVENLİ KODLAMA UYGULAMALARI - Barış İNCEİŞÇİ
Bu makale, girdi doğrulama ve çıktı kodlamanın temel prensiplerini OWASP standartları çerçevesinde özetlemektedir. Özellikle "beyaz liste" yaklaşımı ve "bağlama göre kodlama" kavramları, dersimizin temelini oluşturacaktır.
Lütfen makalenin Girdi Doğrulama (Input Validation) bölümünü okuyun. Burada vurgulanan beyaz liste (whitelist) yaklaşımının, neden kara liste (blacklist) yaklaşımından daha üstün olduğuna dikkat edin. Ardından, Çıktı Kodlama (Output Encoding) bölümünü inceleyin. Özellikle şu cümleye odaklanın: "Burada dikkat edilmesi gereken konu, verinin nereye basılacağına göre uygun encoding yönteminin uygulanmasıdır. XSS ataklarına çözüm sağlanabilmesi için context’e göre encode işlemi uygulanmalıdır." Bu, dersimizin ana fikrini mükemmel bir şekilde özetlemektedir.
Makalenin de vurguladığı gibi, en büyük hatalar ya hiç doğrulama yapmamaktan ya da yanlış bağlamda doğrulama yapmaktan kaynaklanır. Şimdi bu "yanlış bağlam" hatalarını gerçek dünya örnekleriyle inceleyelim.
Vaka Analizi 1: Yol Normalleştirme ve Directory Traversal
Bağlamsal yetersizliğin en klasik ve öğretici örneklerinden biri Directory Traversal zafiyetidir. Geliştirici, genellikle kullanıcıdan gelen dosya adındaki tehlikeli karakter dizisi olan ../ ifadesini filtreleyerek bir "kara liste" oluşturur ve sorunu çözdüğünü düşünür. Ancak bu filtre, verinin geçtiği işlem hattını ve hedef sistemin (dosya sistemi) veriyi nasıl yorumladığını hesaba katmadığı için kolayca atlatılabilir.
Bu zafiyetin nasıl atlatıldığını ve doğru korunma yöntemlerinin ne olduğunu inceleyen kapsamlı bir makaleye göz atalım.
Directory Traversal - Siber Güvenlik Web TR
Bu makale, Directory Traversal zafiyetinin ardındaki temel mantığı ve özellikle basit filtrelerin nasıl atlatıldığını detaylı bir şekilde açıklamaktadır. Bu, "işlem sırası" (order of operations) ve "kurallı hale getirme" (canonicalization) kavramlarının önemini anlamak için mükemmel bir örnektir.
Makalenin bu bölümünü dikkatle okuyun. URL kodlaması (%2e%2e%2f), çift URL kodlaması (%252e%252e%252f) ve diğer tekniklerin nasıl çalıştığına odaklanın. Bu bypass'ların temel nedeni, uygulamanın güvenlik kontrolünü yaptığı an ile web sunucusunun veya framework'ün bu veriyi çözdüğü (decode) an arasındaki uyumsuzluktur. Güvenlik filtresi kodlanmış (encoded) veriyi görürken, dosya sistemi API'ı (sink) çözülmüş (decoded) veriyi görür. Şimdi, doğru çözümün nasıl olması gerektiğini incelemek için korunma yöntemleri bölümünü okuyun. Özellikle 3. Dosya Yolunu Normalize Edin ve Kontrol Edin başlığı altındaki öneri kritiktir. Burada bahsedilen normalize() veya realpath() gibi fonksiyonlar, bir dosya yolunu en basit, mutlak ve "kurallı" (canonical) formuna dönüştürür. Önce kurallı hale getir, sonra kontrol et prensibi, bu tür zafiyetleri önlemenin tek güvenilir yoludur. Yanlış sıra, yani kontrol et -> kullan (ve kullanım sırasında çöz), zafiyetin temel nedenidir.
Bu vaka, bize kritik bir ders veriyor: Güvenlik kontrolleri, verinin ham hali üzerinde değil, sink tarafından yorumlanacak nihai hali üzerinde yapılmalıdır. Veriyi, herhangi bir kontrol yapmadan önce kurallı hale getirmek (canonicalization), bu uyumu sağlamanın en temel yoludur.
Vaka Analizi 2: Yanlış Escaping ve SQL Enjeksiyonu
Bağlamsal hata, sadece kodlama (encoding) farklılıklarından değil, aynı zamanda hedef sistemin kendine özgü kurallarını bilmemekten de kaynaklanabilir. Bir veritabanı için doğru olan bir kaçış (escaping) karakteri, bir başkası için anlamsız veya daha kötüsü, bir zafiyete yol açan bir karakter olabilir.
Önceki derste incelediğimiz Mehmet Dursun İnce'nin PostHog analizinde, bu durumun ileri seviye bir örneğini görmüştük. ClickHouse servisindeki SQL enjeksiyonu, tam olarak bu tür bir bağlamsal hatadan kaynaklanıyordu.
Bir Hacker’ın Günlüğü: Gerçek Bir ‘Product Security’ Hikâyesi - Mehmet Dursun İnce - Meetup #58
Bu sunumda, ClickHouse'un PostgreSQL veritabanıyla iletişim kurarken kullandığı sorgu oluşturma mekanizmasındaki kritik bir hatayı tekrar inceleyeceğiz. Bu, bir temizleme mekanizmasnın hedef teknolojiye (sink) özgü kuralları göz ardı ettiğinde nasıl başarısız olduğunun mükemmel bir örneğidir.
Lütfen bu bölümü tekrar dikkatle izleyin. Araştırmacı, kullanıcıdan gelen tablo adının postog_table sorguya nasıl eklendiğini analiz ediyor. Geliştiricinin, tek tırnak karakterini \ (ters taksim) ile escape ederek SQL enjeksiyonunu önlemeye çalıştığını görüyoruz. Bu, birçok senaryoda işe yarayabilecek bir yöntemdir. Ancak, araştırmacının vurguladığı gibi, hedef veritabanı PostgreSQL'dir. PostgreSQL, varsayılan olarak \ karakterini bir escape karakteri olarak yorumlamaz; bunun yerine, tek tırnağı escape etmek için başka bir tek tırnak ('') kullanılmasını bekler. Kritik Çıkarım: Geliştiricinin yazdığı sanitizer, MySQL veya başka bir veritabanı bağlamında "doğru" olabilirdi, ancak hedef sink olan PostgreSQL bağlamında tamamen yanlıştı. Bu, kod review sırasında sadece bir "escape" fonksiyonunun varlığını kontrol etmenin neden yetersiz olduğunu gösterir. Fonksiyonun, hedef sink'in spesifik lehçesi ve kuralları için doğru implemente edilip edilmediğini doğrulamak zorundasınız.
Kritik Çıkarım: Geliştiricinin yazdığı sanitizer, MySQL veya başka bir veritabanı bağlamında "doğru" olabilirdi, ancak hedef sink olan PostgreSQL bağlamında tamamen yanlıştı. Bu, kod review sırasında sadece bir "escape" fonksiyonunun varlığını kontrol etmenin neden yetersiz olduğunu gösterir. Fonksiyonun, hedef sink'in spesifik lehçesi ve kuralları için doğru implemente edilip edilmediğini doğrulamak zorundasınız.
Vaka Analizi 3: Eksik Doğrulama Mantığı ve SSRF
Bazen bağlamsal hata, kodlama veya escaping'den ziyade, doğrulama mantığının kendisinin, gerçek dünya senaryolarının karmaşıklığını tam olarak kavramamasından kaynaklanır. Doğrulayıcı, bir girdinin alabileceği tüm olası formları veya ağ protokollerinin tüm nüanslarını hesaba katmayan naif bir model üzerine kurulmuş olabilir.
Yine PostHog analizinden SSRF zafiyetinin bypass edilme süreci, bu duruma harika bir örnektir.
Bir Hacker’ın Günlüğü: Gerçek Bir ‘Product Security’ Hikâyesi - Mehmet Dursun İnce - Meetup #58
PostHog'daki SSRF zafiyetini engellemek için yazılan is_private kontrolünün nasıl atlatıldığını tekrar inceleyelim. Bu, bir doğrulama mantığının, modellediği bağlam (IP ağları ve DNS) hakkında eksik varsayımlara sahip olmasının sonuçlarını gösterir.
Lütfen videonun bu bölümünü izleyin. Araştırmacı, is_private fonksiyonunun 127.0.0.1 gibi bilinen özel IP aralıklarını engellediğini, ancak saldırganların bu kontrolü nasıl atlatabileceğini açıklıyor: IPv6-to-IPv4 Mapping: Bir saldırgan, 127.0.0.1'e karşılık gelen özel bir IPv6 adresi (::ffff:127.0.0.1) kullanarak, Python'un default kütüphanesinin bu adresi "private" olarak algılamamasını sağlayabilir. DNS Rebinding: Saldırgan, kontrol anında (time-of-check) herkese açık bir IP döndüren, ancak kullanım anında (time-of-use) 127.0.0.1'e dönen bir DNS kaydı kullanabilir.
Kritik Çıkarım: Buradaki is_private doğrulayıcısı, "yerel bir adrese erişimi engelle" görevini yerine getirmek için çok basit bir model kullanmıştır. Bağlam, yani "bir alan adının yerel bir adresi işaret etme yolları", doğrulayıcının varsaydığından çok daha geniştir. Validator, IPv6 gösterimleri, TTL'i düşük DNS kayıtları gibi ağ protokollerinin standart özelliklerini hesaba katmamıştır. Bu, doğrulama mantığının bağlamı eksik anlamasının klasik bir örneğidir.
Sentez: Güvenli Temizleme İçin Bir Analistin Kontrol Listesi
Bu vakalardan yola çıkarak, bir kod analisti olarak temizleme ve doğrulama mekanizmalarını incelerken kendinize sormanız gereken soruları bir kontrol listesi haline getirebiliriz:
-
Sink'i Tanımla: Bu veri nihai olarak nereye gidiyor?
- Bir HTML belgesinin gövdesi mi? (
<p>...</p>) - Bir HTML etiketinin özelliği mi? (
<a href="...">veya<script src="...">) - Bir JavaScript değişkeni mi? (
var name = "...";) - Bir SQL sorgusu mu?
- Bir dosya sistemi yolu mu?
- Bir işletim sistemi komutu mu?
- Bir HTML belgesinin gövdesi mi? (
-
Sink'in Parser'ını Anla: Bu sink, veriyi nasıl yorumlar?
- Hangi karakterler özel anlam taşır? (
<,>,&,',"SQL'de,/,\dosya sisteminde vb.) - Hangi kodlama (encoding) veya kaçış (escaping) kuralları geçerlidir? (Örn: PostgreSQL'de
'', MySQL'de\'vb.) - Veri, sink'e ulaşmadan önce hangi katmanlar tarafından çözülür? (Web sunucusu, framework, uygulama kodu vb.)
- Hangi karakterler özel anlam taşır? (
-
Temizleme/Doğrulama Mantığını Bul: Kodun hangi bölümü bu veriyi "temizlemeye" veya kontrol etmeye çalışıyor?
- Bir kütüphane fonksiyonu mu, yoksa özel yazılmış bir kod mu?
- Kara liste mi kullanıyor, beyaz liste mi?
-
Sıralamayı Kontrol Et (Order of Operations):
- Temizleme, herhangi bir kod çözme (decoding) veya normalleştirme işleminden önce mi, sonra mı yapılıyor?
- Doğru Sıra:
Girdi -> Decode -> Canonicalize -> Validate -> Use - Yanlış Sıra:
Girdi -> Validate -> Decode/Use(Directory Traversal örneğinde olduğu gibi)
-
Varsayımları Sorgula:
- Doğrulama mantığı, verinin formatı, kaynağı veya geçtiği yol hakkında hangi örtük varsayımlarda bulunuyor? (Örn: "Bu URL zaten test edildi", "IP adresi sadece v4 formatında gelir", "Kullanıcı adı özel karakter içermez.")
- Bu varsayımlar çökertilebilir mi?
Sonuç
Bu derste, veri akışı analizinde bir adım daha derine inerek, veriye uygulanan dönüşümlerin etkinliğini sorgulamayı öğrendik. Gördük ki, bir temizleme fonksiyonunun varlığı tek başına yeterli değildir; asıl önemli olan, bu fonksiyonun verinin kullanılacağı hedefin bağlamına tam olarak uymasıdır.
Temel Çıkarımlar:
- Bağlam Her Şeydir: Bir güvenlik kontrolünün etkinliği, uygulandığı bağlama sıkı sıkıya bağlıdır. HTML için çalışan bir kodlama, SQL için felaket olabilir.
- İşlem Sırası Kritiktir: Veriyi kurallı hale getirmeden (canonicalize) veya çözmeden (decode) önce doğrulamak, bypass'lara davetiye çıkarmaktır. Doğru sıra
Decode -> Canonicalize -> Validateşeklindedir. - Sink'in Uzmanı Olun: Etkili bir kod analizi, sadece kodu değil, kodun etkileşimde bulunduğu hedef sistemlerin (veritabanları, dosya sistemleri, tarayıcılar) davranışlarını ve parser kurallarını da derinlemesine anlamayı gerektirir.
- Kara Listeler Kırılgandır:
../,<script>,SELECTgibi "kötü" ifadeleri engellemeye dayalı kara listeler, yeni kodlama ve bypass teknikleri karşısında neredeyse her zaman başarısız olur. Güvenli yaklaşım, sadece beklenen ve izin verilen girdileri kabul eden beyaz listelerdir.
Artık bir verinin kaynaktan hedefe yolculuğunu takip edebiliyor ve bu yolculuk sırasında geçirilen "sağlık kontrollerinin" gerçekten işe yarayıp yaramadığını analiz edebiliyoruz.
Bir sonraki dersimizde, analiz kapsamımızı genişleteceğiz. Veriyi tek bir uygulama içinde değil, katmanlar arasında (frontend, API, backend, veritabanı) takip ederek modern, çok katmanlı mimarilerde ortaya çıkan güven sınırı ihlallerini nasıl tespit edeceğimizi inceleyeceğiz.