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.
- Komut dosyası manipülasyonu:
<script src>
ve<script>
öğelerinin metin içeriğini ayarlama. - Bir dizeden HTML oluşturma:
- Eklenti içeriğini yürütme:
- Çalışma zamanı JavaScript kodu derlemesi:
eval
setTimeout
setInterval
new Function()
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:
anElement.innerHTML = location.href;
Verilerin güvenli bir şekilde işlendiğini belirtmek için özel bir nesne (Güvenilir Tür) oluşturun.
anElement.innerHTML = aTrustedHTML;
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:
el.textContent = ''; const img = document.createElement('img'); img.src = 'xyz.jpg'; el.appendChild(img);
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, '<')
});
}
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 onerror=alert(1)>');
console.log(escaped instanceof TrustedHTML); // true
el.innerHTML = escaped; // '<img src=x onerror=alert(1)>'
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.