Güvenilir Türler ile DOM tabanlı siteler arası komut dosyası oluşturma güvenlik açıklarını önleyin

Krzysztof Kotowicz
Krzysztof Kotowicz

Tarayıcı Desteği

  • 83
  • 83
  • x
  • x

Kaynak

DOM tabanlı siteler arası komut dosyası çalıştırma (DOM XSS), kullanıcı tarafından kontrol edilen bir kaynaktan (ör. kullanıcı adı veya URL parçasından alınan yönlendirme URL'si) gelen veriler, rastgele JavaScript kodu yürütebilen eval() gibi bir işlev veya .innerHTML gibi bir özellik belirleyici olan bir havuza ulaştığında gerçekleşir.

DOM XSS, en yaygın web güvenliği güvenlik açıklarından biridir ve geliştirici ekiplerinin bunu uygulamalarında yanlışlıkla kullanıma sunması yaygın bir durumdur. Güvenilir Türler, tehlikeli web API işlevlerini varsayılan olarak güvenli hale getirerek size yazma ve güvenlik incelemesi araçları sunmanın yanı sıra uygulamalarda DOM XSS güvenlik açıklarından uzak durmanızı sağlayan araçlar sunar. Güvenilir Türler, henüz bunları desteklemeyen tarayıcılar için polyfill olarak kullanılabilir.

Arka plan

DOM XSS yıllardır en yaygın ve tehlikeli web güvenlik açıklarından biri olmuştur.

İki tür siteler arası komut dosyası vardır. Bazı XSS güvenlik açıkları, web sitesini oluşturan HTML kodunu güvenli olmayan bir şekilde oluşturan sunucu tarafı koddan kaynaklanır. Bazılarının ise istemcide, JavaScript kodunun kullanıcı tarafından kontrol edilen içeriğe sahip tehlikeli işlevler çağırmasına yol açan temel bir nedeni vardır.

Sunucu tarafı XSS'yi önlemek için dizeleri birleştirerek HTML oluşturmayın. Ek hataları azaltmak için tek seferlik bir İçerik Güvenliği Politikası ile birlikte, içeriğe dayalı otomatik kaçış şablonu için güvenli olan kitaplıklar kullanın.

Artık tarayıcılar Güvenilir Türler'i kullanarak istemci taraflı DOM tabanlı XSS'nin engellenmesine yardımcı olabilir.

API'ye giriş

Trusted Types, aşağıdaki riskli havuz işlevlerini kilitleyerek çalışır. Bu araçlardan bazılarını zaten tanıyor olabilirsiniz, çünkü tarayıcı tedarikçileri ve web çerçeveleri güvenlik nedeniyle sizi bu özelliklerden uzaklaştırır.

Güvenilir Türler, verileri bu havuz işlevlerine iletmeden önce işlemenizi gerektirir. Yalnızca dize kullanılması, tarayıcı verilerin güvenilir olup olmadığını bilmediği için başarısız olur:

Yapılmaması gerekenler
anElement.innerHTML  = location.href;
Güvenilir Türler etkinleştirildiğinde tarayıcı bir TypeError hatası verir ve dizeyle bir DOM XSS havuzunun kullanılmasını engeller.

Verilerin güvenli bir şekilde işlendiğini belirtmek için özel bir nesne (Güvenilir Tür) oluşturun.

Yapmanız gerekenler:
anElement.innerHTML = aTrustedHTML;
  
Trusted Types etkinleştirildiğinde, tarayıcı HTML snippet'leri bekleyen havuzlar için bir TrustedHTML nesnesini kabul eder. Diğer hassas havuzlar için TrustedScript ve TrustedScriptURL nesneleri de vardır.

Trusted Types, uygulamanızın DOM XSS saldırı yüzeyini önemli ölçüde azaltır. Güvenlik incelemelerini basitleştirir ve çalışma zamanında kodunuzu tarayıcıda derlerken, test ederken veya paket haline getirirken yapılan tür tabanlı güvenlik kontrollerini zorunlu kılmanıza olanak tanır.

Trusted Types nasıl kullanılır?

İçerik Güvenliği Politikası ihlal raporlarına hazırlanma

Açık kaynaklı go-csp-collector gibi bir rapor toplayıcıyı dağıtabilir veya ticari eşdeğerlerinden birini kullanabilirsiniz. Tarayıcıdaki ihlallerde hata ayıklama da yapabilirsiniz:

document.addEventListener('securitypolicyviolation',
    console.error.bind(console));

Yalnızca rapor amaçlı bir CSP başlığı ekleyin

Güvenilir Türlere taşımak istediğiniz belgelere aşağıdaki HTTP Yanıtı üstbilgisini ekleyin:

Content-Security-Policy-Report-Only: require-trusted-types-for 'script'; report-uri //my-csp-endpoint.example

Şimdi tüm ihlaller //my-csp-endpoint.example ekibine bildiriliyor ancak web sitesi çalışmaya devam ediyor. Sonraki bölümde //my-csp-endpoint.example özelliğinin işleyiş şekli açıklanmaktadır.

Trusted Types ihlallerini tespit edin

Şu andan itibaren, Güvenilir Türler her ihlal algıladığında, tarayıcı yapılandırılmış bir report-uri öğesine bir rapor gönderir. Örneğin, uygulamanız innerHTML öğesine bir dize ilettiğinde tarayıcı aşağıdaki raporu gönderir:

{
"csp-report": {
    "document-uri": "https://my.url.example",
    "violated-directive": "require-trusted-types-for",
    "disposition": "report",
    "blocked-uri": "trusted-types-sink",
    "line-number": 39,
    "column-number": 12,
    "source-file": "https://my.url.example/script.js",
    "status-code": 0,
    "script-sample": "Element innerHTML <img src=x"
}
}

Bu, 39. satırdaki https://my.url.example/script.js öğesinde <img src=x ile başlayan dizeyle innerHTML çağrıldığını belirtir. Bu bilgiler, kodun hangi bölümlerinin DOM XSS'i kullanıma sunduğunu ve değiştirmeniz gerektiğini daraltmanıza yardımcı olur.

İhlalleri giderin

Trusted Type ihlalini düzeltmek için birkaç seçenek vardır. Rahatsız edici kodu kaldırabilir, bir kitaplık kullanabilir, bir Trusted Type politikası oluşturabilir veya son çare olarak varsayılan bir politika oluşturabilirsiniz.

Soruna neden olan kodu yeniden yazın

Uygun olmayan kod artık gerekli olmayabilir veya ihlallere neden olan işlevler olmadan yeniden yazılabilir.

Yapmanız gerekenler:
el.textContent = '';
const img = document.createElement('img');
img.src = 'xyz.jpg';
el.appendChild(img);
Yapılmaması gerekenler
el.innerHTML = '';

Kitaplık kullanma

Bazı kitaplıklar halihazırda havuz işlevlerine iletebileceğiniz Güvenilir Türler oluşturmaktadır. Örneğin, XSS yüklerini kaldırarak bir HTML snippet'ini temizlemek için DOMPurify'ı kullanabilirsiniz.

import DOMPurify from 'dompurify';
el.innerHTML = DOMPurify.sanitize(html, {RETURN_TRUSTED_TYPE: true});

DOMPurify, Trusted Types'ı destekler ve tarayıcının ihlal oluşturmaması için bir TrustedHTML nesnesine sarılmış, temizlenmiş HTML döndürür.

Trusted Type politikası oluşturun

Bazen ihlale neden olan kodu kaldıramazsınız ve değeri başka bir şekilde temizleyip sizin için bir Güvenilir Tür oluşturan kitaplık yoktur. Bu gibi durumlarda, kendiniz bir Trusted Type nesnesi oluşturabilirsiniz.

Öncelikle bir politika oluşturun. Politikalar, Güvenilir Türler için belirli güvenlik kurallarını uygulayan fabrikalardır:

if (window.trustedTypes && trustedTypes.createPolicy) { // Feature testing
  const escapeHTMLPolicy = trustedTypes.createPolicy('myEscapePolicy', {
    createHTML: string => string.replace(/\</g, '&lt;')
  });
}

Bu kod, createHTML() işlevini kullanarak TrustedHTML nesneleri oluşturabilen myEscapePolicy adlı bir politika oluşturur. Tanımlı HTML kuralları, yeni HTML öğelerinin oluşturulmasını önlemek için < karakterinden çıkış yapar.

Politikayı şu şekilde kullanın:

const escaped = escapeHTMLPolicy.createHTML('<img src=x onerror=alert(1)>');
console.log(escaped instanceof TrustedHTML);  // true
el.innerHTML = escaped;  // '&lt;img src=x onerror=alert(1)>'

Varsayılan bir politika kullan

Bazen, örneğin bir CDN'den üçüncü taraf kitaplığı yüklüyorsanız rahatsız edici kodu değiştiremezsiniz. Bu durumda, varsayılan politika kullanın:

if (window.trustedTypes && trustedTypes.createPolicy) { // Feature testing
  trustedTypes.createPolicy('default', {
    createHTML: (string, sink) => DOMPurify.sanitize(string, {RETURN_TRUSTED_TYPE: true})
  });
}

default adlı politika, yalnızca Trusted Type'ı kabul eden bir havuzda bir dizenin kullanıldığı her yerde kullanılır.

Zorunlu İçerik Güvenliği Politikası'na geç

Uygulamanız artık ihlal oluşturmadığında Güvenilir Türler'i zorunlu kılmaya başlayabilirsiniz:

Content-Security-Policy: require-trusted-types-for 'script'; report-uri //my-csp-endpoint.example

Web uygulamanız ne kadar karmaşık olursa olsun, bir DOM XSS güvenlik açığına neden olabilecek tek şey politikalarınızdan birindeki koddur. Politika oluşturmayı sınırlandırarak bu kodu daha da kilitleyebilirsiniz.

Daha fazla bilgi