---
title: 'Kimlik Bilgisi Doldurma Savunması'
source: 'https://academia.sh/tr/kurslar/calisma-zamani-guvenligi/kimlik-bilgisi-doldurma-savunmasi'
course: 'Çalışma Zamanı Güvenliği ve Sır Yönetimi'
language: tr
updated: '2026-08-17T18:06:41+00:00'
license: 'CC BY-SA 4.0'
---

# Kimlik Bilgisi Doldurma Savunması

Bir saatlik oturum açma denemesi kaydında hesap ve adres eşiklerinin ayrı ayrı koşturulması ve hangi eşiğin hangi saldırı biçimini durdurduğunun ayrılması: kaba kuvveti hesap eşiği, yoğun kaynaklı püskürtmeyi adres eşiği durdururken hesap başına tek deneme yapan doldurmanın ikisinden de geçmesi, engellenen deneme sayısıyla önlenen hesap ele geçirme sayısı arasındaki fark, paylaşılan çıkış adresinin ve hedef alınan meşru hesabın kilitlenmesi.

Önceki ders hız sayacını tek bir anahtara bağladı ve o anahtarın ne olduğunu hiç sormadı. Oturum
açma denemesi dizisinin durumu da bu yüzden belirsiz kaldı: saniyedeki hız biliniyordu, ama
denemelerin kaç hesaba ve kaç adrese dağıldığı bilinmiyordu. Aynı toplam hız tek hesaba
yüklendiğinde başka, dört bin hesaba birer deneme olarak dağıtıldığında bambaşka bir saldırı
biçimidir. Bu ders eşiği hız ekseninden çıkarıp hesap ve adres eksenine taşıyor.

İki biçimin adı ayrı tutulur. **Kimlik bilgisi doldurma**, başka bir yerden sızmış hesap–parola
çiftlerinin bu sistemde denenmesidir; hesap başına genellikle tek deneme yapılır ve umut, aynı
parolanın burada da kullanılmış olmasıdır. **Püskürtme** ise az sayıda yaygın parolanın çok
hesapta denenmesidir; hesap başına birkaç deneme düşer. İkisi de hesap ekseninde seyrektir, ama
adres ekseninde farklı yoğunluk gösterirler ve savunma tam olarak bu farkı ölçebilir.

## Üç Saldırı Biçimi, İki Eksen

Aşağıdaki her şey `node` ile kurulan bir modeldir. Hiçbir deneme gerçekten yapılmıyor, hiçbir
kimlik bilgisi listesi ya da deneme aracı yazılmıyor; saldırı yalnız bir kayıt satırı biçiminde,
hedef hesap ve kaynak adres alanlarıyla temsil ediliyor.

- **US11.** Bin dokuz yüz gerçek hesap, saldırı biçimleri ve sayıları kurgusal ölçüm ağına
  aittir. Kayıt görünür tohumla üretiliyor; üreteç kendi yazıldığı için koşum yinelenebilir.
- **US12.** Bir denemenin başarılı olması modelde hesabın özelliğinden türer: doldurma yalnız
  parolası sızmış çifte ait hesapta, püskürtme yalnız parolası yaygın olan hesapta başarılıdır.
- **US13.** Eşik, pencere içinde biriken **başarısız** deneme sayısına bakar; başarılı deneme
  sayacı artırmaz. Üretimdeki yaygın davranış budur ve bu dersin ana bulgusunun kaynağıdır.
- **US14.** Meşru başarısızlık oranı yüzde on ikidir ve saha ekibinin tamamı tek bir paylaşılan
  çıkış adresinden geliyor. Otuz abone de parolasını unutup art arda deniyor.
- **US15.** Eşik aşıldığında sonraki denemeler engelleniyor; hesap kilidi ile adres kısması aynı
  sonucu veriyor. Gerçekte ikisinin çözülme süresi farklıdır, sayıların yönünü değiştirmez.

```js
// giris.mjs — bir saatlik oturum acma denemesi kaydi; model, gercek deneme uretilmiyor
export const TOHUM = 20250804;
let s = TOHUM;
const rnd = () => (s = (s * 48271) % 2147483647) / 2147483647;
const tam = (n) => Math.floor(rnd() * n);

// gercek hesaplar: ikinci etken kayitli mi, parolasi sizmis cifte mi ait, parolasi yaygin mi
export const HESAP = [];
for (let i = 0; i < 1900; i++)
  HESAP.push({ ad: `hesap-${i}`, etken: rnd() < 0.86, tekrar: rnd() < 0.038, yaygin: rnd() < 0.009 });
export const HARITA = new Map(HESAP.map((h) => [h.ad, h]));

// [dakika, hesap, adres, sinif, basarili]
export function kayitUret() {
  const k = [];
  for (let i = 0; i < 500; i++)                      // saha ekibi: tek paylasilan cikis adresi
    k.push([tam(60), HESAP[tam(380)].ad, 'paylasilan-cikis', 'mesru', rnd() > 0.12]);
  for (let i = 0; i < 1900; i++)                     // portal aboneleri: dagitik adres
    k.push([tam(60), HESAP[380 + tam(1520)].ad, `abone-adres-${tam(900)}`, 'mesru', rnd() > 0.12]);
  for (let i = 0; i < 30; i++) {                     // parolasini unutan abone: ardisik deneme
    const n = 6 + tam(4), t0 = tam(50), ad = `abone-adres-${tam(900)}`, h = HESAP[380 + tam(1520)].ad;
    for (let j = 0; j < n; j++) k.push([t0 + j, h, ad, 'mesru', j === n - 1]);
  }
  for (let i = 0; i < 4000; i++) {                   // doldurma: hesap basina tek deneme, 400 adres
    const h = i < 1900 ? HESAP[i] : null;
    k.push([tam(60), h ? h.ad : `yok-${i}`, `doldurma-adres-${i % 400}`, 'doldurma', Boolean(h && h.tekrar)]);
  }
  for (let r = 0; r < 3; r++)                        // puskurtme: uc tur, hesap basina birer deneme
    for (let i = 0; i < 1900; i++)
      k.push([5 + r * 20 + tam(5), HESAP[i].ad, `puskurtme-adres-${i % 40}`, 'puskurtme',
        HESAP[i].yaygin && r === i % 3]);
  for (let i = 0; i < 600; i++)                      // kaba kuvvet: tek hesap, tek adres
    k.push([10 + Math.floor(i / 120), HESAP[7].ad, 'kaba-adres', 'kabakuvvet', false]);
  return k.sort((a, b) => a[0] - b[0]);
}

// esik: pencere icinde biriken basarisiz deneme sayisi; asilinca sonraki denemeler engellenir
export function olc(kayit, hesapEsigi, adresEsigi) {
  const hf = new Map(), af = new Map(), kilit = new Set();
  const tur = {}, gec = [];
  let engelMesru = 0, mesruHesapla = 0, mesruAdresle = 0, engelKotu = 0, gecenKotu = 0;
  for (const [, hesap, adres, sinif, basarili] of kayit) {
    const h = hf.get(hesap) || 0, a = af.get(adres) || 0;
    const engel = h >= hesapEsigi || a >= adresEsigi;
    if (sinif === 'mesru') {
      if (engel) { engelMesru++; kilit.add(hesap); h >= hesapEsigi ? mesruHesapla++ : mesruAdresle++; }
      else if (!basarili) { hf.set(hesap, h + 1); af.set(adres, a + 1); }
      continue;
    }
    tur[sinif] = tur[sinif] || { engellenen: 0, gecen: 0, eleGecen: 0 };
    if (engel) { engelKotu++; tur[sinif].engellenen++; continue; }
    gecenKotu++; tur[sinif].gecen++;
    if (basarili) { tur[sinif].eleGecen++; gec.push([hesap, sinif]); }
    else { hf.set(hesap, h + 1); af.set(adres, a + 1); }
  }
  return { engelMesru, mesruHesapla, mesruAdresle, kilitliHesap: kilit.size,
    engelKotu, gecenKotu, eleGecen: gec, tur };
}
```

## Hangi Eşik Neyi Görüyor

```js
// kosum.mjs — ayni kayit, degisen tek sey hesap ve adres esikleri
import { TOHUM, kayitUret, olc } from './giris.mjs';

const s = (x, n) => String(x).padStart(n);
const K = kayitUret();
const say = (f) => K.filter(f).length;
const I = Infinity;
console.log(`tohum ${TOHUM}; 60 dakika, ${K.length} deneme` +
  ` (${say((r) => r[3] === 'mesru')} mesru / ${say((r) => r[3] !== 'mesru')} kotu)\n`);

console.log(`${'saldiri bicimi'.padEnd(14)}${s('deneme', 8)}${s('hesap', 7)}${s('adres', 7)}` +
  `${s('deneme/hesap', 14)}${s('deneme/adres', 14)}${s('ele gecen hesap', 17)}`);
for (const t of ['doldurma', 'puskurtme', 'kabakuvvet']) {
  const r = K.filter((x) => x[3] === t);
  const h = new Set(r.map((x) => x[1])).size, a = new Set(r.map((x) => x[2])).size;
  console.log(`${t.padEnd(14)}${s(r.length, 8)}${s(h, 7)}${s(a, 7)}` +
    `${s((r.length / h).toFixed(1), 14)}${s((r.length / a).toFixed(1), 14)}` +
    `${s(r.filter((x) => x[4]).length, 17)}`);
}

const AYAR = [['esik yok', I, I], ['hesap 5', 5, I], ['adres 50', I, 50],
  ['hesap 5 + adres 50', 5, 50], ['hesap 3 + adres 20', 3, 20]];
console.log(`\n${'ayar'.padEnd(20)}${s('engellenen kotu', 17)}${s('gecen kotu', 12)}` +
  `${s('ele gecen', 11)}${s('engellenen mesru', 18)}${s('kilitli hesap', 15)}`);
for (const [ad, he, ae] of AYAR) {
  const r = olc(K, he, ae);
  console.log(`${ad.padEnd(20)}${s(r.engelKotu, 17)}${s(r.gecenKotu, 12)}${s(r.eleGecen.length, 11)}` +
    `${s(r.engelMesru, 18)}${s(r.kilitliHesap, 15)}`);
}

console.log(`\nsaldiri bicimine gore engellenen deneme:`);
console.log(`${'ayar'.padEnd(20)}${['doldurma', 'puskurtme', 'kabakuvvet'].map((t) => s(t, 12)).join('')}`);
for (const [ad, he, ae] of AYAR.slice(1)) {
  const r = olc(K, he, ae);
  console.log(`${ad.padEnd(20)}` +
    ['doldurma', 'puskurtme', 'kabakuvvet'].map((t) => s(r.tur[t].engellenen, 12)).join(''));
}
```

```
tohum 20250804; 60 dakika, 12923 deneme (2623 mesru / 10300 kotu)

saldiri bicimi  deneme  hesap  adres  deneme/hesap  deneme/adres  ele gecen hesap
doldurma          4000   4000    400           1.0          10.0               57
puskurtme         5700   1900     40           3.0         142.5               13
kabakuvvet         600      1      1         600.0         600.0                0

ayar                  engellenen kotu  gecen kotu  ele gecen  engellenen mesru  kilitli hesap
esik yok                            0       10300         70                 0              0
hesap 5                           669        9631         69               220             91
adres 50                         4244        6056         63               227            164
hesap 5 + adres 50               4301        5999         62               364            194
hesap 3 + adres 20               5512        4788         57               613            315

saldiri bicimine gore engellenen deneme:
ayar                    doldurma   puskurtme  kabakuvvet
hesap 5                       18          55         596
adres 50                       0        3694         550
hesap 5 + adres 50            11        3694         596
hesap 3 + adres 20            15        4899         598
```

İlk tablo iki ekseni yan yana koyuyor ve ayrım orada okunuyor. Kaba kuvvet hesap ekseninde altı
yüz denemeyle uçtadır; hesap eşiği beşe kurulduğunda beş yüz doksan altı denemesi engellenir,
yani bu biçim tek bir eşikle bitirilmiş sayılır. Püskürtme hesap ekseninde seyrektir — hesap
başına üç deneme, eşiğin altında — ama kırk adrese sıkıştığı için adres başına yüz kırk iki
denemeye çıkar; adres eşiği elliye kurulduğunda üç bin altı yüz doksan dört denemesi engellenir.
Doldurma her iki eksende de eşiğin altındadır: hesap başına bir deneme, adres başına on. Adres
eşiği bu biçimden **sıfır** deneme engelliyor.

Alt tablodaki doldurma sütununda görünen on beş ile on sekiz, doldurmanın kendi yoğunluğundan
değil, aynı hesapların püskürtmeye de hedef olmasından geliyor: iki biçimin başarısızlıkları aynı
hesap sayacında toplanınca birkaç hesap eşiği aşıyor. Yani doldurma ancak yanında başka bir
biçim varsa dolaylı olarak görülüyor.

Orta tablonun son iki sütunu bedeli yazıyor. Hesap eşiği beşte doksan bir meşru hesap kilitleniyor
ve bunların yalnız otuzu parolasını unutan abonedir; kalanı **saldırının hedefi olduğu için**
kilitlendi. Hesabına yönelik başarısız denemeler sayacı doldurdu ve hesabın gerçek sahibi
giremez oldu. Adres eşiği ellide ise iki yüz yirmi yedi meşru deneme kesiliyor; hepsi paylaşılan
çıkış adresinden gelen saha ekibine ait, çünkü o adresten geçen beş yüz denemenin yüzde on ikilik
başarısız payı eşiği tek başına aşıyor. Adres eşiği bir hesabı değil, bir ekibi kesiyor.

## Eşiğin Önlemediği Ele Geçirme

Yukarıdaki tabloda gözden kaçması en muhtemel sütun "ele geçen" sütunudur. Gösterge tablosunda
öne çıkan sayı engellenen denemedir ve o sayı ayar sıkılaştıkça yüzlerden binlere tırmanır.
Ele geçen sütunu ise neredeyse yerinde duruyor: eşiksiz koşumda yetmiş hesap ele geçiyor, en sıkı
ayarda elli yedi. Beş bin beş yüz on iki deneme engellendi ve ele geçirme yalnız on üç azaldı.
Bu iki sayının aynı tabloda bulunması gerekir, çünkü savunmanın amacı denemeyi azaltmak değil,
hesabın ele geçmesini önlemektir.

```js
// asama.mjs — ayni hesap ele gecirmeyi daha erken hangi asama kapatir
import { HESAP, HARITA, kayitUret, olc } from './giris.mjs';

const s = (x, n) => String(x).padStart(n);
const K = kayitUret(), I = Infinity;
const mesru = K.filter((r) => r[3] === 'mesru').length;
const taban = olc(K, I, I), siki = olc(K, 3, 20);
const etkensiz = (r) => r.eleGecen.filter(([ad]) => !HARITA.get(ad).etken).length;
const belirleme = HESAP.filter((h) => h.tekrar || h.yaygin).length;

console.log(`${'onlem'.padEnd(34)}${s('asama', 16)}${s('ele gecen', 11)}${s('mesru bedel', 28)}`);
for (const [a, b, c, d] of [
  ['onlem yok', '-', taban.eleGecen.length, '0'],
  ['hesap 3 + adres 20 esigi', 'calisma zamani', siki.eleGecen.length,
    `${siki.engelMesru} deneme, ${siki.kilitliHesap} hesap`],
  ['ikinci etken, kapsam %86', 'kod', etkensiz(taban), `${mesru} oturumda ek adim`],
  ['esik ve ikinci etken', 'ikisi', etkensiz(siki), `${siki.engelMesru} deneme, ek adim`],
  ['parola belirlemede cift denetimi', 'tasarim', 0, `${belirleme} hesapta parola degisir`],
]) console.log(`${a.padEnd(34)}${s(b, 16)}${s(c, 11)}${s(d, 28)}`);

console.log(`\nikinci etken kapsami ${HESAP.filter((h) => h.etken).length}/${HESAP.length};` +
  ` kapsam disindaki ${HESAP.filter((h) => !h.etken).length} hesap her ayarda savunmasiz kaliyor\n`);

console.log(`${'ayar'.padEnd(20)}${s('hesap esigi kesti', 19)}${s('adres esigi kesti', 19)}` +
  `${s('kilitli mesru hesap', 21)}`);
for (const [ad, he, ae] of [['hesap 5', 5, I], ['adres 50', I, 50],
  ['hesap 5 + adres 50', 5, 50], ['hesap 3 + adres 20', 3, 20]]) {
  const r = olc(K, he, ae);
  console.log(`${ad.padEnd(20)}${s(r.mesruHesapla, 19)}${s(r.mesruAdresle, 19)}${s(r.kilitliHesap, 21)}`);
}
console.log(`\npaylasilan cikis adresinden gelen mesru deneme: ` +
  `${K.filter((r) => r[3] === 'mesru' && r[2] === 'paylasilan-cikis').length}`);
```

```
onlem                                        asama  ele gecen                 mesru bedel
onlem yok                                        -         70                           0
hesap 3 + adres 20 esigi            calisma zamani         57       613 deneme, 315 hesap
ikinci etken, kapsam %86                       kod          5       2623 oturumda ek adim
esik ve ikinci etken                         ikisi          4         613 deneme, ek adim
parola belirlemede cift denetimi           tasarim          0   70 hesapta parola degisir

ikinci etken kapsami 1639/1900; kapsam disindaki 261 hesap her ayarda savunmasiz kaliyor

ayar                  hesap esigi kesti  adres esigi kesti  kilitli mesru hesap
hesap 5                             220                  0                   91
adres 50                              0                227                  164
hesap 5 + adres 50                  138                226                  194
hesap 3 + adres 20                  220                393                  315

paylasilan cikis adresinden gelen mesru deneme: 500
```

Üst tablo kursun ana sorusunu bu ders için yanıtlıyor. Çalışma zamanı eşiği kötü denemenin yüzde
elli üçünü engelledi ve ele geçirmeyi yetmişten elli yediye indirdi: önlenen ele geçirme oranı
yüzde on dokuz. Bunun nedeni eşiğin ayarında değil, tanımındadır. Eşik **başarısızlıkları** sayar;
doldurmada başarılı deneme hesabın gördüğü ilk denemedir ve o an sayaç boştur. Sayaç ancak
başarısızlıklar biriktikten sonra dolar, yani eşik geç kalmış olmayı yapısal olarak taşır.

Aynı ele geçirme kod aşamasında ikinci etkenle yetmişten beşe iniyor. Beşin sıfır olmamasının
nedeni de tabloda yazılı: ikinci etken kapsamı bin altı yüz otuz dokuz hesaptır ve kapsam dışında
kalan iki yüz altmış bir hesap hiçbir eşik ayarında korunmuyor. Kapsam, bu önlemin tek gerçek
ayarıdır. Bedeli ise iki bin altı yüz yirmi üç meşru oturumda ek bir adımdır; kesilen oturum
yoktur, geciken oturum vardır.

Tasarım aşamasındaki önlem daha da ucuza kapatıyor. Parola belirlenirken sızmış çift ve yaygın
parola denetimi yapıldığında doldurmanın da püskürtmenin de başarı koşulu ortadan kalkar: ele
geçen hesap sıfırdır. Bedeli yetmiş hesabın parola değiştirmesidir ve bu bir defalıktır. Çalışma
zamanı eşiği aynı kalem için her gün altı yüz on üç meşru denemeyi kesiyor ve üç yüz on beş
hesabı kilitliyor; tasarımdaki denetim kalemi bir kez kapatıyor.

Alt tablo yanlış kesmenin nereye düştüğünü ayırıyor. Hesap eşiği kesmeyi hesap sahibine, adres
eşiği ise bir ağ konumunun arkasındaki herkese yükler. Paylaşılan çıkış adresi arkasında beş yüz
meşru deneme duruyor ve adres eşiği yirmiye indirildiğinde bu adresten kesilen deneme üç yüz
doksan üçe çıkıyor. Adres eşiği, hedeflenen saldırgandan çok o adresin arkasındaki ekibin
büyüklüğüne göre ceza kesiyor.

## Özet

- Üç saldırı biçimi iki eksende ayrışıyor: kaba kuvvet hesap başına 600 denemeyle hesap eşiğinde
  (596 engellendi), püskürtme adres başına 142,5 denemeyle adres eşiğinde (3.694 engellendi)
  durur; doldurma hesap başına 1,0 ve adres başına 10,0 denemeyle ikisinin de altındadır.
- Adres eşiği doldurmadan sıfır deneme engelledi. Alt tabloda görünen 15–18 deneme, aynı
  hesapların püskürtmeye de hedef olmasından gelen dolaylı bir yakalamadır.
- Eşiksiz koşumda 70 hesap ele geçti; en sıkı ayarda 57. Engellenen deneme 5.512'ye çıkarken
  önlenen ele geçirme yalnız 13'tür (yüzde 19), çünkü eşik başarısızlıkları sayar ve doldurmada
  başarılı deneme hesabın ilk denemesidir.
- Yanlış kesme iki ayrı yere düşüyor: hesap eşiği 5'te kilitlenen 91 hesabın yalnız 30'u
  parolasını unutan abonedir, kalanı saldırının hedefi olduğu için kilitlendi. Adres eşiği 50'de
  kesilen 227 denemenin tamamı paylaşılan çıkış adresindeki saha ekibine aittir.
- Aynı ele geçirme kod aşamasında ikinci etkenle 70'ten 5'e (kalan 5, kapsam dışındaki 261
  hesaptan), tasarımda parola belirleme denetimiyle 0'a iniyor. Tasarımdaki bedel 70 hesapta bir
  defalık parola değişimi; çalışma zamanı eşiğinin bedeli her gün 613 kesilen meşru denemedir.

## Sonraki Adım

Bu dersin eşikleri de önceki iki dersin kuralları ve sayaçları da tek tek isteklere ya da
denemelere bakıyordu. Üçünün de ortak varsayımı, savunmanın istekle birlikte gelen bilgiye
bakmasıydı. Oysa çalışma zamanında sunucunun verdiği ve isteğin içeriğiyle hiç ilgisi olmayan
bir karar daha vardır: yanıtla birlikte gönderilen güvenlik başlıkları. Bunlar bir isteği
durdurmaz; tarayıcının ne yapmasına izin verildiğini belirler ve tek bir yerden yönetildiklerinde
arkalarındaki bütün uygulamaları aynı anda kapsarlar. Sonraki ders bu katmanı yakaladığı istekle
değil, **kapsadığı uygulama sayısıyla** ölçüyor ve asıl soruyu kapsamın dışında kalan uca
soruyor.
