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 (bir kullanıcı adı veya URL parçasından alınan bir yönlendirme URL'si gibi) gelen veriler bir havuz'a (eval() gibi bir işleve veya rastgele JavaScript kodu yürütebilen .innerHTML gibi bir özellik belirleyiciye) ulaştığında ortaya çıkar.

DOM XSS, en yaygın web güvenliği güvenlik açıklarından biridir. Geliştirici ekiplerinin, bunu uygulamalarında yanlışlıkla kullanıma sunması sık karşılaşılan bir durumdur. Güvenilir Türler, tehlikeli web API işlevlerini varsayılan olarak güvenli hale getirerek size yazma, güvenlik incelemesi ve uygulamaları DOM XSS güvenlik açıklarından uzak tutmanızı sağlayacak araçlar sunar. Güvenilir Türler, henüz desteklenmeyen tarayıcılar için polyfill olarak kullanılabilir.

Arka plan

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

İki tür siteler arası komut dosyası çalıştırma vardır. Bazı XSS güvenlik açıklarına, web sitesini oluşturan HTML kodunu güvenli olmayan bir şekilde oluşturan sunucu tarafı kodu neden olur. 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, 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ş

Trusted Types, aşağıdaki riskli havuz 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 dize kullanmak başarısız olur:

Yapılmaması gerekenler
anElement.innerHTML  = location.href;
Güvenilir Türler etkinleştirildiğinde tarayıcı, bir TypeError hatası gönderir 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.

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

Güvenilir Türler, uygulamanızın DOM XSS saldırı yüzeyini önemli ölçüde azaltır. Güvenlik incelemelerini basitleştirir ve kodunuzu tarayıcıda derlerken, analiz ederken veya çalışma zamanında gruplarken yapılan tür tabanlı güvenlik kontrollerini zorunlu kılmanızı sağlar.

Trusted Types nasıl kullanılır?

İç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ıya özel günlük kaydı ve hata ayıklama ihlalleri ekleyebilirsiniz:

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 rapor amaçlı bir İGP başlığı ekleyin

Güvenilir Türler'e taşımak istediğiniz dokümanlara aşağıdaki HTTP Yanıtı başlığını 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 sitesine bildiriliyor, ancak web sitesi çalışmaya devam ediyor. Bir sonraki bölümde //my-csp-endpoint.example'in işleyiş şekli açıklanmaktadır.

Trusted Types ihlallerini tanımlama

Artık Trusted Types bir ihlal algıladığında, tarayıcı yapılandırılmış bir report-uri'a rapor gönderir. Örneğin, uygulamanız innerHTML hizmetine 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, https://my.url.example/script.js içindeki 39. satırdaki innerHTML öğesinin, <img src=x ile başlayan dizeyle çağrıldığını belirtir. Bu bilgiler, kodun hangi kısımlarının DOM XSS'i kullanıma sunabileceğini ve değiştirilmesi gerektiğini daraltmanıza yardımcı olur.

İhlalleri giderin

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.

Rahatsız edici kodu yeniden yazma

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 = '<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, TrustedHTML nesnesine sarmalanmış arındırılmış HTML döndürür.

Güvenilir Tür politikası oluşturma

Bazen ihlale neden olan kodu kaldıramazsınız ve değeri arındıracak ve sizin için Güvenilir Tür oluşturabileceğiniz bir kitaplık yoktur. Böyle durumlarda, kendiniz Güvenilir Tür nesnesi oluşturabilirsiniz.

İlk olarak bir politika oluşturun. Politikalar, Trusted Types'ın girişlerinde belirli güvenlik kurallarını zorunlu kılan 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 adında bir politika oluşturur. Tanımlanan kurallar, yeni HTML öğelerinin oluşturulmasını önlemek için HTML-çıkış < karakterlerini kullanır.

Politikayı şu şekilde kullanın:

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

Varsayılan bir politika kullan

Örneğin, bir CDN'den üçüncü taraf kitaplığı yüklüyorsanız bazen rahatsız edici kodu değiştiremezsiniz. Bu durumda, varsayılan politikayı 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, bir dizenin yalnızca Güvenilir Türü kabul eden bir havuzda kullanıldığı her yerde kullanılır.

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

Uygulamanız artık ihlal oluşturmadığında Güvenilir Türleri 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, DOM XSS güvenlik açığı oluşturabilecek tek şey, politikalarınızdan birindeki koddur. Politika oluşturmayı sınırlandırarak bunu daha da fazla kilitleyebilirsiniz.

Daha fazla bilgi