---
title: 'Siteler Arası Betik Çalıştırma'
source: 'https://academia.sh/tr/kurslar/saldiri-teknikleri/siteler-arasi-betik-calistirma'
course: 'Saldırı Teknikleri ve Tehdit Ortamı'
language: tr
updated: '2026-08-17T18:08:33+00:00'
license: 'CC BY-SA 4.0'
---

# Siteler Arası Betik Çalıştırma

Üç biçimin ayrı adım dizisi olarak ölçülmesi: yansıyan beş, saklı altı, belge nesnesi tabanlı dört adım; sunucu tarafındaki üç katmanın belge nesnesi tabanlı biçimde kırdığı adım sayısının sıfır olması, sekiz sayfada yirmi dört bileşimin üçünde hiçbir halkanın kırılamaması, yalnız son adımda kırılan yedi bileşimin günlük yüz doksan oturumluk bedeli ve tarayıcı tarafındaki tek katmanın üç biçimi birden kapatması.

Önceki dersin zincirinde yorumlayıcı sunucunun içindeydi ve altı adımın üçü sunucuda
geçiyordu. Bu ders aynı adım dizisini yorumlayıcı **kullanıcının tarayıcısında** olduğunda
ölçer. Değişen tek şey ayrıştırmanın nerede yapıldığıdır; sonuç, zincirin uzunluğunun ve
kırılabilen halkanın üç ayrı biçimde üç ayrı yere düşmesidir.

Üç biçim ayrılır: değerin aynı yanıtta geri döndüğü **yansıyan** biçim, değerin önce depoya
yazılıp sonra her görüntüleyene sunulduğu **saklı** biçim ve değerin sunucuya hiç uğramadığı
**belge nesnesi tabanlı** biçim. Ölçüm boyunca hiçbir betik gövdesi, hiçbir değer ve hiçbir
sayfa kaynağı yazılmaz; biçimler yalnız adım dizileriyle anılır.

## Üç Adım Dizisi

**Yansıyan biçim, beş adım.** (1) Değer bir istek alanında uca ulaşır — önkoşul: uç o alanı
yanıtına geri yazıyor. (2) Değer, yanıtta kod olarak okunacak bir konuma yerleşir — önkoşul:
o konumun bağlamına göre kodlama yapılmıyor. (3) Bağlantı kurbana ulaşır ve kurban onu kendi
oturumuyla açar — önkoşul: bir teslim kanalı var. (4) Tarayıcı yerleşen değeri çalıştırır —
önkoşul: sayfanın içerik politikası bu kaynağa izin veriyor. (5) Çalışan kod oturum kalemine
erişip dışarı taşır — önkoşul: çerez betiğe açık.

**Saklı biçim, altı adım.** Yansıyan biçimin ilk adımı ikiye ayrılır: değer önce bir yazma
ucundan **depoya** girer, sonra bir görüntüleme yolunda yanıta yerleşir. Karşılığında üçüncü
adımın önkoşulu **ortadan kalkar**: kimseyi bir bağlantıya yönlendirmek gerekmez, sayfayı
kendi işi için açan herkes zinciri kendisi tamamlar. Zincir bir adım uzar ve teslim halkası
bedavaya gelir.

**Belge nesnesi tabanlı biçim, dört adım.** (1) Değer istemci tarafında bir kaynaktan okunur
— önkoşul: adres parçası ya da yerel depolama gibi sunucuya gitmeyen bir kaynak kullanılıyor.
(2) İstemci betiği değeri, kod olarak yorumlanan bir hedefe yazar — önkoşul: hedef seçimi
sabit değil. (3) Tarayıcı çalıştırır. (4) Erişim ve çıkış. Bu dizide **sunucuda geçen adım
yoktur**; sunucu isteği görmez, kaydına düşmez, yanıtını değiştirmez.

Üç dizinin ortak noktası son iki adımdır: çalışma ve çıkış. Bu, savunmanın niçin iki ayrı
yerde durabildiğini açıklar — biri değerin yanıta yerleşmesini, öteki tarayıcının onu
çalıştırmasını engeller. Ayrıldıkları nokta ise başlangıçtır: yansıyan ve saklı biçim
sunucudan geçer, üçüncüsü geçmez.

**TS10:** her biçim ayrı bir adım dizisidir. **TS11:** her katman her biçimde belirli bir adımı
kırar; kırmadığı biçimde değeri yoktur. **TS12:** bağlantı başına teslimde bedel kurgu 12
kişidir, görüntüleme başına teslimde sayfanın günlük görüntüleme sayısıdır. **TS13:** ilk
kırılan halka, o sayfada dağıtılmış katmanların kırdığı en küçük adım indeksidir.

```js
// xss/bicim.mjs — siteler arasi betik calistirmanin uc bicimi, adim dizileri ve katmanlar
// (model). Gercek bir sayfa, gercek bir deger ve hicbir betik govdesi yok.
export const BICIM = {
  yansiyan: { adim: ["giris", "yerlesme", "teslim", "calisma", "cikis"],
    taraf: ["sunucu", "sunucu", "kurban", "tarayici", "tarayici"], teslim: "baglanti basina" },
  sakli: { adim: ["yazma", "depolama", "yerlesme", "goruntuleme", "calisma", "cikis"],
    taraf: ["sunucu", "sunucu", "sunucu", "kurban", "tarayici", "tarayici"],
    teslim: "goruntuleme basina" },
  belgeNesnesi: { adim: ["istemci-kaynagi", "hedefe-yazma", "calisma", "cikis"],
    taraf: ["tarayici", "tarayici", "tarayici", "tarayici"], teslim: "baglanti basina" },
};

// kirar[bicim] = 1 tabanli adim indeksi ya da 0 (o bicimde hicbir adimi kirmaz).
export const KATMAN = [
  { ad: "girdi-sozlesmesi", yer: "sunucu",
    kirar: { yansiyan: 1, sakli: 1, belgeNesnesi: 0 }, mesru: 3 },
  { ad: "depo-temizleme", yer: "sunucu",
    kirar: { yansiyan: 0, sakli: 2, belgeNesnesi: 0 }, mesru: 2 },
  { ad: "cikti-kodlama", yer: "sunucu",
    kirar: { yansiyan: 2, sakli: 3, belgeNesnesi: 0 }, mesru: 0 },
  { ad: "icerik-politikasi", yer: "tarayici",
    kirar: { yansiyan: 4, sakli: 5, belgeNesnesi: 3 }, mesru: 7 },
  { ad: "istemci-hedef-secimi", yer: "istemci-kodu",
    kirar: { yansiyan: 0, sakli: 0, belgeNesnesi: 2 }, mesru: 1 },
  { ad: "cerez-bayragi", yer: "tarayici",
    kirar: { yansiyan: 5, sakli: 6, belgeNesnesi: 4 }, mesru: 4 },
];

export const BAGLANTI = 12;

// Kurgu olcum aginin sekiz sayfasi: dagitilmis katmanlar ve gunluk goruntuleme sayisi.
export const SAYFA = [
  ["abone-portali.arama", ["girdi-sozlesmesi", "cikti-kodlama", "icerik-politikasi", "cerez-bayragi"], 210],
  ["abone-portali.itiraz", ["girdi-sozlesmesi", "depo-temizleme", "cikti-kodlama", "cerez-bayragi"], 90],
  ["abone-portali.fatura", ["cikti-kodlama", "icerik-politikasi", "cerez-bayragi"], 340],
  ["saha-uygulamasi.is-emri", ["girdi-sozlesmesi", "cikti-kodlama", "cerez-bayragi"], 160],
  ["saha-uygulamasi.saha-notu", ["cerez-bayragi"], 75],
  ["sube-ucu.pano", ["cikti-kodlama", "icerik-politikasi"], 40],
  ["sube-ucu.rapor-baglantisi", ["istemci-hedef-secimi", "cerez-bayragi"], 55],
  ["yonetim.olcum-arama", [], 20],
];

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(""));
```

```js
// xss/olcum.mjs — uc bicim sekiz sayfada kosturulur: ilk kirilan halka, sunucu tarafinin
// kirdigi adim ve kirilmadiginda etkilenen oturum sayisi. Rastgelelik yok.
import { BICIM, KATMAN, SAYFA, BAGLANTI, yaz } from "./bicim.mjs";

const adlar = Object.keys(BICIM);
const AD = { yansiyan: "yansiyan", sakli: "sakli", belgeNesnesi: "belge nesnesi" };
const ilkKirilan = (b, d) => Math.min(...KATMAN
  .filter((k) => d.includes(k.ad) && k.kirar[b] > 0).map((k) => k.kirar[b]), Infinity);
const bedel = (b, gor) => (b === "sakli" ? gor : BAGLANTI);

console.log(`${adlar.length} bicim, ${KATMAN.length} katman, ${SAYFA.length} kurgu sayfa\n`);

const A = [-16, 7, 10, 12, 20];
console.log("1. bicim basina zincir");
yaz(A, "bicim", "adim", "sunucuda", "kirabilen", "teslim");
for (const b of adlar)
  yaz(A, AD[b], BICIM[b].adim.length, BICIM[b].taraf.filter((t) => t === "sunucu").length,
    KATMAN.filter((k) => k.kirar[b] > 0).length, BICIM[b].teslim);

const B = [-22, -14, 10, 8, 15];
console.log("\n2. katman-adim eslemesi");
yaz(B, "katman", "yer", "yansiyan", "sakli", "belge nesnesi");
for (const k of KATMAN)
  yaz(B, k.ad, k.yer, k.kirar.yansiyan || "-", k.kirar.sakli || "-", k.kirar.belgeNesnesi || "-");
const sunucu = KATMAN.filter((k) => k.yer === "sunucu");
console.log(`sunucu tarafindaki ${sunucu.length} katmanin belge nesnesi tabanli bicimde ` +
  `kirdigi adim sayisi: ${sunucu.filter((k) => k.kirar.belgeNesnesi > 0).length}`);

const C = [-26, 7, 12, 12, 15];
console.log("\n3. sayfa basina ilk kirilan halka");
yaz(C, "sayfa", "katman", "yansiyan", "sakli", "belge nesnesi");
let acik = 0, oturum = 0;
for (const [ad, d, gor] of SAYFA) {
  const h = adlar.map((b) => ilkKirilan(b, d));
  h.forEach((v, i) => { if (v === Infinity) { acik++; oturum += bedel(adlar[i], gor); } });
  yaz(C, ad, d.length, ...h.map((v) => (v === Infinity ? "kirilmiyor" : `${v}. adim`)));
}
console.log(`${SAYFA.length * adlar.length} sayfa-bicim bilesiminin ${acik} tanesinde hicbir ` +
  `halka kirilmiyor; bu bilesimlerin gunluk bedeli ${oturum} kurgu oturum`);
const gec = SAYFA.flatMap(([, d, gor]) => adlar.filter((b) =>
  ilkKirilan(b, d) === BICIM[b].adim.length).map((b) => bedel(b, gor)));
console.log(`yalnizca son adimda kirilan bilesim: ${gec.length}, gunluk bedeli ` +
  `${gec.reduce((a, x) => a + x, 0)} kurgu oturum`);

const D = [-22, 10, 8, 15, 9, 15];
console.log("\n4. tek katman butun sayfalarda olsaydi");
yaz(D, "tek katman", "yansiyan", "sakli", "belge nesnesi", "mesru", "kalan oturum");
for (const k of KATMAN) {
  const top = SAYFA.reduce((t, [, , gor]) => t + adlar.reduce((s, b) =>
    s + (k.kirar[b] > 0 ? 0 : bedel(b, gor)), 0), 0);
  yaz(D, k.ad, k.kirar.yansiyan || "-", k.kirar.sakli || "-", k.kirar.belgeNesnesi || "-",
    k.mesru, top);
}
const hepsiAcik = SAYFA.reduce((t, [, , gor]) => t + adlar.reduce((s, b) => s + bedel(b, gor), 0), 0);
console.log(`hicbir katman yokken gunluk bedel: ${hepsiAcik} kurgu oturum`);
```

```
3 bicim, 6 katman, 8 kurgu sayfa

1. bicim basina zincir
bicim              adim  sunucuda   kirabilen              teslim
yansiyan              5         2           4     baglanti basina
sakli                 6         3           5  goruntuleme basina
belge nesnesi         4         0           3     baglanti basina

2. katman-adim eslemesi
katman                yer             yansiyan   sakli  belge nesnesi
girdi-sozlesmesi      sunucu                 1       1              -
depo-temizleme        sunucu                 -       2              -
cikti-kodlama         sunucu                 2       3              -
icerik-politikasi     tarayici               4       5              3
istemci-hedef-secimi  istemci-kodu           -       -              2
cerez-bayragi         tarayici               5       6              4
sunucu tarafindaki 3 katmanin belge nesnesi tabanli bicimde kirdigi adim sayisi: 0

3. sayfa basina ilk kirilan halka
sayfa                      katman    yansiyan       sakli  belge nesnesi
abone-portali.arama             4     1. adim     1. adim        3. adim
abone-portali.itiraz            4     1. adim     1. adim        4. adim
abone-portali.fatura            3     2. adim     3. adim        3. adim
saha-uygulamasi.is-emri         3     1. adim     1. adim        4. adim
saha-uygulamasi.saha-notu       1     5. adim     6. adim        4. adim
sube-ucu.pano                   2     2. adim     3. adim        3. adim
sube-ucu.rapor-baglantisi       2     5. adim     6. adim        2. adim
yonetim.olcum-arama             0  kirilmiyor  kirilmiyor     kirilmiyor
24 sayfa-bicim bilesiminin 3 tanesinde hicbir halka kirilmiyor; bu bilesimlerin gunluk bedeli 44 kurgu oturum
yalnizca son adimda kirilan bilesim: 7, gunluk bedeli 190 kurgu oturum

4. tek katman butun sayfalarda olsaydi
tek katman              yansiyan   sakli  belge nesnesi    mesru   kalan oturum
girdi-sozlesmesi               1       1              -        3             96
depo-temizleme                 -       2              -        2            192
cikti-kodlama                  2       3              -        0             96
icerik-politikasi              4       5              3        7              0
istemci-hedef-secimi           -       -              2        1           1086
cerez-bayragi                  5       6              4        4              0
hicbir katman yokken gunluk bedel: 1182 kurgu oturum
```

## Sunucunun Görmediği Zincir

İkinci tablonun son satırı bu dersin ana bulgusudur: sunucu tarafındaki üç katmanın belge
nesnesi tabanlı biçimde kırdığı adım sayısı **sıfırdır**. Girdi sözleşmesi bir istek görmez,
depo temizleme bir yazma görmez, çıktı kodlaması yanıtın içine yazılan bir değer görmez.
Değer sunucuya hiç uğramaz.

Bunun ikinci bir sonucu vardır ve ilkinden ağırdır: sunucu bu zincirin **hiçbir adımını
kaydetmez**. Kırılamayan bir zincirde ölçü tespite kayar; burada tespit de sunucu tarafında
yapılamaz, çünkü bakılacak bir kayıt satırı yoktur. Bu biçimin görülebileceği tek yerler
tarayıcı davranışını raporlayan bir politika ihlali bildirimi ve istemci kodunun kendi
kaydıdır.

Aynı satır bir katman sınıfını da öne çıkarır: `istemci-hedef-secimi` yalnız bu biçimde
değer taşır ve tek başına **ikinci adımı** kırar. Sunucuyu sertleştirmekle ilgili hiçbir
karar bu adımı etkilemez.

Bu, ölçünün nereye taşındığını da belirler. Bir savunma raporu sunucu tarafındaki üç katmanı
sayarak "üç katmanlı koruma" yazabilir ve bu, iki biçim için doğru olur. Üçüncü biçim için
sayı üçtür ama kırdığı adım sıfırdır — ve rapor bu ikisini ayırmadığı sürece fark
görünmez. Katman saymak yerine **kırılan adımı** saymanın gerekçesi bu satırdır.

## Zincir Uzunluğu ve Teslim

Birinci tablo üç biçimi yan yana koyar: 5, 6 ve 4 adım. En uzun zincir en güvenli olan
değildir. Saklı biçim altı adımdır ve bir adım fazlası **saldıranın lehinedir**: dördüncü
adım bir teslim çabası gerektirmez, sayfayı kendi işi için açan herkes o adımı tamamlar.

Kırabilen katman sayısı da aynı yönde okunur: yansıyan biçimi dört katman, saklı biçimi beş,
belge nesnesi tabanlı biçimi üç katman kırabiliyor. Saklı biçim en çok katmanın gördüğü
biçimdir çünkü en çok adımı sunucudan geçer; en az katmanın gördüğü biçim ise sunucudan hiç
geçmeyendir. **Bir zincirin görülebilirliği uzunluğuyla değil, savunmanın bulunduğu tarafta
kaç adım geçirdiğiyle ölçülür.**

Teslim sütunu bedelin de biriminin farklı olduğunu söyler. Yansıyan ve belge nesnesi tabanlı
biçimlerde bedel bağlantı başınadır — kurgu 12 kişi. Saklı biçimde bedel görüntüleme
başınadır ve sayfaya göre 20 ile 340 arasında değişir. Aynı sınıf, aynı sayfa, farklı biçim:
**geç kırmanın bedeli yirmi sekiz katına kadar çıkar.**

## Sayfa Başına Kırılma

Üçüncü tablo dağıtımı ölçer. Sekiz sayfa ve üç biçimin kurduğu 24 bileşimin **3'ünde** hiçbir
halka kırılmıyor; üçü de tek bir sayfada toplanıyor. O sayfada hiçbir katman dağıtılmamış
durumda ve günlük bedeli 44 kurgu oturum.

Daha ince olan sonuç yedi bileşimdedir: oralarda zincir kırılıyor, ama **yalnız son adımda**.
Çerez bayrağı taşıyan ama başka hiçbir katmanı olmayan bir sayfada kod çalışır, sayfa
değişir, istekler gider — kırılan tek halka en sondaki erişimdir. Bu yedi bileşimin günlük
bedeli 190 oturumdur ve savunma raporunda "korunuyor" diye görünürler.

Tablonun sol sütunu bu sonucun nedenini verir. Dört katmanı olan iki sayfada zincir birinci
adımda kırılıyor; üç katmanı olan sayfalarda ikinci ya da üçüncü adımda; tek katmanı olan
sayfada beşinci ve altıncı adımda. Katman sayısı ile kırılan halkanın indeksi bu kümede
birlikte hareket ediyor, ama birebir değil: üç katmanlı `abone-portali.fatura` ikinci adımda
kırarken, iki katmanlı `sube-ucu.pano` da ikinci adımda kırıyor. Belirleyici olan sayı değil,
katmanların **hangi adımlara** düştüğüdür.

`sube-ucu.rapor-baglantisi` satırı iki katmanın yön farkını gösterir. Belge nesnesi tabanlı
biçimde zincir **ikinci adımda** kırılıyor, çünkü istemci hedef seçimi oradadır; yansıyan ve
saklı biçimlerde ise ancak beşinci ve altıncı adımda. Aynı sayfa, aynı iki katman, biçime
göre üç farklı halka.

## Tek Katmanın Kapsamı

Dördüncü tablo her katmanı tek başına, bütün sayfalarda varsayar ve geriye kalan günlük
bedeli sayar. Hiçbir katman yokken bedel 1.182 kurgu oturumdur.

İki satır sıfır veriyor: içerik politikası ve çerez bayrağı üç biçimi de kırıyor, çünkü
ikisi de **tarayıcı tarafındadır** ve üç biçim de orada birleşir. Meşru işe bedelleri 7 ve
4'tür — üç katmanın en pahalıları.

Depo temizlemenin satırı ise tek biçime bağlı bir katmanın sınırını verir: saklı biçimi
ikinci adımda kırar, öteki iki biçimde hiçbir şey yapmaz ve geriye 192 oturum bırakır — altı
satırın en yükseği değil ama en dar kapsamlısı.

Çıktı kodlamasının meşru işe bedeli **sıfırdır** ve yansıyan ile saklı biçimi ikinci ve
üçüncü adımda kırar; ama belge nesnesi tabanlı biçimde hiçbir şey yapmaz ve geriye 96 oturum
bırakır. En ucuz katman en erken kırar ve en dar kapsar; en pahalı katman en geç kırar ve
tam kapsar. **Kapsam ile erkenlik aynı katmanda birleşmiyor** — bu, iki katmanın da
gerekmesinin ölçülmüş nedenidir.

## Özet

- Üç biçim üç ayrı zincirdir: yansıyan 5, saklı 6, belge nesnesi tabanlı 4 adım. Saklı biçimin
  fazladan adımı saldıranın lehinedir, çünkü teslim halkasının önkoşulunu ortadan kaldırır.
- Sunucu tarafındaki 3 katmanın belge nesnesi tabanlı biçimde kırdığı adım sayısı 0'dır ve o
  zincirin hiçbir adımı sunucu kaydına düşmez; orada ölçü kırmadan tespite kayar, tespit de
  yalnız tarayıcı tarafında yapılabilir.
- Bedelin birimi biçime göre değişir: bağlantı başına 12 kurgu kişi, görüntüleme başına 20 ile
  340 arası. Aynı sayfada geç kırmanın bedeli biçime göre yirmi sekiz katına kadar çıkar.
- Sekiz sayfa ve üç biçimin 24 bileşiminin 3'ünde hiçbir halka kırılmıyor (günlük 44 oturum),
  7'sinde yalnız son adımda kırılıyor (günlük 190 oturum).
- Tarayıcı tarafındaki iki katmanın her biri tek başına üç biçimi de kapatıyor ve kalan bedeli
  0'a indiriyor; meşru bedelleri 7 ve 4. Bedeli 0 olan çıktı kodlaması en erken kırıyor ama
  bir biçimi hiç görmediği için geriye 96 oturum bırakıyor.

## Sonraki Adım

Bu dersin üç biçiminde de kod kurbanın tarayıcısında çalışıyordu ve son adımda oturum
kalemine erişiyordu. Aynı tarayıcının yapabileceği daha sessiz bir şey daha vardır: hiçbir
kod çalıştırmadan, yalnız bir isteği **kurbanın kimliğiyle** göndermek. Sonraki ders bu
sınıfı ölçer — isteğin kurbanın tarayıcısı üzerinden gittiği yön ile sunucunun kendi
kimliğiyle gittiği yön ayrı zincirler olarak yazılır, her yönün kaç adımı olduğu, hangi
katmanın hangi adımı kırdığı ve iki yönün geç kırma bedellerinin neden aynı birimle
ölçülemediği sayılır.
