Ders 18 / 27
Güvenlik Başlıkları
Taşıma güvenliğinin zorlanması, çerçevelemenin sınırlanması, referans bilgisinin daraltılması, tür tahmininin kapatılması ve kaynak yalıtımı; eksikleri bulan bir yapılandırma denetleyicisi.
İçindekiler
Önceki üç ders belirli saldırı sınıflarına karşı belirli katmanlar kurdu. Bu ders, tek bir sınıfa bağlı olmayan ama hepsinin etkisini azaltan bir kümeyi ele alır: yanıt başlıklarıyla bildirilen ve tarayıcının uyguladığı kısıtlar.
Bu başlıkların ortak özelliği, uygulama kodunda değil sunucu yapılandırmasında yaşamalarıdır. Bir sürüm çıkarken gözden kaçmaları kolaydır, çünkü hiçbir işlevi bozmazlar; yokluklarının gözlenebilir sonucu yalnız bir şeyler ters gittiğinde ortaya çıkar. Dersin sonundaki denetleyici bu görünmezliği giderir.
Taşıma Güvenliğinin Zorlanması
İnternet Nasıl Çalışır kursundaki HTTPS’in Rolü dersi şifreli taşımanın gizlilik, bütünlük ve kimlik doğrulama sağladığını kurmuştu. Uygulama tümüyle şifreli sunuluyor olsa bile bir boşluk kalır: kullanıcı adresi şemasız yazdığında ilk istek şifresiz gidebilir ve yönlendirmeden önce araya girilebilir.
Strict-Transport-Security başlığı bu boşluğu kapatır. Tarayıcıya, bildirilen süre boyunca
bu konağa yalnız şifreli bağlanmasını söyler; şemasız yazılan adres ağa çıkmadan
dönüştürülür. Üç bileşeni vardır. max-age sürenin saniye cinsinden uzunluğudur ve
anlamlı bir koruma için uzun tutulur. includeSubDomains kuralı alt alanlara yayar; bu
olmadan bir alt alan şifresiz kalabilir ve çerez kapsamı üzerinden uygulamayı etkiler.
Üçüncü bileşen, konağı tarayıcılara gömülü listeye kaydeden ön yükleme bildirimidir; ilk
isteği de kapsar, ama geri alınması yavaştır ve tüm alt alanların şifreli sunulmasını
kalıcı olarak taahhüt eder.
Başlığın şifresiz bir yanıtta gönderilmesinin bir etkisi yoktur ve olmamalıdır: aksi takdirde araya giren biri, konağı erişilemez kılan bir kayıt yazdırabilirdi.
Çerçevelemenin Sınırlanması
Kuzey Yamaç Ölçüm İstasyonu arayüzü, istasyon konumunu gösteren bir harita çerçevesi gömer. Bu, çerçevelemenin bir yönüdür. Öteki yön, uygulamanın kendisinin başka bir sayfa tarafından çerçevelenmesidir ve savunma gerektiren yön budur.
Görünmez kılınmış bir çerçeve içine alınan bir sayfa, kullanıcının gördüğü başka bir arayüzün altında durur. Kullanıcı gördüğü düğmeye tıkladığını sanırken çerçeve içindeki sayfanın bir denetimine tıklar; oturum kendisine ait olduğu için işlem gerçekleşir. Bu sınıfın adı tıklama hırsızlığıdır (clickjacking) ve savunması, belgenin kimler tarafından çerçevelenebileceğini bildirmektir.
İki mekanizma vardır. X-Frame-Options başlığı DENY veya SAMEORIGIN değerlerini alır
ve tek bir karar bildirir. İçerik güvenlik politikasının frame-ancestors yönergesi ise
kaynak listesi kabul eder ve daha ayrıntılıdır: yalnız belirli kaynakların çerçevelemesine
izin verilebilir. Yönergeyi anlayan bir gerçekleştirimde yönerge kazanır; ikisini birlikte
yazmak, yalnız birini anlayan gerçekleştirimlerde de koruma sağlar.
Referans Bilgisinin Daraltılması
Bir bağa tıklandığında veya bir alt kaynak yüklendiğinde tarayıcı, isteğe hangi sayfadan
gelindiğini bildiren bir başlık ekler. Öntanımlı davranış, tam adresi göndermeye kadar
gidebilir. Ölçüm istasyonunda bu, .../istasyon/kuzey-yamac?olcum=4417 biçimindeki bir
adresin yol ve sorgu bileşenlerinin üçüncü bir tarafa sızması demektir.
Referrer-Policy başlığı bu davranışı daraltır. Değerler bir eksen üzerinde durur: hiçbir
şey göndermeyen uçtan, tam adresi gönderen uca kadar. Dengeli seçim, aynı kaynağa tam
adresi, başka kaynaklara yalnız kaynak dizgisini gönderen ve şifreliden şifresize geçişte
hiçbir şey göndermeyen değerdir. Analiz ihtiyacı bu bilgiyi gerektiriyorsa, bilgi
başlıktan değil uygulamanın kendi ölçümünden alınır.
Tür Tahmininin Kapatılması
Bir yanıtın içerik türü eksik veya yanlışsa, tarayıcı gövdeye bakıp türü tahmin edebilir. Kullanıcıların dosya yüklediği bir uygulamada bu tahmin bir açığa dönüşür: metin olarak sunulmak istenen bir yükleme, işaretleme gibi yorumlanırsa aynı kaynakta belge olarak çalışır.
X-Content-Type-Options: nosniff başlığı tahmini kapatır ve tarayıcıyı bildirilen türe
uymaya zorlar. Başlık tek başına yetmez; bildirilen türün doğru olması, kullanıcı
yüklemelerinin ayrı bir kaynaktan sunulması ve indirme olarak işaretlenmesi aynı savunmanın
parçalarıdır.
Kaynak Yalıtımı ve Yetenek İzni
Cross-Origin-Resource-Policy başlığı, bir kaynağın başka kaynaklarca gömülüp
gömülemeyeceğini bildirir. Değeri same-origin olduğunda, kaynak yalnız kendi kaynağının
belgelerinde kullanılabilir. Bu, verinin başka bir belgenin bellek alanına çekilmesini
sınırlayan bir kısıttır.
Aynı ailede iki başlık daha bulunur: belgenin açtığı ve kendisini açan pencerelerle tarayıcı bağlamı paylaşımını kesen başlık ve gömülen kaynakların açık izin bildirmesini zorunlu kılan başlık. İkisi birlikte kaynak yalıtımı (cross-origin isolation) adı verilen durumu kurar. Bu durum bazı yeteneklerin ön koşuludur ve yeteneklerin kullanılmadığı bir uygulamada zorunlu değildir; gereksiz yere açıldığında meşru gömme işlemlerini kırar.
Web’in Temelleri ve HTML kursunda tanıtılan yetenek izni (permission policy) ise ayrı bir eksendir: belgenin ve gömdüğü çerçevelerin hangi aygıt yeteneklerini kullanabileceğini sayar. Harita çerçevesinin konum yeteneğine ihtiyacı yoksa, çerçeveye o yetenek verilmez.
Yapılandırmayı Denetlemek
Bu başlıkların hepsi tek tek doğru yazılabilir ve bir sürüm sonra biri düşebilir. Denetimi kural kümesine dönüştürmek, düşen başlığı görünür kılar.
// basliklar.mjs — yanit basliklarini kural kumesine gore denetler const BIR_YIL = 31536000; const KURALLAR = [ { ad: 'tasima guvenligi', denetle: (b) => { const deger = b['strict-transport-security']; if (!deger) return 'Strict-Transport-Security yok'; const sure = Number(/max-age=(\d+)/.exec(deger)?.[1] ?? 0); if (sure < BIR_YIL) return `max-age ${sure} saniye, bir yildan kisa`; if (!/includeSubDomains/i.test(deger)) return 'includeSubDomains yok, alt alanlar disarida'; return null; }, }, { ad: 'icerik guvenlik politikasi', denetle: (b) => { const deger = b['content-security-policy']; if (!deger) return 'Content-Security-Policy yok'; if (/script-src[^;]*'unsafe-inline'/.test(deger)) return "script-src icinde 'unsafe-inline' var"; if (!/frame-ancestors/.test(deger)) return 'frame-ancestors yonergesi yok'; return null; }, }, { ad: 'cerceveleme', denetle: (b) => b['x-frame-options'] || /frame-ancestors/.test(b['content-security-policy'] ?? '') ? null : 'cerceveleme sinirlanmamis', }, { ad: 'tur tahmini', denetle: (b) => (b['x-content-type-options'] === 'nosniff' ? null : 'X-Content-Type-Options: nosniff yok'), }, { ad: 'referans politikasi', denetle: (b) => { const deger = b['referrer-policy']; if (!deger) return 'Referrer-Policy yok'; const gevsek = ['unsafe-url', 'no-referrer-when-downgrade', 'origin-when-cross-origin']; return gevsek.includes(deger) ? `gevsek deger: ${deger}` : null; }, }, { ad: 'kaynak paylasim politikasi', denetle: (b) => (b['cross-origin-resource-policy'] ? null : 'Cross-Origin-Resource-Policy yok'), }, { ad: 'oturum cerezi', denetle: (b) => { const deger = b['set-cookie']; if (!deger) return null; const eksik = ['HttpOnly', 'Secure', 'SameSite'].filter((n) => !new RegExp(n, 'i').test(deger)); return eksik.length ? `cerez nitelikleri eksik: ${eksik.join(', ')}` : null; }, }, ]; function denetle(ad, basliklar) { const bulgular = KURALLAR.map((k) => [k.ad, k.denetle(basliklar)]).filter(([, b]) => b !== null); console.log(`\n${ad}: ${bulgular.length} bulgu`); for (const [kural, bulgu] of bulgular) console.log(' -', `${kural}:`, bulgu); if (bulgular.length === 0) console.log(' - bulgu yok'); } const ilkYayin = { 'content-type': 'text/html; charset=utf-8', 'strict-transport-security': 'max-age=86400', 'content-security-policy': "default-src 'self'; script-src 'self' 'unsafe-inline'", 'referrer-policy': 'unsafe-url', 'set-cookie': 'olcum_oturum=abc; Path=/', }; const duzeltilmis = { 'content-type': 'text/html; charset=utf-8', 'strict-transport-security': 'max-age=31536000; includeSubDomains', 'content-security-policy': "default-src 'self'; script-src 'self' 'nonce-r4k2'; frame-ancestors 'none'", 'x-frame-options': 'DENY', 'x-content-type-options': 'nosniff', 'referrer-policy': 'strict-origin-when-cross-origin', 'cross-origin-resource-policy': 'same-origin', 'set-cookie': 'olcum_oturum=abc; Path=/; HttpOnly; Secure; SameSite=Lax', }; denetle('ilk yayin', ilkYayin); denetle('duzeltilmis yapilandirma', duzeltilmis);
$ node basliklar.mjs ilk yayin: 7 bulgu - tasima guvenligi: max-age 86400 saniye, bir yildan kisa - icerik guvenlik politikasi: script-src icinde 'unsafe-inline' var - cerceveleme: cerceveleme sinirlanmamis - tur tahmini: X-Content-Type-Options: nosniff yok - referans politikasi: gevsek deger: unsafe-url - kaynak paylasim politikasi: Cross-Origin-Resource-Policy yok - oturum cerezi: cerez nitelikleri eksik: HttpOnly, Secure, SameSite duzeltilmis yapilandirma: 0 bulgu - bulgu yok
İlk yapılandırmanın kusurları tek tek küçüktür ve hiçbiri uygulamayı bozmaz: taşıma kuralının süresi kısadır, politika satır içi koda izin verir, çerçeveleme sınırlanmamıştır, oturum çerezi üç niteliğini de taşımaz. Bulgu listesi bunları tek bir çalıştırmada görünür kılar.
Bu denetimin değeri, sürekli çalıştırılmasındadır. Yayın öncesi bir adım olarak çalıştırıldığında, başlık düşüren bir yapılandırma değişikliği kendini bir sonraki güvenlik gözden geçirmesinde değil, aynı gün gösterir. Kural kümesi de zamanla değişir; yeni bir kural eklendiğinde bulgu listesinin uzaması beklenen davranıştır.
Özet
- Güvenlik başlıkları sunucu yapılandırmasında yaşar ve eksiklikleri hiçbir işlevi bozmadığı için sessizce oluşur.
Strict-Transport-Securityilk istek boşluğunu kapatır;includeSubDomainsolmadan alt alanlar korumasız kalır.- Çerçeveleme
X-Frame-Optionsveyaframe-ancestorsyönergesiyle sınırlanır; ikincisi kaynak listesi kabul ettiği için daha ayrıntılıdır. Referrer-Policyyol ve sorgu bilgisinin dışarı sızmasını daraltır;X-Content-Type-Options: nosnifftür tahminini kapatır.- Başlık kümesini denetleyen bir kural çözümleyicisi, düşen bir başlığı aynı gün görünür kılar; denetim yayın akışının bir adımı olarak çalıştırılır.
Sonraki Adım
Buraya kadarki savunmalar uygulamanın kendi kodu ve kendi sunucusu üzerinde kuruldu. Ölçüm arayüzü ise kendi yazmadığı kodu da çalıştırır: harita çerçevesi, ölçüm grafiğini çizen dış betik, bağımlılık ağacındaki yüzlerce paket. Bu kodun her satırı, uygulamanın kaynağının yetkileriyle çalışır. Sonraki ders üçüncü taraf kodun oluşturduğu riski, tedarik zinciri boyunca nerede oluştuğunu ve alt kaynak bütünlüğü ile nasıl daraltılabileceğini ele alır.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.