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ı sunar. Güvenilir Türler, henüz desteklemeyen tarayıcılar için polyfill olarak kullanılabilir.
Arka plan
DOM XSS, uzun yıllardır en yaygın ve tehlikeli web güvenlik açıklarından biri olmuştur.
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 temel nedeni, JavaScript kodunun kullanıcı tarafından kontrol edilen içerikle tehlikeli işlevler çağırması nedeniyle istemcidedir.
Sunucu tarafı XSS'yi önlemek için dizeleri birleştirerek HTML oluşturmayın. Daha fazla hata azaltma için bunun yerine güvenli bağlama dayalı otomatik kaçış karakteri ekleme şablon kitaplıklarını ve tek seferlik anahtara dayalı İçerik Güvenliği Politikası'nı kullanın.
Artık tarayıcılar, Güvenilir Türleri kullanarak istemci taraflı DOM tabanlı XSS'yi önlemeye de yardımcı olabilir.
API'ye giriş
Güvenilir Türleri, aşağıdaki riskli akış işlevlerini kilitleyerek çalışır. Tarayıcı tedarikçileri ve web çerçeveleri, güvenlik nedeniyle bu özellikleri kullanmamanızı önerdiğinden bazılarını zaten biliyor olabilirsiniz.
- Komut dosyası değiştirme:
<script src>
ve<script>
öğelerinin metin içeriğini ayarlama. - Dizeden HTML oluşturma:
- Eklenti içeriğini yürütme:
- Çalışma zamanı JavaScript kodu derlemesi:
eval
setTimeout
setInterval
new Function()
Güvenilir Türlerde, verileri bu akış işlevlerine aktarmadan önce işleme almanız gerekir. Tarayıcı, verilerin güvenilir olup olmadığını bilmediği için yalnızca bir 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ü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ı ihlali raporlarına 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 bir ihlal her 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 ihlallerini düzeltmek için birkaç seçenek vardır. Sorunlu kodu kaldırabilir, 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:
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, aktarma işlevlerine iletebileceğiniz Güvenilir Türleri zaten oluşturur. Örneğin, bir HTML snippet'ini temizlemek ve XSS yüklerini kaldırmak için DOMPurify'i 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 temizlenmiş HTML'yi bir TrustedHTML
nesnesine sarmalayarak 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. Bu gibi durumlarda, Güvenilir Tür nesnesi kendiniz 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, '<')
});
}
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; // '<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 koymaya 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 bu açığı daha da azaltabilirsiniz.