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.
- Komut dosyası değiştirme:
<script src>
ve<script>
öğelerinin metin içeriğini ayarlama. - Bir dizeden HTML oluşturma:
- Eklenti içeriği yürütme:
- Çalışma zamanı JavaScript kodu derlemesi:
eval
setTimeout
setInterval
new Function()
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:
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;
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.
el.textContent = ''; const img = document.createElement('img'); img.src = 'xyz.jpg'; el.appendChild(img);
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, '<')
});
}
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; // '<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.