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

  • Chrome: 83.
  • Edge: 83.
  • Firefox: Desteklenmez.
  • Safari: Desteklenmez.

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 eval() gibi bir işlev veya .innerHTML gibi rastgele JavaScript kodunu çalıştırabilen bir özellik ayarlayıcı olan bir alıcıya ulaştığında gerçekleşir.

DOM XSS, en yaygın web güvenlik açıklarından biridir ve geliştirici ekiplerinin bu açıkları uygulamalarına yanlışlıkla dahil etmesi yaygındır. Güvenilir Türleri, tehlikeli web API işlevlerini varsayılan olarak güvenli hale getirerek uygulamaları DOM XSS güvenlik açıklarından uzak tutmak, yazmak ve güvenlik incelemesi yapmak için gereken araçları sağlar. Güvenilir Türler, henüz desteklenmeyen tarayıcılar için çoklu dolgu olarak kullanılabilir.

Arka plan

DOM XSS yıllardır en yaygın ve tehlikeli web güvenliği açıklarından biri.

Siteler arası komut dosyası çalıştırma işleminin iki türü vardır. Bazı XSS güvenlik açıkları, web sitesini oluşturan HTML kodunu güvenli olmayan bir şekilde oluşturan sunucu tarafı kodundan kaynaklanır. Diğerlerinin istemcide temel bir nedeni vardır. JavaScript kodu, kullanıcı tarafından kontrol edilen içeriğe sahip tehlikeli işlevleri çağırır.

Sunucu tarafı XSS'yi önlemek için dizeleri birleştirerek HTML oluşturmayın. Bunun yerine, ek hata azaltma için tek seferlik rastgele sayı tabanlı İçerik Güvenliği Politikası'nın yanı sıra güvenli bir bağlama dayalı otomatik şablon oluşturma kitaplıkları kullanın.

Artık tarayıcılar, Güvenilir Türleri kullanarak istemci taraflı DOM tabanlı XSS'lerin önlenmesine de yardımcı olabilir.

API'ye giriş

Güvenilir Türleri, aşağıdaki riskli akış işlevlerini kilitleyerek çalışır. Tarayıcı satıcıları ve web çerçeveleri güvenlik nedeniyle bu özellikleri kullanmaktan kaçınmanıza neden olduğundan bu değişikliklerden bazılarını zaten tanıyor olabilirsiniz.

Trusted Types, verileri bu havuz işlevlerine iletmeden önce işlemenizi gerektirir. Tarayıcı, verilerin güvenilir olup olmadığını bilmediği için yalnızca bir dize kullanmak başarısız olur:

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

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

Yapılması gerekenler
anElement.innerHTML = aTrustedHTML;
  
Güvenilir Türler etkinleştirildiğinde tarayıcı, HTML snippet'leri bekleyen alıcılar için bir TrustedHTML nesnesini kabul eder. Diğer hassas havuzlar için TrustedScript ve TrustedScriptURL nesneleri de mevcuttur.

Güvenilir Türleri, uygulamanızın DOM XSS saldırıya açık alanını önemli ölçüde azaltır. Güvenlik incelemelerini basitleştirir ve kodunuzu derleme, linting veya çalışma zamanında paketleme sırasında yapılan tür tabanlı güvenlik kontrollerini tarayıcıda zorunlu kılmanıza olanak tanır.

Güvenilir Türleri kullanma

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

Açık kaynak reporting-api-processor veya go-csp-collector gibi bir rapor toplayıcı dağıtabilir ya da ticari eşdeğerlerinden birini kullanabilirsiniz. Ayrıca, ReportingObserver kullanarak tarayıcıda özel günlük kaydı ekleyebilir ve ihlalleri hata ayıklayabilirsiniz:

const observer = new ReportingObserver((reports, observer) => {
    for (const report of reports) {
        if (report.type !== 'csp-violation' ||
            report.body.effectiveDirective !== 'require-trusted-types-for') {
            continue;
        }

        const violation = report.body;
        console.log('Trusted Types Violation:', violation);

        // ... (rest of your logging and reporting logic)
    }
}, { buffered: true });

observer.observe();

veya bir etkinlik işleyici ekleyerek:

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

Yalnızca raporlama için CSP üstbilgisi ekleme

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

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

Tüm ihlaller //my-csp-endpoint.example'e bildirildi ancak web sitesi çalışmaya devam ediyor. //my-csp-endpoint.example'ün işleyiş şekli sonraki bölümde açıklanmıştır.

Trusted Types ihlallerini belirleme

Bundan sonra, Güvenilir Türler her ihlal tespit ettiğinde tarayıcı, yapılandırılmış bir report-uri'e rapor gönderir. Örneğin, uygulamanız innerHTML adresine bir dize iletirse 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 içinde innerHTML'un <img src=x ile başlayan dizeyle çağrıldığını belirtir. Bu bilgiler, DOM XSS'ye neden olabilecek ve değiştirilmesi gereken kod bölümlerinin daraltılmasına yardımcı olacaktır.

İhlalleri düzeltme

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

Sorunlu kodu yeniden yazma

Uygun olmayan koda artık ihtiyaç duyulmuyor olabilir veya ihlallere neden olan işlevler olmadan yeniden yazılabilir:

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

Kitaplık kullanma

Bazı kitaplıklar, havuz işlevlerine iletebileceğiniz Trusted Type'ları zaten oluşturur. Örneğin, bir HTML snippet'ini temizlemek ve XSS yüklerini kaldırmak için DOMPurify'ı kullanabilirsiniz.

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

DOMPurify, Güvenilir Türleri destekler ve tarayıcının ihlal oluşturmaması için, bir TrustedHTML nesnesine sarmalanmış arındırılmış HTML döndürür.

Güvenilir Tür politikası oluşturma

Bazen ihlal oluşturan kodu kaldıramazsınız ve değeri temizleyip sizin için Güvenilir Tür oluşturacak bir kitaplık yoktur. Böyle durumlarda, kendiniz Güvenilir Tür nesnesi oluşturabilirsiniz.

Öncelikle bir politika oluşturun. Politikalar, girişlerinde belirli güvenlik kurallarını uygulayan Trusted Types fabrikalarıdı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ımlanan kurallar, yeni HTML öğelerinin oluşturulmasını önlemek için < karakterlerini HTML'de kaçar.

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 kullanma

Bazen, soruna neden olan kodu değiştiremezsiniz. Örneğin, bir CDN'den üçüncü taraf kitaplığı yüklüyorsanız. Bu durumda, varsayılan bir 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 Güvenilir Tür'ü kabul eden bir alıçta dize kullanıldığı her yerde kullanılır.

İçerik Güvenliği Politikası'nı uygulamaya geçme

Uygulamanız artık ihlal oluşturmadığında Güvenilir Türleri uygulamaya koyabilirsiniz:

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

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

Daha fazla bilgi