Ders 15 / 22
Enjeksiyon Saldırıları
Enjeksiyon sınıfının altı adımlık zincir olarak ölçülmesi: altı savunma katmanının hangi adımı kırdığı, on iki çağrı yerinin yetmiş iki adım bileşiminden kırk ikisinde denetim bulunmaması, kâğıt üzerindeki üç katmanlı kuruluşun yalnız bir çağrı yerinde tam olması, yüz doksan iki girdi-yer bileşiminden altısının altı adımı tamamlaması ve bu altısının iki çağrı yerinde toplanması.
İçindekiler
Önceki ders on risk kalemini üç sütunla andı ve en yüksek geç kırma bedelini enjeksiyon sınıfına verdi: altı adımlık bir zincir, üç adımında denetim noktası, kırılmadığında 480 kurgu kalem. Bu ders o satırın içini açar. Altı adımın her biri önkoşuluyla yazılır, altı savunma katmanı adımlara eşlenir ve aynı girdi kümesi kurgu ölçüm ağının on iki çağrı yerinden geçirilir.
Ölçümün tamamı biçimsel özellikler üzerinde yürür. Hiçbir girdi değeri yazılmaz, hiçbir sorgu metni kurulmaz ve hiçbir düzeltme örneği verilmez. Girdiler yalnız dört ikili özellikle tanımlanır: alan sözleşmesine uyuyor mu, o bağlamın ayırıcı karakter sınıfını taşıyor mu, bağlam bir geri dönüş üretiyor mu, uzunluğu büyük mü. Ölçülen şey girdinin kendisi değil, girdinin hangi adımda durduğudur.
Zincirin Altı Adımı
Enjeksiyon tek bir an değildir; altı adımın hepsinin sırayla tutmasını gerektirir.
- Giriş. Değer bir uçtan sisteme girer. Önkoşul: uç dışarıdan erişilebilir ve alan bu değeri kabul ediyor.
- Birleştirme. Değer, bir yorumlayıcıya verilecek metnin içine yazılır. Önkoşul: çağrı yeri değeri ayrı bir işlenen olarak geçirmiyor.
- Ayrıştırma. Yorumlayıcı, değerin bir bölümünü veri değil sözdizimi olarak okur. Önkoşul: değer o bağlamın ayırıcı karakter sınıfını taşıyor ve o sınıf kaçırılmamış.
- Yetki. Değişmiş ifade, çağıran kimliğin yetkisiyle çalışır. Önkoşul: o kimlik hedeflenen kalemlere erişebiliyor.
- Geri dönüş. Sonuç çağırana ulaşır. Önkoşul: yanıt gövdesi ya da hata metni ayrıntı taşıyor ve bağlam bir geri dönüş üretiyor.
- Çıkış. Elde edilen kalemler dışarıya taşınır. Önkoşul: çıkış hacmi ve hedefi üzerinde bir sınır yok.
Adımların hiçbirinin nasıl yapıldığı yazılmadı; her biri neye ihtiyaç duyduğuyla yazıldı. Savunmanın işi de tam olarak budur: bir adımın önkoşulunu ortadan kaldırmak.
TS6: adım dizisi ve bedel alanı bir modeldir; bedel, zincir o adımı kırılmadan
geçerse etkilenen kurgu kalem sayısıdır. TS7: her katman tek bir adımı kırar; koşullu
katman yalnız belirli girdi sınıfında kırar. TS8: adım 3 ancak girdi ayırıcı sınıfı
taşıyorsa, adım 5 ancak bağlam bir geri dönüş üretiyorsa tutar. TS9: aynı girdi her çağrı
yerinden ayrı geçirilir; bir yerde kırılan zincir başka bir yerde kırılmış sayılmaz.
// enj/zincir.mjs — enjeksiyon sinifinin adim dizisi ve savunma katmanlari (model). // Gercek bir sistem, gercek bir uc ve gercek bir girdi degeri yok; girdiler yalnizca // bicimsel ozellikleriyle tanimlanir. export const ADIM = [ { n: 1, ad: "giris", bedel: 0 }, { n: 2, ad: "birlestirme", bedel: 0 }, { n: 3, ad: "ayristirma", bedel: 40 }, { n: 4, ad: "yetki", bedel: 120 }, { n: 5, ad: "geri-donus", bedel: 300 }, { n: 6, ad: "cikis", bedel: 480 }, ]; export const KATMAN = [ { ad: "alan-sozlesmesi", kirar: 1, kosul: (g) => !g.sozlesme, mesru: 3 }, { ad: "ayri-islenen", kirar: 2, kosul: () => true, mesru: 0 }, { ad: "baglam-kacirma", kirar: 3, kosul: () => true, mesru: 1 }, { ad: "en-az-yetki", kirar: 4, kosul: () => true, mesru: 6 }, { ad: "sade-yanit", kirar: 5, kosul: () => true, mesru: 4 }, { ad: "cikis-siniri", kirar: 6, kosul: () => true, mesru: 9 }, ]; export const ONKOSUL = { 3: (g) => g.ayirici, 5: (g) => g.okuma }; // 16 kurgu girdi: dort ikili ozelligin butun bilesimleri. Hicbirinin degeri yazilmaz. export const GIRDI = []; for (const sozlesme of [true, false]) for (const ayirici of [true, false]) for (const okuma of [true, false]) for (const uzun of [true, false]) GIRDI.push({ no: GIRDI.length + 1, sozlesme, ayirici, okuma, uzun }); export const sinif = (g) => !g.sozlesme ? "sozlesme-disi" : g.ayirici ? "ayirici-tasiyan" : g.uzun ? "uzun-ama-uyumlu" : "duz-uyumlu"; // Kurgu olcum aginin 12 cagri yeri ve her birinde gercekten dagitilmis katmanlar. export const CAGRI = [ ["abone-portali.arama", ["alan-sozlesmesi", "ayri-islenen", "baglam-kacirma", "sade-yanit"]], ["abone-portali.fatura", ["alan-sozlesmesi", "ayri-islenen", "sade-yanit"]], ["abone-portali.itiraz", ["alan-sozlesmesi", "ayri-islenen", "baglam-kacirma"]], ["toplayici.okuma-yaz", ["ayri-islenen", "en-az-yetki"]], ["toplayici.toplu-aktarim", ["ayri-islenen", "en-az-yetki", "cikis-siniri"]], ["dogrulayici.esik", ["alan-sozlesmesi", "ayri-islenen"]], ["dogrulayici.arsiv-ara", ["alan-sozlesmesi"]], ["fatura-uretimi.donem", ["ayri-islenen", "sade-yanit", "cikis-siniri"]], ["fatura-uretimi.rapor", ["baglam-kacirma", "sade-yanit"]], ["is-emri.olustur", ["alan-sozlesmesi", "ayri-islenen", "en-az-yetki"]], ["is-emri.saha-notu", []], ["sube-ucu.sorgu", ["alan-sozlesmesi", "ayri-islenen", "baglam-kacirma", "en-az-yetki"]], ]; export const yaz = (g, ...s) => console.log(s.map((v, i) => (g[i] < 0 ? String(v).padEnd(-g[i]) : String(v).padStart(g[i]))).join(""));
// enj/olcum.mjs — ayni 16 girdi butun cagri yerlerinden gecirilir: her adimda zincir // bir denetimle mi kirildi, yoksa onkosul mu tutmadi. Rastgelelik yok. import { ADIM, KATMAN, ONKOSUL, GIRDI, sinif, CAGRI, yaz } from "./zincir.mjs"; const bedel = (n) => ADIM[n - 2]?.bedel ?? 0; // n. adimda kirilirsa birikmis kalem function yurut(girdi, dagitilan) { for (const a of ADIM) { const k = KATMAN.find((x) => x.kirar === a.n && dagitilan.includes(x.ad) && x.kosul(girdi)); if (k) return { durak: a.n, neden: "denetim", bedel: bedel(a.n) }; if (ONKOSUL[a.n] && !ONKOSUL[a.n](girdi)) return { durak: a.n, neden: "onkosul", bedel: bedel(a.n) }; } return { durak: 7, neden: "tamamlandi", bedel: ADIM[5].bedel }; } console.log(`${ADIM.length} adimlik zincir, ${KATMAN.length} katman, ` + `${CAGRI.length} cagri yeri, ${GIRDI.length} kurgu girdi\n`); const A = [-17, 9, 22, 13, 12]; console.log("1. katman-adim eslemesi"); yaz(A, "katman", "kirdigi", "kosul", "mesru bedel", "cagri yeri"); for (const k of KATMAN) yaz(A, k.ad, `${k.kirar}. adim`, k.kosul({ sozlesme: true }) ? "kosulsuz" : "girdi sinifina bagli", k.mesru, CAGRI.filter(([, d]) => d.includes(k.ad)).length); const B = [-26, 8, 14, 13, 13]; console.log("\n2. cagri yeri basina zincir"); yaz(B, "cagri yeri", "katman", "ilk kirilan", "denetimsiz", "tamamlayan"); let denetimsiz = 0; for (const [ad, d] of CAGRI) { const kirilan = ADIM.filter((a) => KATMAN.some((x) => x.kirar === a.n && d.includes(x.ad))); const kosulsuz = kirilan.filter((a) => KATMAN.find((x) => x.kirar === a.n).kosul({ sozlesme: true })); const tamam = GIRDI.filter((g) => yurut(g, d).durak === 7).length; denetimsiz += ADIM.length - kirilan.length; yaz(B, ad, d.length, kosulsuz.length ? `${kosulsuz[0].n}. adim` : "yok", ADIM.length - kirilan.length, `${tamam}/${GIRDI.length}`); } console.log(`${CAGRI.length * ADIM.length} adim-yer bilesiminin ${denetimsiz} tanesinde denetim yok`); const KAGIT = ["ayri-islenen", "baglam-kacirma", "sade-yanit"]; console.log(`kagit uzerindeki kurulus (${KAGIT.join(" + ")}) tam olan yer: ` + `${CAGRI.filter(([, d]) => KAGIT.every((k) => d.includes(k))).length}/${CAGRI.length}`); const C = [-17, 7, 15, 15, 13, 12]; console.log("\n3. girdi sinifi basina duraklar (16 girdi x 12 yer)"); yaz(C, "girdi sinifi", "girdi", "denetim durdu", "onkosul durdu", "tamamlandi", "bedel"); for (const s of [...new Set(GIRDI.map(sinif))]) { const kume = GIRDI.filter((g) => sinif(g) === s); const r = kume.flatMap((g) => CAGRI.map(([, d]) => yurut(g, d))); yaz(C, s, kume.length, r.filter((x) => x.neden === "denetim").length, r.filter((x) => x.neden === "onkosul").length, r.filter((x) => x.neden === "tamamlandi").length, r.reduce((t, x) => t + x.bedel, 0)); } const hepsi = GIRDI.flatMap((g) => CAGRI.map(([ad, d]) => ({ ad, ...yurut(g, d) }))); const tam = hepsi.filter((x) => x.neden === "tamamlandi"); console.log(`${hepsi.length} bilesimin ${tam.length} tanesi alti adimi tamamladi, ` + `hepsi su iki yerde: ${[...new Set(tam.map((x) => x.ad))].join(", ")}`); const D = [-14, 17, 16, 13]; console.log("\n4. gec kirmanin bedeli"); yaz(D, "kirilan adim", "birikmis kalem", "kiran katman", "mesru bedel"); for (const a of ADIM) { const k = KATMAN.find((x) => x.kirar === a.n); yaz(D, `${a.n}. adim`, bedel(a.n), k.ad, k.mesru); } console.log(`hic kirilmazsa ${ADIM[5].bedel} kalem; alti katmanin toplam mesru bedeli ` + `${KATMAN.reduce((t, k) => t + k.mesru, 0)} kalem/gun, ilk iki adimi kiran ikisininki ` + `${KATMAN.slice(0, 2).reduce((t, k) => t + k.mesru, 0)}`);
6 adimlik zincir, 6 katman, 12 cagri yeri, 16 kurgu girdi 1. katman-adim eslemesi katman kirdigi kosul mesru bedel cagri yeri alan-sozlesmesi 1. adim girdi sinifina bagli 3 7 ayri-islenen 2. adim kosulsuz 0 9 baglam-kacirma 3. adim kosulsuz 1 4 en-az-yetki 4. adim kosulsuz 6 4 sade-yanit 5. adim kosulsuz 4 4 cikis-siniri 6. adim kosulsuz 9 2 2. cagri yeri basina zincir cagri yeri katman ilk kirilan denetimsiz tamamlayan abone-portali.arama 4 2. adim 2 0/16 abone-portali.fatura 3 2. adim 3 0/16 abone-portali.itiraz 3 2. adim 3 0/16 toplayici.okuma-yaz 2 2. adim 4 0/16 toplayici.toplu-aktarim 3 2. adim 3 0/16 dogrulayici.esik 2 2. adim 4 0/16 dogrulayici.arsiv-ara 1 yok 5 2/16 fatura-uretimi.donem 3 2. adim 3 0/16 fatura-uretimi.rapor 2 3. adim 4 0/16 is-emri.olustur 3 2. adim 3 0/16 is-emri.saha-notu 0 yok 6 4/16 sube-ucu.sorgu 4 2. adim 2 0/16 72 adim-yer bilesiminin 42 tanesinde denetim yok kagit uzerindeki kurulus (ayri-islenen + baglam-kacirma + sade-yanit) tam olan yer: 1/12 3. girdi sinifi basina duraklar (16 girdi x 12 yer) girdi sinifi girdi denetim durdu onkosul durdu tamamlandi bedel ayirici-tasiyan 4 40 4 4 2400 uzun-ama-uyumlu 2 20 4 0 0 duz-uyumlu 2 20 4 0 0 sozlesme-disi 8 88 6 2 1200 192 bilesimin 6 tanesi alti adimi tamamladi, hepsi su iki yerde: dogrulayici.arsiv-ara, is-emri.saha-notu 4. gec kirmanin bedeli kirilan adim birikmis kalem kiran katman mesru bedel 1. adim 0 alan-sozlesmesi 3 2. adim 0 ayri-islenen 0 3. adim 0 baglam-kacirma 1 4. adim 40 en-az-yetki 6 5. adim 120 sade-yanit 4 6. adim 300 cikis-siniri 9 hic kirilmazsa 480 kalem; alti katmanin toplam mesru bedeli 23 kalem/gun, ilk iki adimi kiran ikisininki 3
Katmanın Koşulu
Birinci tablo altı katmanı tek bir sütunla ayırır: koşul. Beş katman koşulsuzdur — dağıtıldıkları yerde her girdi için aynı adımı kırarlar. Bir tanesi koşulludur: alan sözleşmesi yalnız sözleşmeyi ihlal eden girdide zinciri kırar. Sözleşmeye uyan ve ayırıcı sınıfı taşıyan bir girdi için sözleşme katmanı hiçbir adım kırmaz.
Bu ayrım pratikte en sık yanlış okunan noktadır. Sözleşme doğrulaması bir enjeksiyon savunması gibi anılır; ölçüldüğünde görülen şey, onun yalnız biçimsel olarak dışarıda kalan girdileri durdurduğudur. Meşru bir abone adının içindeki ayırıcı karakter sınıfı da, o alanın sözleşmesine uyar.
İkinci ayrım maliyet sütunundadır. İkinci adımı kıran katmanın meşru işe bedeli sıfırdır: değeri ayrı bir işlenen olarak geçirmek hiçbir meşru isteği reddetmez. Altıncı adımı kıran çıkış sınırının bedeli 9 kalem/gündür. Altı katmanın toplam bedeli 23 iken, ilk iki adımı kıran ikisinin toplam bedeli 3’tür. Erken kırmak yalnız daha az kalem kaybettirmez; kırmanın kendisi de daha ucuzdur.
Çağrı Yeri Başına Kırılma
İkinci tablo dersin asıl ölçümüdür. Sınıf tektir, zincir tektir — ama savunma çağrı yeri başına dağıtılır ve on iki yerde on iki farklı sonuç çıkar.
On iki yerin dokuzunda zincir ikinci adımda kırılıyor ve tek bir katman bunu yapıyor. Bir yerde ilk kırılma üçüncü adıma kayıyor. İki yerde koşulsuz hiçbir katman yok: orada zincir yalnız girdinin önkoşulları tutmadığında duruyor, savunma yüzünden değil. On iki çağrı yeri ile altı adımın kurduğu 72 bileşimin 42’sinde hiçbir denetim yok.
Denetimsiz bileşimlerin dağılımı da tek düze değildir. Dört katman on iki yerin dördünde ya da daha azında bulunuyor; en yaygın katman dokuz yerde. Sayı, kapsamın katman başına ölçülmesi gerektiğini gösterir: bir katmanın var olması onun her yerde var olduğu anlamına gelmez ve zincir en zayıf çağrı yerinden yürür.
Son satır kâğıt ile sahanın farkını verir. Bir önceki ders enjeksiyon zincirini “üç adımında denetim var” diye kaydetmişti; o kayıt, üç katmanın her yerde bulunduğunu varsayar. Ölçüm o kuruluşun 12 çağrı yerinin yalnız 1’inde tam olduğunu söylüyor. Sistem düzeyinde yazılan her savunma iddiası, çağrı yeri başına sayılmadan doğrulanmış sayılmaz.
Girdi Sınıfı ve Durak
Üçüncü tablo 16 girdiyi dört sınıfa ayırır ve 192 girdi-yer bileşiminin nerede durduğunu sayar. İki sütun ayrı tutulur: zinciri bir denetim mi durdurdu, yoksa girdinin önkoşulu mu tutmadı.
Ayırıcı sınıfı taşımayan girdiler üçüncü adımda kendiliğinden duruyor — hiçbir savunma iş
yapmadan. Bu, duz-uyumlu ve uzun-ama-uyumlu sınıflarının bedel sütununu sıfır yapan
şeydir. Bir savunmanın “hiçbir sorun görülmedi” demesi, çoğu zaman zincirin o girdi için
zaten önkoşulsuz olduğu anlamına gelir.
Ayırıcı sınıfı taşıyan dört girdi ise 48 bileşimin 40’ında bir denetimle durduruluyor, 4’ünde önkoşul tutmuyor ve 4’ünde zincir tamamlanıyor. Aynı dört girdi, dağıtımı eksik iki yerde 2.400 kalemlik bedeli tek başına taşıyor.
Toplam 192 bileşimin yalnız 6’sı altı adımı tamamlıyor ve altısı da aynı iki çağrı yerinde. Bu iki yerin taşıdığı bedel 2.400 ve 1.200 kalemdir. Risk kalemin kendisine değil, kalemin kaç yerde denetimsiz olduğuna bağlıdır: sınıf on iki yerde de aynıdır, sayı iki yerde toplanır.
Geç Kırmanın Bedeli
Dördüncü tablo bedeli adım adım verir. İlk üç adımda kırılan zincirin bedeli sıfırdır: ayrıştırma gerçekleşmemiştir. Dördüncü adımda kırılırsa 40, beşincide 120, altıncıda 300 kurgu kalem etkilenmiştir; hiç kırılmazsa 480.
Sıfır bedelli üç adımın anlamı, o adımlarda kırmanın karşılıksız olduğu değildir. Orada kırmak bir olayın hiç oluşmamasını sağlar; kayda düşen tek şey reddedilmiş bir istektir. Dördüncü adımdan sonra kırmak ise her zaman bir olay kaydı, bir inceleme ve bir kapsam sorusu üretir — bedel sütununun yazmadığı ikinci maliyet budur.
Bedelin sıçraması eşit değildir. Üçüncü adımdan dördüncüye geçiş 0’dan 40’a çıkar; beşinciden altıncıya geçiş 120’den 300’e. Zincirin sonuna doğru her adım bir öncekinden pahalıdır, çünkü her adım bir öncekinin elde ettiğini çoğaltır. En az yetki ile çıkış sınırı bu yüzden “geç” savunmalardır: işe yararlar, ama devreye girdiklerinde kaybın bir bölümü olmuştur.
Özet
- Enjeksiyon sınıfı altı adımlık bir zincirdir ve her adım bir önkoşula bağlıdır: erişilebilir uç, birleştiren çağrı yeri, ayırıcı sınıfı taşıyan değer, geniş yetki, ayrıntılı geri dönüş, sınırsız çıkış.
- Altı katmandan beşi koşulsuz kırar, biri koşulludur: alan sözleşmesi yalnız sözleşme dışı girdide kırar ve sözleşmeye uyup ayırıcı sınıfı taşıyan girdi için hiçbir adım kırmaz.
- İkinci adımı kıran katmanın meşru işe bedeli 0, altıncı adımı kıranınki 9 kalem/gündür; altı katmanın toplamı 23, ilk iki adımı kıran ikisinin toplamı 3’tür.
- On iki çağrı yerinin 9’unda zincir ikinci adımda kırılıyor, 1’inde üçüncüde, 2’sinde hiçbir koşulsuz katman yok. 72 adım-yer bileşiminin 42’sinde denetim bulunmuyor ve kâğıt üzerindeki üç katmanlı kuruluş 12 yerin yalnız 1’inde tam.
- 192 girdi-yer bileşiminin 6’sı altı adımı tamamlıyor ve altısı da aynı iki çağrı yerinde; bedel dördüncü adımdan itibaren 40, 120, 300 ve kırılmazsa 480 kalemdir.
Sonraki Adım
Bu dersin zincirinde değer bir yorumlayıcının metnine yazılıyordu ve yorumlayıcı sunucunun içindeydi. Aynı adım dizisi, yorumlayıcı kullanıcının tarayıcısında olduğunda başka bir biçim alır: değer sunucudan geçer, bir sayfaya yerleşir ve ayrıştırma başka bir makinede gerçekleşir. Sonraki ders bu kaymayı ölçer — üç ayrı biçimin adım sayıları neden farklıdır, bir biçimde değer sunucuya hiç uğramadığında sunucu tarafındaki katmanların kırdığı adım sayısı kaça iner ve o durumda ölçünün kırmadan tespite kayması ne anlama gelir.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.