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ştiricilerinin neden bundan haberdar 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 diğer sitelerden veri çalmak için Spectre gibi spekülatif yan kanal saldırılarını kullanması ç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> 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 Access-Control-Allow-Origin: * gibi izin verici CORS başlıklarıyla 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şturucu işleminin kaynaklar arası 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.

İstek arka planda gerçekleştirilse de CORB politikası tarafından engellenen veri kaynakları sürece boş olarak sunulur. Sonuç olarak, kötü amaçlı bir web sayfası, siteler arası verileri çalmak üzere işleme almakta zorlanır.

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 başlığını kullanarak yoklama ö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ç belirsiz yan etkiyle birlikte gelir. Bilinen Site İzolasyon 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>

Başlangıç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. Dolayısıyla, yanıt artık 123 (eski width değeri) olabilir.

Bir sayfa, kaynaktan bağımsız <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 etkili bir çözüm üst çerçevede width değerini ayarlar ve bir resize etkinliğini dinleyerek <iframe> öğesindeki bu değişikliği algılar.

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

Bir çerçeve gezinirken veya kapatıldığında, hem eski doküman hem de içine yerleştirilmiş tüm alt çerçeve dokümanları unload işleyicisini çalıştırır. Yeni gezinme aynı oluşturucu işleminde (ör. aynı kaynaktan gezinme için) gerçekleşiyorsa eski dokümanın ve alt çerçevelerinin unload işleyicileri, yeni gezinmenin kaydedilmesine izin vermeden önce rastgele uzun bir süre çalışabilir.

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

Bu durumda, tüm karelerdeki unload işleyicileri son derece 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 tamamlanmazlarsa eski boşaltma işleyicileri sonlandırılır. Kaldırma işleyicileri zaman aşımından önce bitmeyebileceği için kaldırma 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>'lerdeki 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 da, 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 ile kaldırma işleyicileri farklı süreçlerde paralel olarak çalışır.

Bunlar, Site İzolasyonu'nun etkinleştirilmesinin 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 doğrultusunda daha etkili bir yaklaşım, onun 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.