İçeriğe atla
0 XP 0
13 dkderinleşmeyle 14 dk50 XP7 etkinlik

Enjeksiyonun kök nedeni

Bu derste
  • Enjeksiyon ailesini tek kök nedene bağlarsın: veriyle komut aynı dizgede birleşince yorumlayıcı ikisini ayıramaz ve savunma çöker.
  • Bu derste SQL, işletim sistemi komutu, şablon ve NoSQL ailesini aynı hataya bağlar; log ve hata izinden ilk belirtiyi tanırsın.

Puan bütün etkinlikleri cevaplayınca hesaba yazılır. Bu dersi tamamlayınca +50 XP alacaksın. Giriş yapmadan ilerlersen puan yalnız bu tarayıcıda durur.

Enjeksiyon, tek bir yazım hatasının değil bir tasarım kararının sonucudur. Uygulama, kullanıcıdan aldığı veriyi bir yorumlayıcıya (interpreter) gönderirken veriyle komutu aynı dizgede birleştirirse, o dizgede neyin sabit komut neyin değişken veri olduğunu ayırma işi yorumlayıcıya kalır.

Yorumlayıcı bu ayrımı yalnız söz dizimine bakarak yapar; söz dizimini de saldırgan yazabilir. Bu derste dört ayrı yorumlayıcıyı, yani SQL veritabanını, işletim sistemi kabuğunu, şablon motorunu ve NoSQL sürücüsünü tek bir kök nedene bağlarsın: veriyle komutun karışması. Ayrımın neden temizlemekten daha güçlü olduğunu, kör (blind) tekniğin ortak mantığını ve enjeksiyonun logda bıraktığı ilk izi öğrenirsin.

Veri ile komut neden karışır

Uygulama, kullanıcıdan aldığı veriyi çoğu zaman bir yorumlayıcıya gönderir. Veritabanı motoru sorguyu yorumlar, işletim sistemi kabuğu komutu çalıştırır, şablon motoru ifadeyi değerlendirir, NoSQL sürücüsü sorgu belgesini işler. Dördü de aynı sorunu taşır: önüne gelen dizgede neyin sabit komut, neyin değişken veri olduğunu kendi başına ayıramaz. Uygulama, kullanıcı girdisini bu dizgenin tam ortasına yapıştırırsa, sınırı artık saldırgan çizer.

Tek bir tırnak işareti, noktalı virgül ya da süslü parantez, veri alanının sınırını taşırır. Yorumlayıcı taşan kısmı yeni bir komut sanır ve onu çalıştırır. SQL enjeksiyonu, işletim sistemi komutu enjeksiyonu, şablon enjeksiyonu (SSTI) ve NoSQL enjeksiyonu bu yüzden ayrı açıklar değil, aynı hatanın dört farklı yorumlayıcıdaki görünümüdür.

Bir yorumlayıcı, aldığı dizeyi önce ayrıştırır (parse): dizeyi jetonlara böler, bir söz dizimi ağacı kurar, sonra bu ağacı çalıştırır. Ağaçta bazı düğümler komuttur (SELECT, WHERE, boru işareti), bazıları veridir (aranan ad, sayı). Asıl sorun ikinci adımda gizlidir. Uygulama dizeyi metin birleştirmeyle kurduğunda veri ile komut aynı düz metne iner ve aradaki sınır kaybolur.

Yorumlayıcı ağacı kurarken sınırı yeniden çizmek zorunda kalır, bunu da yalnız karakterlere bakarak yapar. Kullanıcı doğru karakteri araya sokarsa kendi verisini yeni bir komut düğümüne dönüştürür. Parametreli çağrı bu sınırı önceden çizer: komut ağacı veri gelmeden kurulur, veri yalnız hazır bir düğüme değer olarak oturur.

Aynı karakter dizisi bir yerde veri, başka yerde komuttur. Kullanıcının yazdığı tek tırnak, adının içinde masum bir kesme işaretiyken, sorgu metnine girince bir dizeyi kapatan söz dizimi işareti olur. Yorumlayıcı niyeti bilmez, yalnız söz dizimini görür.

Enjeksiyonun sinsiliği buradadır: zararlı olan karakter değil, karakterin yanlış katmanda yorumlanmasıdır. Bu yüzden savunmayı karaktere değil, sınırı kimin çizdiğine kurarsın; sınırı yorumlayıcının tahminine bırakmaz, önceden kendin belirlersin.

İstemcitarayıcı, JavaScriptUygulamayönlendirme, iş kuralıŞablon motoruçıktı üretimiVeri katmanıSQL, dosya
Bir web uygulamasının katmanları. Girdi her katmanda ayrı bir yorumlayıcıya iner; enjeksiyon kökü her birinde aynıdır.

Etkinlik 1 / 7

Her örneği, veri ile komutun karıştığı yorumlayıcıya göre ayır.

Önce bir seçeneğe, sonra aşağıdaki uygun kutuya bas. İstersen seçeneği kutuya sürükleyip bırak. Yerini değiştirmek için aynı işlemi tekrarla.

0/4 seçenek yerleşti.

Ayırmak mı, temizlemek mi

İki savunma yolu var. Biri veriyi temizlemek (sanitization): tehlikeli görünen karakterleri silmek ya da kaçırmak. Öteki veriyi komuttan ayırmak: veriyi ayrı bir kanaldan, hazır bir veri düğümü olarak geçirmek. İkisi aynı güvence düzeyinde değildir.

Temizleme, tehlikeli karakterlerin listesini önceden bilmeni ister; bu liste her zaman eksik kalır. Tek tırnağı silersin, saldırgan onaltılık kodlamayla ya da çift kodlamayla gelir.

Bir yorumlayıcıda zararsız olan karakter başka bir sürümde anlam kazanır. Ayırma ise karakterlere hiç bakmaz: veri, söz dizimine ait olmayan bir kutuya konur ve içindeki hiçbir karakter komut olamaz. OWASP, A05 Enjeksiyon başlığında bu ilkeyi açıkça söyler: enjeksiyonu önlemenin en iyi yolu veriyi komut ve sorgulardan ayrı tutmaktır.

Girdi doğrulama bu ayrımın yerine geçmez, yanına eklenir. Doğru yöntem izin listesidir (allowlist): kabul edilen değerleri sen tanımlarsın, geri kalan her şey reddedilir. Kara liste (denylist) tersini dener ve hep açık kalır; ayrıca O'Brian gibi geçerli girdileri de yanlışlıkla engeller.

Doğrulamadan önce girdiyi tek bir kanonik biçime indirmelisin (canonicalization): aynı karakterin farklı kodlamaları tek biçime çevrilmezse, izin listesi bir biçimi görür, yorumlayıcı başka biçimi çalıştırır. OWASP girdi doğrulamayı iki katmanda tanımlar: sözdizimsel doğrulama biçimi denetler (girdi geçerli bir tarih mi), anlamsal doğrulama değerin iş kuralında anlamlı olduğunu denetler (başlangıç tarihi bitişten önce mi). Girdi doğrulama, XSS ve SQL enjeksiyonunun birincil savunması değildir; ayrımın yanında ikinci bir katmandır.

Kara listenin neden dayanıksız kaldığını bir örnekle gör. Diyelim tek tırnağı silen bir süzgeç var. Saldırgan tırnağı doğrudan yazmaz; karakterin yüzde kodlu ya da onaltılık gösterimini yollar.

Süzgeç bu biçimi tanımaz, ama bir alt katman kodu çözünce tırnak geri gelir. Bazen çift kodlama yeter: karakteri iki kez kodlarsın, ilk çözme süzgeçten sonra çalışır ve tırnak tam da yorumlayıcının önünde ortaya çıkar. İzin listesi bu oyunu bitirir, çünkü tanımadığı hiçbir biçimi kabul etmez; onaylanan değerler dışında her şey reddedilir.

Etkinlik 2 / 7

Bir geliştirici, girdideki tek tırnak ve noktalı virgülü siliyor ve enjeksiyonun kapandığını düşünüyor. Bu yaklaşımın asıl zayıflığı nedir?

Logda ilk iz

Enjeksiyon denemesi çoğu zaman iz bırakır. Uygulama beklemediği bir söz dizimiyle karşılaşınca hatasını loglar, bazen doğrudan ekrana da basar. Veritabanı sürücüsünün ürettiği bir söz dizimi hatası, kabuğun komut bulunamadı çıktısı, şablon motorunun fırlattığı ayrıştırma istisnası aynı örüntüyü taşır.

Uygulama beklediği veriyi değil, saldırganın yazdığı söz dizimini görmüştür. İkinci ve daha sessiz iz, isteğin kendi deseninde saklıdır: aynı uca art arda gelen, yalnız birkaç karakteri değişen çok sayıda istek.

Kaynaklarsunucu, uçToplayıcıagentSIEMnormalleştirmeKuraltespitAlarmanalist
Loglardan alarma giden hat. Enjeksiyon izleri toplama ve kural aşamasında yakalanır.

Şema, ham isteğin nasıl alarma dönüştüğünü gösterir. Kaynaklar ham metni toplar, kural bu metindeki söz dizimi anomalisini arar, eşleşme alarma dönüşür. Savunmacı bu izi tanırsa saldırının hangi ailede olduğunu, isteğin gövdesine hiç bakmadan sırf logdan tahmin eder. Kör enjeksiyon ise hata mesajı basmayan uygulamalarda bile çalışır.

Saldırgan doğru sorguyu yollarsa sayfa normal döner, yanlış sorguyu yollarsa sayfa boş kalır ya da yanıt gecikir. Bu ikili fark, veriyi harf harf dışarı çıkarmaya yeter. Sıradan bir kullanıcı aynı formu yüzlerce kez ufak varyasyonlarla doldurmaz; bu tekrar deseni otomatik bir aracın çalıştığını gösterir.

Her ailenin bıraktığı hata farklı görünür ama aynı şeyi söyler. SQL sürücüsü bir söz dizimi hatası döner ve çoğu zaman sorgunun bir parçasını mesaja koyar. Kabuk, komut bulunamadı der. Şablon motoru bir ayrıştırma istisnası fırlatır ve motorun adını verir.

NoSQL sürücüsü beklenmeyen bir tür ya da operatör hatası basar. Savunmacı bu imzaları tanırsa, saldırının hangi yorumlayıcıyı hedeflediğini isteğin gövdesine bakmadan anlar. Hata metnini kullanıcıya göstermemek bu bilgiyi saldırgandan saklar, ama savunmacının kendi loglarında tutması gerekir.

Etkinlik 3 / 7

Doğru mu, yanlış mı?

Veritabanı sürücüsünün ürettiği bir söz dizimi hatası, enjeksiyon denemesinin tek olası kanıtıdır.

Bu ikili farkı loglarda da görürsün. Söz dizimi hatası açık bir belirti verir. Daha sessiz ve güçlü sinyal isteklerin desenidir: aynı uca gelen, yalnız birkaç karakteri değişen art arda istekler otomatik bir denemeyi ele verir.

Tek bir söz dizimi hatası bir yazım kazası olabilir; art arda gelen, yalnız birkaç karakteri değişen istekler ise niyeti gösterir ve arkada otomatik bir aracın çalıştığını işaret eder. Aşağıdaki kayıtta hem hatayı hem de bu tekrar desenini ara.

Etkinlik 4 / 7

Uygulama kaydında enjeksiyon denemesine ait satırları işaretle.

Şüpheli satırlara tıkla. Birden fazla olabilir.

WAF: dıştaki ek katman

Uygulamanın önüne bir web uygulama güvenlik duvarı (WAF) koyabilirsin. WAF, gelen isteği uygulamaya ulaşmadan önce bir kural kümesiyle tarar. OWASP Core Rule Set (CRS), enjeksiyon söz dizimini yakalayan açık kaynaklı kural kümesidir.

SQL enjeksiyonu için istekteki söz dizimini libinjection kütüphanesiyle sınar. Komut ve şablon enjeksiyonu için ayrı kural aileleri çalıştırır. CRS anomali puanı toplar: her eşleşen kural önem derecesine göre puan ekler.

Kritik bir kural 5, hata 4, uyarı 3, bilgi 2 puandır. Toplam, önerilen giriş eşiği olan 5 puanı geçince istek engellenir. Tek bir tırnak ya da bir UNION SELECT çoğu zaman kritik bir kurala takılır ve tek başına eşiği aşar.

Etkinlik 5 / 7

Bir ekip enjeksiyon riskini yalnız WAF ile kapatmayı, kodu hiç değiştirmemeyi öneriyor. En doğru değerlendirme hangisidir?

Enjeksiyon savunmasını tek bir teknik değil, üst üste binen katmanlar kurar. Parametreli sorgu kök nedeni kapatır, izin listesi parametre bağlanamayan yerleri korur, en az yetkili hesap etkiyi daraltır, WAF ise önde bir güvenlik ağı gerer. Biri aşılsa bile öteki devrede kalır.

Tek bir katmana güvenmek, o katman aşıldığında bütün savunmayı sıfırlar; katmanları üst üste bindirmenin nedeni budur. Aşağıda bu dört katmanı işleriyle eşle.

Etkinlik 6 / 7

Her savunma katmanını yaptığı işle eşle.

Soldan bir tane seç, sağdan eşini seç. Kullanılmış bir seçeneği yeniden seçersen yeni öğeye taşınır.
Derinleş:CWE-74: tek aile, birçok yorumlayıcı

MITRE, enjeksiyonu CWE-74 altında toplar: alt bileşene giden çıktıda özel karakterlerin yanlış etkisizleştirilmesi. Bu kök sınıfın altında SQL enjeksiyonu (CWE-89), işletim sistemi komutu enjeksiyonu (CWE-78), XSS (CWE-79), şablon motoru enjeksiyonu (CWE-1336), veri sorgu mantığı enjeksiyonu (CWE-943), LDAP enjeksiyonu (CWE-90) ve XPath enjeksiyonu (CWE-643) durur. Hepsi aynı cümleyi başka kelimelerle söyler: veri, alt bileşenin söz dizimine karışmıştır.

OWASP Top 10 2025'te Enjeksiyon A05 sırasında yer alır ve 37 farklı CWE'yi bu başlıkta toplar. Kategoride 62 binden çok CVE, en yüksek görülme oranı yüzde 13,77 kayıtlıdır. XSS tek başına 30 binden, SQL enjeksiyonu 14 binden çok CVE taşır. Tek kök nedeni anlamak, bu uzun listeyi tek bir zihinsel modele indirir.

Aynı kök, dört yorumlayıcı

Bu dersin geri kalanı her aileyi ayrı ayrı çözer: SQL enjeksiyonunda parametreli sorgu, işletim sistemi komutunda güvenli çağrı API'si, şablon ve NoSQL'de bağlama göre kodlama. Ortak ilke şimdiden nettir: veriyi komuttan ayırmak, veriyi temizlemekten çok daha güvenilirdir. Karakter süzme, saldırganın bulacağı yeni bir kodlamayla neredeyse her zaman aşılır.

Şimdi bu kök nedeni başka bir yorumlayıcıya taşı. Altay Kargo'nun rapor motoru, kullanıcının seçtiği tarih aralığını doğrudan bir kabuk ifadesine ekleyerek PDF üretiyor. Tarih alanına noktalı virgül ve ikinci bir komut eklenirse, aynı kök neden burada da tekrarlanır. Bu kalıbı bir kez gördüğünde her yerde tanırsın.

Bir arama kutusu, bir dosya adı, bir e-posta şablonu, bir sıralama parametresi, hepsi aynı soruyu sorar: bu girdi bir yorumlayıcıya metin olarak mı gidiyor? Cevap evetse, veriyi koddan ayırmadığın sürece açık oradadır. Yorumlayıcıyı ve girdinin ona nasıl ulaştığını bilmek, dört ailenin de savunmasını tek bir alışkanlığa indirir.

Etkinlik 7 / 7

Rapor motoru, kullanıcının seçtiği tarih aralığını doğrudan bir kabuk ifadesine ekliyor. Veri ile ____ aynı dizgede birleşince yorumlayıcı ikisini ayıramaz.

Derinleş:Enjeksiyonun kısa tarihi

SQL enjeksiyonunun ilk kamuya açık anlatımı Aralık 1998'e uzanır. Phrack dergisinin 54. sayısında rain.forest.puppy takma adlı araştırmacı, NT Web Technology Vulnerabilities yazısında SQL sunucusuna nasıl ek komut iliştirilebildiğini gösterdi ve savunmayı da yazdı: web kullanıcısından gelen her dizgeyi tırnak içine al, tek tırnakları çiftle. Aradan geçen çeyrek yüzyılda kök neden değişmedi, yalnız yorumlayıcı çeşitlendi.

2014'te ShellShock (CVE-2014-6271), Bash kabuğunun ortam değişkenlerini işleyişindeki bir açıkla komut enjeksiyonunu web sunucularına taşıdı. 2016'da ImageTragick (CVE-2016-3714), resim işleyen bir kütüphanede kabuk metakarakterleriyle komut çalıştırdı. 2023'te bir dosya transfer ürününde bulunan SQL enjeksiyonu (CVE-2023-34362) geniş çaplı veri sızıntılarına yol açtı. Aynı kök neden, her on yılda yeni bir kılıkla geri döner.

Bu derste bir hata mı gördün? Bildir