Web geliştiricileri için Site İzolasyonu

Masaüstünde Chrome 67'de Site İzolasyonu adlı yeni bir özellik varsayılan olarak etkindir. Bu makalede, Site İzolasyonunun ne olduğu, neden gerekli olduğu ve web geliştiricilerin neden bu konuda bilgi sahibi olması gerektiği açıklanmaktadır.

Site izolasyonu nedir?

İnternette kedi videoları izleyebilir ve kripto para cüzdanlarını yönetebilirsiniz. Ancak fluffycats.example'nin değerli kripto paralarınıza erişmesini istemezsiniz. Neyse ki web siteleri, aynı kaynak politikası sayesinde genellikle tarayıcıda birbirlerinin verilerine erişemez. Yine de kötü amaçlı web siteleri, diğer web sitelerine saldırmak için bu politikayı atlatmaya çalışabilir. Ayrıca, aynı kaynak politikasını uygulayan tarayıcı kodunda zaman zaman güvenlik hataları bulunur. Chrome Ekibi, bu tür hataları mümkün olduğunca hızlı bir şekilde düzeltmeyi amaçlamaktadır.

Site İzolasyonu, Chrome'daki bir güvenlik özelliğidir. Bu özellik, bu tür saldırıların başarılı olma olasılığını azaltmak için ek bir savunma hattı sunar. Bu özellik, farklı web sitelerindeki sayfaların her zaman farklı işlemlere yerleştirilmesini sağlar. Bu işlemler, her biri işlemin yapabileceği işlemleri sınırlayan bir korumalı alanda çalışır. Ayrıca, işlemin diğer sitelerden belirli türde hassas veriler almasını engeller. Sonuç olarak, site izolasyonu sayesinde kötü amaçlı bir web sitesinin Spectre gibi spekülatif yan kanal saldırılarını kullanarak diğer sitelerden veri çalması çok daha zordur. Chrome ekibi ek yaptırımları tamamladıkça Site İzolasyon özelliği, saldırganın sayfası kendi işleminde bazı kuralları ihlal edebilse bile yardımcı olacaktır.

Site izolasyonu, güvenilmeyen web sitelerinin diğer web sitelerindeki hesaplarınızdan bilgi erişmesini veya bu bilgileri çalmasını etkili bir şekilde zorlaştırır. Yakın zamandaki Meltdown ve Spectre yan kanal saldırıları gibi çeşitli güvenlik hatası türlerine karşı ek koruma sağlar.

Site izolasyonu hakkında daha fazla bilgi için Google Güvenlik blogundaki makalemizi inceleyin.

Kaynaklar Arası Okuma Engelleme

Tüm siteler arası sayfalar ayrı işlemlere yerleştirilmiş olsa bile sayfalar, resim ve JavaScript gibi bazı siteler arası alt kaynakları meşru bir şekilde isteyebilir. Kötü amaçlı bir web sayfası, banka bakiyeniz gibi hassas veriler içeren bir JSON dosyası yüklemek için <img> öğesini kullanabilir:

<img src="https://your-bank.example/balance.json" />
<!-- Note: the attacker refused to add an `alt` attribute, for extra evil points. -->

Site yalıtımı olmadan JSON dosyasının içeriği, oluşturma işleminin belleğine ulaşır. Bu noktada oluşturma işlemi, geçerli bir resim biçimi olmadığını fark eder ve resim oluşturmaz. Ancak saldırgan, bu bellek parçasını okumak için Spectre gibi bir güvenlik açığından yararlanabilir.

Saldırgan, hassas verileri belleğe kaydetmek için <img> yerine <script>'ü de kullanabilir:

<script src="https://your-bank.example/balance.json"></script>

Cross-Origin Read Blocking (CORB), balance.json içeriğinin MIME türüne göre oluşturma işlemi belleğine girmesini engelleyen yeni bir güvenlik özelliğidir.

CORB'nin işleyiş şeklini inceleyelim. Bir web sitesi, sunucudan iki tür kaynak isteyebilir:

  1. HTML, XML veya JSON dokümanları gibi veri kaynakları
  2. Resim, JavaScript, CSS veya yazı tipleri gibi medya kaynakları

Bir web sitesi, kendi kaynağından veya izin verici CORS başlıkları (ör. Access-Control-Allow-Origin: *) içeren diğer kaynaklardan veri kaynakları alabilir. Öte yandan, medya kaynakları izin verilen CORS başlıkları olmadan bile herhangi bir kaynaktan dahil edilebilir.

CORB, aşağıdaki durumlarda oluşturma işleminin kaynakta çapraz veri kaynağı (ör. HTML, XML veya JSON) almasını engeller:

  • Kaynakta X-Content-Type-Options: nosniff üstbilgisi var
  • CORS, kaynağa erişime açıkça izin vermiyor

Kaynaklar arası veri kaynağında X-Content-Type-Options: nosniff üstbilgisi ayarlanmamışsa CORB, HTML, XML veya JSON olup olmadığını belirlemek için yanıt gövdesini koklamaya çalışır. Bazı web sunucuları yanlış yapılandırıldığı ve resimleri örneğin text/html olarak yayınladığı için bu gereklidir.

CORB politikası tarafından engellenen veri kaynakları işleme boş olarak sunulur ancak istek arka planda gerçekleşmeye devam eder. Sonuç olarak, kötü amaçlı bir web sayfasının siteler arası verileri işlemine çekmesi zordur.

Optimum güvenlik için ve CORB'den yararlanmak üzere aşağıdakileri yapmanızı öneririz:

  • Yanıtları doğru Content-Type üstbilgisiyle işaretleyin. (Örneğin, HTML kaynakları text/html olarak, JSON kaynakları JSON MIME türü ile ve XML kaynakları XML MIME türü ile sunulmalıdır.)
  • X-Content-Type-Options: nosniff üstbilgisini kullanarak koku alma özelliğini devre dışı bırakın. Bu başlık olmadan Chrome, türün doğru olduğunu onaylamak için hızlı bir içerik analizi yapar. Ancak bu analiz, JavaScript dosyaları gibi öğelerin engellenmesini önlemek için yanıtlara izin verme yönünde hata yaptığından, doğru şeyi kendiniz doğrulamak daha iyidir.

Daha fazla bilgi için web geliştiricileri için CORB makalesine veya CORB hakkındaki ayrıntılı açıklamamıza göz atın.

Web geliştiricileri site izolasyonunu neden önemsemelidir?

Site izolasyonu, çoğu zaman web geliştiricilerine doğrudan gösterilmeyen, perde arkasında çalışan bir tarayıcı özelliğidir. Örneğin, öğrenilecek yeni bir web'e açık API yoktur. Genel olarak, web sayfaları Site İzolasyonu ile veya Site İzolasyonu olmadan çalıştırıldığında fark edemez.

Ancak bu kuralın bazı istisnaları vardır. Site izolasyonunu etkinleştirmek, web sitenizi etkileyebilecek birkaç küçük yan etkiyle birlikte gelir. Bilinen site izolasyonu sorunlarının bir listesini tutuyoruz ve en önemlilerini aşağıda ayrıntılı olarak açıklıyoruz.

Tam sayfa düzeni artık senkronize değil

Site izolasyonu ile bir sayfanın çerçeveleri artık birden fazla işleme yayılabileceğinden, tam sayfa düzeninin eşzamanlı olması artık garanti edilmez. Bu durum, sayfadaki tüm çerçevelere hemen yayılacağını varsaydığı bir sayfa düzeni değişikliğini etkiler.

Örneğin, social-widget.example adresinde barındırılan bir sosyal widget ile iletişim kuran fluffykittens.example adlı bir web sitesini ele alalım:

<!-- https://fluffykittens.example/ -->
<iframe src="https://social-widget.example/" width="123"></iframe>
<script>
  const iframe = document.querySelector('iframe');
  iframe.width = 456;
  iframe.contentWindow.postMessage(
    // The message to send:
    'Meow!',
    // The target origin:
    'https://social-widget.example'
  );
</script>

İlk başta, sosyal widget'ın <iframe> genişliği 123 pikseldir. Ancak FluffyKittens sayfası, genişliği 456 piksele değiştirir (düzenlemeyi tetikler) ve sosyal widget'a aşağıdaki kodu içeren bir mesaj gönderir:

<!-- https://social-widget.example/ -->
<script>
  self.onmessage = () => {
    console.log(document.documentElement.clientWidth);
  };
</script>

Sosyal widget, postMessage API aracılığıyla bir mesaj aldığında kök <html> öğesinin genişliğini günlüğe kaydeder.

Hangi genişlik değeri günlüğe kaydedilir? Chrome Site İzolasyonu'nu etkinleştirmeden önce yanıt 456 idi. document.documentElement.clientWidth öğesine erişmek, Chrome'un Site İzolasyonu'nu etkinleştirmeden önce senkronize olan düzeni zorlar. Ancak Site İzolasyonu etkinleştirildiğinde, çapraz kaynaklı sosyal widget'ın yeniden düzenlenmesi artık ayrı bir işlemde eşzamansız olarak gerçekleşir. Bu nedenle, yanıt artık 123 (eski width değeri) olabilir.

Bir sayfa, kaynakta farklı bir <iframe> öğesinin boyutunu değiştirip ona bir postMessage gönderirse Site İzolasyonu'nda alıcı çerçeve, mesajı alırken henüz yeni boyutunu bilmiyor olabilir. Daha genel olarak, bir düzen değişikliğinin sayfadaki tüm çerçevelere hemen yayıldığını varsayan sayfalar bu durumda bozulabilir.

Bu örnekte daha sağlam bir çözüm, width değerini üst çerçevede ayarlayıp resize etkinliğini dinleyerek <iframe>'teki bu değişikliği algılayacaktır.

Yükleme işleyicileri daha sık zaman aşımı yaşayabilir

Bir çerçeve gezindiğinde veya kapandığında, eski doküman ve içine yerleştirilmiş tüm alt çerçeve dokümanları unload işleyicilerini çalıştırır. Yeni gezinme aynı oluşturma işleminde gerçekleşirse (ör. aynı kaynaktan gezinme için) eski dokümanın ve alt çerçevelerinin unload işleyicileri, yeni gezinmenin bağlanmasına izin vermeden önce keyfi olarak uzun bir süre çalışabilir.

addEventListener('unload', () => {
  doSomethingThatMightTakeALongTime();
});

Bu durumda, tüm çerçevelerdeki unload işleyicileri çok güvenilirdir.

Ancak site izolasyonu olmasa bile bazı ana çerçeve gezinmeleri işlemler arasıdır ve bu durum, kaldırma işleyici davranışını etkiler. Örneğin, adres çubuğuna URL'yi yazarak old.example adresinden new.example adresine giderseniz new.example adresine gitme işlemi yeni bir işlemde gerçekleşir. old.example ve alt çerçevelerinin boşaltma işleyicileri, new.example sayfası gösterildikten sonra arka planda old.example işleminde çalışır ve belirli bir zaman aşımı içinde bitmezse eski boşaltma işleyicileri sonlandırılır. Boşaltma işleyicileri zaman aşımından önce tamamlanmayabileceğinden, boşaltma davranışı daha az güvenilirdir.

Site izolasyonu sayesinde, siteler arası tüm gezinmeler işlemler arası hale gelir. Böylece farklı sitelerdeki dokümanlar birbirleriyle işlem paylaşmaz. Sonuç olarak, yukarıdaki durum daha fazla durumda geçerli olur ve <iframe> öğelerindeki boşaltma işleyicileri genellikle yukarıda açıklanan arka plan ve zaman aşımı davranışlarına sahiptir.

Site izolasyonundan kaynaklanan bir diğer fark, boşaltma işleyicilerinin yeni paralel sıralamasıdır: Site izolasyonu olmadan boşaltma işleyicileri, çerçeveler arasında katı bir yukarıdan aşağıya sırayla çalışır. Ancak Site İzolasyonu'nda, boşaltma işleyicileri farklı işlemlerde paralel olarak çalışır.

Bunlar, Site İzolasyonu'nu etkinleştirmenin temel sonuçlarıdır. Chrome ekibi, mümkün olduğunda yaygın kullanım alanları için boşaltma işleyicilerinin güvenilirliğini iyileştirmek üzere çalışıyor. Alt çerçeveyi boşaltma işleyicilerinin henüz belirli özellikleri kullanamadığı hatalardan da haberdarız ve bu sorunları çözmek için çalışıyoruz.

Kaldırma işleyicileri için önemli bir durum, oturum sonu ping'leri göndermektir. Bu işlem genellikle aşağıdaki şekilde yapılır:

addEventListener('pagehide', () => {
  const image = new Image();
  img.src = '/end-of-session';
});

Bu değişiklik göz önüne alındığında daha sağlam ve daha iyi bir yaklaşım, bunun yerine navigator.sendBeacon kullanmaktır:

addEventListener('pagehide', () => {
  navigator.sendBeacon('/end-of-session');
});

İstek üzerinde daha fazla kontrole ihtiyacınız varsa Getirme API'sinin keepalive seçeneğini kullanabilirsiniz:

addEventListener('pagehide', () => {
  fetch('/end-of-session', {keepalive: true});
});

Sonuç

Site izolasyonu, her siteyi kendi işleminde izole ederek güvenilmeyen web sitelerinin diğer web sitelerindeki hesaplarınıza erişmesini veya bu hesaplardaki bilgileri çalmasını zorlaştırır. Bu kapsamda CORB, hassas veri kaynaklarını oluşturma işleminden uzak tutmaya çalışır. Yukarıdaki önerilerimiz, bu yeni güvenlik özelliklerinden en iyi şekilde yararlanmanızı sağlar.

Bu makalenin taslak sürümünü okuyup geri bildirimde bulunan Alex Moshchuk, Charlie Reis, Jason Miller, Nasko Oskov, Philip Walton, Shubhi Panicker ve Thomas Steiner'e teşekkür ederiz.