Siteler arası komut dosyası çalıştırma (XSS), bir web uygulamasına kötü amaçlı komut dosyaları yerleştirme kullanmaya devam ediyor.
İçerik Güvenliği Politikası (İGP)
XSS'yi azaltmaya yardımcı olan ek bir güvenlik katmanıdır. CSP'yi yapılandırmak için:
Content-Security-Policy
HTTP üstbilgisini bir web sayfasına ekleyin ve
Kullanıcı aracısının söz konusu sayfa için hangi kaynakları yükleyebileceğini kontrol eder.
Bu sayfada, XSS'yi azaltmak için nonce veya hash'lere dayalı bir CSP'nin nasıl kullanılacağı açıklanmaktadır. yaygın olarak kullanılan, ana makine izin verilenler listesi tabanlı ve genellikle sayfadan ayrılan CSP'ler yerine çoğu yapılandırmada atlanabildikleri için XSS'e maruz kalırlar.
Anahtar terim: Tek seferlik rastgele sayısı, bir öğeyi işaretlemek için kullanabileceğiniz rastgele bir sayıdır.
<script>
etiketi güvenilir olarak işaretlendi.
Anahtar terim: Karma işlevi, girdi dönüşümünü gerçekleştiren matematiksel bir işlevdir.
değerini karma adı verilen sıkıştırılmış sayısal bir değere dönüştürebilirsiniz. Karma oluşturma işlemi uygulamak için
(örneğin, SHA-256) kullanarak
<script>
etiketi güvenilir olarak işaretlendi.
Noce veya karmalara dayalı bir İçerik Güvenliği Politikası genellikle katı CSP değerleridir. Bir uygulama katı bir CSP kullandığında, HTML'yi bulan saldırganlar yerleştirme hataları, genellikle bunları tarayıcıyı Güvenli olmayan bir dokümanda kötü amaçlı komut dosyaları. Bunun nedeni yalnızca katı CSP'dir Oluşturulan doğru tek seferlik rastgele sayı değerine sahip, karma oluşturma işlemi uygulanmış komut dosyalarına veya Bu nedenle, saldırganlar doğru tek seferlik rastgele sayı bilmeden komut dosyasını çalıştıramaz. temel alabilir.
Neden katı bir CSP kullanmalısınız?
Sitenizde zaten script-src www.googleapis.com
gibi görünen bir İGP varsa
siteler arası için etkili olmayacaktır. Bu tür CSP'ler
İzin verilenler listesi CSP. Çok fazla özelleştirme gerektirirler ve
atlanabilir.
Kriptografik nonce'lara veya hash'lere dayalı katı CSP'ler bu tehlikelerden kaçınır.
Katı CSP yapısı
Temel bir katı İçerik Güvenliği Politikası, aşağıdaki HTTP yanıtlarının birini kullanır başlıklar:
Duyarlı olmayan sıkı CSP
Content-Security-Policy:
script-src 'nonce-{RANDOM}' 'strict-dynamic';
object-src 'none';
base-uri 'none';
![](https://web.dev/static/articles/strict-csp/image/er4BaGCJzBwDaESFKfZd.jpg?authuser=2&hl=tr)
Karma tabanlı katı CSP
Content-Security-Policy:
script-src 'sha256-{HASHED_INLINE_SCRIPT}' 'strict-dynamic';
object-src 'none';
base-uri 'none';
Aşağıdaki özellikler bunun gibi bir İGP'yi "katı" yapar ve dolayısıyla güvenlidir:
- Noce
'nonce-{RANDOM}'
veya'sha256-{HASHED_INLINE_SCRIPT}'
karmaları kullanıyor sitenin geliştiricisinin güvendiği<script>
etiketlerini belirtmek için Kullanıcının tarayıcısı. 'strict-dynamic'
Böylece, tek seferlik rastgele veya karma tabanlı bir CSP'yi otomatik olarak dağıtma güvenilir bir komut dosyasının oluşturduğu komut dosyalarının yürütülmesine olanak tanır. Bu ayrıca çoğu üçüncü taraf JavaScript kitaplığının ve widget'ının kullanılmasını engeller.- URL izin verilenler listelerini temel almadığından yaygın CSP atlamaları.
- Satır içi etkinlik işleyiciler veya
javascript:
gibi güvenilmeyen satır içi komut dosyalarını engeller. URI'lar. - Flash gibi tehlikeli eklentileri devre dışı bırakmak için
object-src
ürününü kısıtlar. base-uri
ürününü,<base>
etiketlerinin yerleştirilmesini engelleyecek şekilde kısıtlar. Bu durum, saldırganların göreli URL'lerden yüklenen komut dosyalarının konumlarını değiştirmesini engelleyebilir.
Katı bir İGP benimseyin
Katı bir CSP benimsemek için şunları yapmanız gerekir:
- Uygulamanızın tek seferlik mi yoksa karma tabanlı CSP mi ayarlaması gerektiğine karar verin.
- Katı CSP yapısı bölümünden CSP'yi kopyalayıp ayarlayın bir yanıt başlığı olarak kullanabilirsiniz.
- Kalıpları kaldırmak için HTML şablonlarını ve istemci tarafı kodunu yeniden düzenleme uyumlu değildir.
- CSP'nizi dağıtın.
Daha fazla bilgi için Lighthouse'u
(--preset=experimental
işaretiyle birlikte sürüm 7.3.0 ve sonraki sürümler) En İyi Uygulamalar denetimi
Bu süreç boyunca sitenizde İGP bulunup bulunmadığını ve bu içeriğin CSP olup olmadığını
XSS'ye karşı etkili olacak kadar katı olmalıdır.
![Deniz feneri
yaptırım modunda hiçbir İGP bulunamadığını belirten uyarı bildirimi.](https://web.dev/static/articles/strict-csp/image/lighthouse-report-warning-74f66e2ef76dc.png?authuser=2&hl=tr)
1. Adım: Tek seferlik veya karma tabanlı bir CSP'ye ihtiyacınız olup olmadığına karar verin
Katı CSP'nin iki türü şu şekilde işler:
Tek seferlik rastgele sayı tabanlı CSP
Ortalama olmayan bir CSP ile çalışma zamanında rastgele bir sayı oluşturur ve bunu CSP'nizi tanımlama ve sayfanızdaki tüm komut dosyası etiketiyle ilişkilendirmeniz gerekir. Bir saldırgan çalıştıramaz. Bunun nedeni, bunların doğru rastgele sayıyı tahmin edebilir. Bu yalnızca telefon araması üreten tahmin edilemez ve her yanıt için çalışma zamanında yeni oluşturulur.
Sunucuda oluşturulan HTML sayfaları için tek seferlik rastgele olmayan bir CSP kullanın. Bu sayfalarda her yanıt için yeni bir rastgele sayı oluşturabilirsiniz.
Karma tabanlı CSP
Karma tabanlı bir CSP için, her satır içi komut dosyası etiketinin karma değeri CSP'ye eklenir. Her komut dosyasının farklı bir karması vardır. Saldırganlar kötü amaçlı bir dosya içeremez veya çalıştıramaz komut dosyası yükleyebilirsiniz. Çünkü bu komut dosyasının karmasının gerekli olan CSP'dir.
Statik olarak sunulan HTML sayfaları veya önbelleğe alındı. Örneğin, tek sayfalık web için karma tabanlı bir CSP kullanabilirsiniz. Angular, React veya diğerleri gibi çerçevelerle oluşturulmuş diğer sunucu tarafında oluşturulmadan statik olarak sunulur.
2. Adım: Katı bir CSP belirleyin ve komut dosyalarınızı hazırlayın
CSP ayarlarken birkaç seçeneğiniz vardır:
- Yalnızca rapor modu (
Content-Security-Policy-Report-Only
) veya yaptırım modu (Content-Security-Policy
). Yalnızca rapor modunda, CSP çalışır, dolayısıyla sitenizdeki hiçbir şey bozulamaz, ancak hatalar görebilir ve her tür içeriği raporlayabilir. Yerel olarak, CSP'nizi ayarlamanın önemi yoktur, çünkü her iki mod da emin olun. Yaptırım modu, aşağıdakileri yapmanıza yardımcı olabilir: kaynaklarınız olacaktır çünkü bir kaynağı engellemek, sayfa bozuk görünüyor. Salt rapor modu işlemin ilerleyen aşamalarında en yararlı hale gelir (5. adıma bakın). - Üstbilgi veya HTML
<meta>
etiketi. Yerel geliştirme için<meta>
etiketi daha fazla olabilir CSP'nizde ayarlamalar yapmak ve sitenizi nasıl etkilediğini hızla görmek için uygundur. Ancak:- Daha sonra, CSP'nizi üretime dağıtacağınız zaman bir HTTP üstbilgisi ekleyin.
- İGP'nizi salt rapor modunda ayarlamak isterseniz bunu bir üst bilgisine eklenmelidir. Bunun nedeni, CSP meta etiketleri salt rapor modunu desteklememesidir.
Aşağıdaki Content-Security-Policy
HTTP yanıtını ayarlayın
başlık ekleyin:
Content-Security-Policy: script-src 'nonce-{RANDOM}' 'strict-dynamic'; object-src 'none'; base-uri 'none';
CSP için tek seferlik rastgele sayı oluşturma
Tek seferlik rastgele sayı, sayfa yükleme başına yalnızca bir kez kullanılan rastgele bir sayıdır. Tek seferlik rastgele olmayan CSP, yalnızca saldırganlar tek seferlik rastgele sayı değerini tahmin edemediğinde XSS'nin etkisini azaltabilir. CEVAP CSP tek seferlik rastgele sayısı:
- Kriptografik olarak güçlü bir rastgele değer (ideal olarak 128 bitten fazla uzunlukta)
- Her yanıt için yeni oluşturulur
- Base64 olarak kodlanmış
Sunucu tarafı çerçevelere CSP tek seferlik rastgele sayısının nasıl ekleneceğiyle ilgili bazı örnekleri burada bulabilirsiniz:
- Django (piton)
- Ekspres (JavaScript):
const app = express(); app.get('/', function(request, response) { // Generate a new random nonce value for every response. const nonce = crypto.randomBytes(16).toString("base64"); // Set the strict nonce-based CSP response header const csp = `script-src 'nonce-${nonce}' 'strict-dynamic'; object-src 'none'; base-uri 'none';`; response.set("Content-Security-Policy", csp); // Every <script> tag in your application should set the `nonce` attribute to this value. response.render(template, { nonce: nonce }); });
<script>
öğelerine nonce
özelliği ekleyin
Ortalama olmayan bir CSP ile her <script>
öğesi,
rastgele tek seferlik rastgele sayıyla eşleşen bir nonce
özelliğine sahip
CSP başlığında belirtilen değer. Tüm komut dosyaları aynı
tek seferlik rastgele sayı. İlk adım, bu özellikleri tüm komut dosyalarına eklemektir. Böylece
CSP bunlara izin verir.
Aşağıdaki Content-Security-Policy
HTTP yanıtını ayarlayın
başlık ekleyin:
Content-Security-Policy: script-src 'sha256-{HASHED_INLINE_SCRIPT}' 'strict-dynamic'; object-src 'none'; base-uri 'none';
Birden fazla satır içi komut dosyası için söz dizimi aşağıdaki gibidir:
'sha256-{HASHED_INLINE_SCRIPT_1}' 'sha256-{HASHED_INLINE_SCRIPT_2}'
Kaynaklı komut dosyalarını dinamik olarak yükleme
CSP karmaları tüm tarayıcılarda yalnızca satır içi komut dosyaları için desteklendiğinden, tüm üçüncü taraf komut dosyalarını satır içi bir komut dosyası kullanarak dinamik olarak yüklemeniz gerekir. Kaynaklı komut dosyalarına yönelik karmalar tarayıcılar arasında iyi bir şekilde desteklenmez.
![](https://web.dev/static/articles/strict-csp/image/B2YsfJDYw8PRI6kJI7Bs.jpg?authuser=2&hl=tr)
<script> var scripts = [ 'https://example.org/foo.js', 'https://example.org/bar.js']; scripts.forEach(function(scriptUrl) { var s = document.createElement('script'); s.src = scriptUrl; s.async = false; // to preserve execution order document.head.appendChild(s); }); </script>
{HASHED_INLINE_SCRIPT}
yer tutucusu içerir. Karma sayısını azaltmak için tüm satır içi öğeleri birleştirebilirsiniz
tek bir komut dosyasına dönüştürmenize olanak tanır. Bunun nasıl uygulandığını görmek için şuraya bakın:
örnek
ve kodunu içerir.
<script src="https://example.org/foo.js"></script> <script src="https://example.org/bar.js"></script>
Komut dosyası yüklemeyle ilgili dikkat edilmesi gereken noktalar
Satır içi komut dosyası örneği, s.async = false
foo
öğesinin bar
öncesinde yürütüldüğü,
bar
önce yüklenir. Bu snippet'te, s.async = false
, komut dosyaları yüklenirken ayrıştırıcıyı engellemez, çünkü
dinamik bir şekilde eklenir. Ayrıştırıcı, yalnızca komut dosyaları yürütülürken durur;
async
komut dosyası için de geçerlidir. Ancak bu snippet'le
unutmayın:
-
Komut dosyalarından biri veya her ikisi, doküman tamamlanmadan önce yürütülebilir
indiriliyor. Belli bir zaman dilimi içinde dokümanın
komut dosyaları yürütülür, önce
DOMContentLoaded
etkinliğini bekleyin bazı işaretler var. Bu durum, komut dosyaları yeterince erken indirilemiyorsa sayfada daha önceki önceden yükleme etiketlerini kullanın. -
defer = true
hiçbir şey yapmaz. İhtiyacınız varsa Gerektiğinde komut dosyasını manuel olarak çalıştırın.
3. Adım: HTML şablonlarını ve istemci tarafı kodunu yeniden düzenleyin
Satır içi etkinlik işleyiciler (ör. onclick="…"
, onerror="…"
) ve JavaScript URI'leri
(<a href="javascript:…">
), komut dosyalarını çalıştırmak için kullanılabilir. Bu,
XSS hatası bulan saldırganlar, bu tür HTML'leri yerleştirebilir ve kötü amaçlı yazılım
JavaScript'e dokunun. Tek seferlik veya karma tabanlı bir CSP, bu tür işaretlemelerin kullanımını yasaklar.
Siteniz bu kalıplardan herhangi birini kullanıyorsa bunları daha güvenli olacak şekilde yeniden düzenlemeniz gerekir.
sağlayabilir.
Önceki adımda CSP'yi etkinleştirdiyseniz İGP ihlallerini şurada görebilirsiniz: CSP uyumsuz bir kalıbı her engellediğinde konsola geri yüklenir.
![Chrome Developer Console'daki İGP ihlal raporları.](https://web.dev/static/articles/strict-csp/image/csp-violation-reports-th-ff599b24b17be.jpg?authuser=2&hl=tr)
Bu sorunu çoğu durumda kolayca çözebilirsiniz:
Satır içi etkinlik işleyicileri yeniden düzenleme
<span id="things">A thing.</span> <script nonce="${nonce}"> document.getElementById('things').addEventListener('click', doThings); </script>
<span onclick="doThings();">A thing.</span>
javascript:
URI'sını yeniden düzenle
<a id="foo">foo</a> <script nonce="${nonce}"> document.getElementById('foo').addEventListener('click', linkClicked); </script>
<a href="javascript:linkClicked()">foo</a>
eval()
JavaScript'inizden kaldırın
Uygulamanız JSON dizesi serileştirmelerini JS'ye dönüştürmek için eval()
kullanıyorsa
nesnelerinde bu tür örnekleri JSON.parse()
olarak yeniden düzenlemelisiniz. Bu da
daha hızlı şekilde ayarlayabilirsiniz.
Tüm eval()
kullanımlarını kaldıramıyorsanız yine de rastgele olmayan katı bir değer ayarlayabilirsiniz
CSP'dir, ancak 'unsafe-eval'
İGP anahtar kelimesini kullanmanız gerekir. Bu da
daha az güvenlidir.
Bu katı CSP'de bunları ve yeniden düzenlemeyle ilgili daha fazla örnek bulabilirsiniz. codelab:
4. Adım (İsteğe bağlı): Eski tarayıcı sürümlerini desteklemek için yedek ekleyin
Eski tarayıcı sürümlerini desteklemeniz gerekiyorsa:
strict-dynamic
kullanımı, daha önceki öğeler için yedek olarakhttps:
eklenmesini gerektirir sürümlerinde yer alır. Bunu yaptığınızda:strict-dynamic
özelliğini destekleyen tüm tarayıcılarhttps:
yedeğini yoksayar, bu nedenle politikanın gücünü azaltmaz.- Eski tarayıcılarda, harici olarak sağlanan komut dosyaları yalnızca
HTTPS kaynağı. Bu, katı bir CSP'den daha az güvenli olsa da
javascript:
URI'larının yerleştirilmesi gibi bazı yaygın XSS nedenlerini önler.
- Çok eski (4+ yıl) tarayıcı sürümleriyle uyumluluğu sağlamak için
unsafe-inline
yedek olarak kullanılabilir. Son tarayıcıların tümüunsafe-inline
talimatını yoksayar CSP tek seferlik rastgele sayı veya karma varsa.
Content-Security-Policy:
script-src 'nonce-{random}' 'strict-dynamic' https: 'unsafe-inline';
object-src 'none';
base-uri 'none';
5. Adım: İGP'nizi dağıtın
CSP'nizin yerel geliştirme ortamınızdan yararlanmak istiyorsanız CSP'nizi hazırlık aşamasına, ardından kendi üretim ortamı:
- (İsteğe bağlı) CSP'nizi
Content-Security-Policy-Report-Only
üstbilgisi. Salt rapor modu, önce üretimde yeni bir İGP gibi zarar verebilecek bir değişikliği test etmeden önce CSP kısıtlamalarını uygulamaya başlayabilirsiniz. Yalnızca rapor modunda İGP'niz uygulamanızın davranışını etkilemesine rağmen tarayıcı yine de konsol hataları oluşturacaktır ve ihlal raporları, İGP'nizle uyumlu olmayan kalıplarla karşılaştığında Böylece son kullanıcılarınız açısından neyin sorun olabileceğini görebilirsiniz. Daha fazla Reporting API'ye göz atın. - İGP'nizin son kullanıcılarınız için sitenizi bozmayacağından emin olduğunuzda
Content-Security-Policy
yanıt başlığını kullanarak CSP'nizi dağıtın. Biz CSP'nizi sunucu tarafında bir HTTP başlığı kullanarak ayarlamanızı öneririz.<meta>
etiketinden daha güvenlidir. Bu adımı tamamladıktan sonra İGP'niz nasıl koruyacağını daha iyi anlayacaksınız.
Sınırlamalar
Katı bir CSP genellikle
yardımcı olabilir. Çoğu durumda CSP saldırı yüzeyini önemli ölçüde küçülterek
javascript:
URI'leri gibi tehlikeli kalıpları reddetmektedir. Ancak, reklamın türüne göre
içeren ('strict-dynamic'
içeren veya içermeyen) CSP'ler,
CSP'nin uygulamanızı korumadığı durumlar şunlardır:
- Bir komut dosyasını tek seferlik rastgele eklerseniz, ancak doğrudan gövdeye veya
Bu
<script>
öğesininsrc
parametresi. - Dinamik olarak oluşturulan komut dosyalarının konumlarına yerleştirme varsa
(
document.createElement('script')
) (tüm kitaplık işlevleri dahil) , bağımsız değişkenlerinin değerlerine görescript
DOM düğümü oluşturan Bu jQuery'nin.html()
yanı sıra.get()
ve jQuery'de.post()
< 3.0. - Eski AngularJS uygulamalarında şablon yerleştirme işlemi varsa. Bir saldırgan bir AngularJS şablonuna eklenebilen isteğe bağlı JavaScript yürütün.
- Politika
'unsafe-eval'
,eval()
konumuna eklemeler içeriyorsasetTimeout()
ve nadiren kullanılan diğer birkaç API.
Geliştiriciler ve güvenlik mühendisleri bu tür durumlara özellikle dikkat etmelidir: emin olun. Ayrıntılı bilgiyi Bu durumlara İçerik Güvenliği Politikası: Sağlamlaştırma ve Azaltma Arasındaki Başarılı Kargaşa bölümünden ulaşabilirsiniz.
Daha fazla bilgi
- CSP Sona Erdi, Çok Yaşayın CSP Beyaz Listelerin Güvenliği Konusunda ve İçerik Güvenliği Politikasının Geleceği Hakkında
- CSP Değerlendirici
- LocoMoco Konferansı: İçerik Güvenliği Politikası: Sağlamlaştırma ve azaltma arasındaki başarılı bir karmaşa
- Google I/O konuşması: Modern Platform Özellikleriyle Web Uygulamalarının Güvenliğini Sağlama