Emre Kızıldaş
Published in

Emre Kızıldaş

.Net Core MVC Projelerine Content Security Policy Nasıl Uygulanır?

Herkese yeniden merhaba! 👋🏼 Bu makalemizde sizlere güvenlik başlıklarından (headers) en önemlilerinden olan Content-Security-Policy başlığını .Net Core tabanlı internet projelerinizde nasıl uygulayacağınızdan bahsedeceğim.

Headers (Başlıklar) nedir? Ne işe yararlar?

Yazımıza öncelikle http başlıklarının ne olduklarından ve nasıl sınıflandırıldıklarından MDN kaynaklı bir açıklama ile başlayalım.

HTTP başlıkları, istemci ve sunucunun istek veya yanıtla birlikte ek bilgiler iletebilmesini sağlar.Başlık bilgileri bağlamlarına (context) göre grouplanabilir:

  • General header: Başlık bilgileri hem isteklerde hem de yanıtlarda görülülür. Başlık bilgileri gövde hakkında direktifler içerir.
  • Request header: Çekilen kaynak veya istemci hakkında daha fazla bilgi içeren başlık bilgileridir. Sunucuya gönderilir.
  • Response header: Sunucudan alınan yanıt hakkında ek bilgi içeren başlık bilgileridir. Örneğin sunucuya yapılan istek sonucu veya sunucu hakkında bilgi içerir. Tarayıcıya gelir.
  • Entity header: Entity gövdesi hakkında daha fazla bilgi içeren başlık bilgileridir. Örneğin MIME-tipi veya içerik uzunluğu.

Content-Security-Policy nedir?

Bu response header çeşidi ile sitenizde yer alan kaynaklara erişimi kısıtlayabilirsiniz. Örneğin sadece kendi sitenizde barındırılan style dosyalarını okuyabilir, veya kendi sitenizde yer alan, cloudflare’den ve google’dan gelecek Javascript dosyalarının çalışabilmesini diğer tüm kaynaklardan gelecek script dosyalarını engellemesini sağlayabilirsiniz.

Özellikle Javascript dosyalarının kısıtlanması özelliği ile sitemizde var olabilecek script zaafiyetlerinin önüne geçmiş oluruz. Sitemize dışarıdan bir kaynaktan veya site üzerinden herhangi bir şekilde script enjekte edilebilmesinin imkanı kalmayacaktır.

Bu yazımızda özellikle script-src ayarı üzerinde duracağız. Sitemizdeki viewlara gömülü scriptlerden yalnızca nonce değeri olan scriptleri çalışmasına olanak sağlayacağız.

Nonce değeri nedir?

CSP Kapsamında sitemizde önyüze gömülü (inline) olarak yazdığımız javascript kodlarının çalışabilmesi için headerlarda yer alan nonce adını verdiğimiz sha512 ile şifrelenmiş 128 bitlik bir anahtar ile tanımlamasını yapmamız gerekir.

Her request başına bu nonce değeri yeniden oluşturulmaktadır. Bu sayede sitemize inject edilebilecek bir script olsa dahi request olduğunda nonce değeri değişeceğinden dolayı saldırgan bu scripti sitemizde çalıştıramayacaktır.

Nonce nasıl kullanılır?

Aşağıda ki örnek kodda nonce değerinin javascript kodlarımızda nasıl kullanıldığını görebilirsiniz:

<script type="text/javascript" nonce="BurayaNonceDegeri">
$(function(){
alert('Hello!');
});
</script>

Buraya yazdığımız nonce attribute’ı kesinlikle sabit bir değer olarak header ‘da ayarlanmamalıdır. Her yapılan istekte bu nonce değeri değiştirilmeli ve view üzerinde ilgili yerlerde kullanılmalıdır.

.Net Core Projemizde nasıl kullanabiliriz?

Middleware benzeri bir yapı kullanarak yapılan her istekte nonce değerini yeniden oluşturan bir kod bloğunu startup.cs dosyamızda yazabiliriz.

Nonce değerlerini oluştururken kripto kütüphanelerinden RNGCryptoServiceProvider kullanarak şifrelenmiş metnimizi oluşturacağız.

Startup sınıfımız içerisinde yer alan Configure metodunda aşağıdaki kod bloğunu ekleyelim:

Kodu açıklamak gerekirse:

  • Yeni bir RNGCryptoServiceProvider nesnesi oluştur
  • 32 bitlik bir dizi oluştur.
  • rng nesnesine bu baytları işle
  • İşlenen baytlar rng algoritmasıyla size yeni bir string değer üretsin
  • Bu nonce değerini HttpContext nesnemize ekle
  • Aynı değeri bir de HttpContext içerisinde yer alan Response headerlarına Content-Security-Policy adıyla ekleyelim

Bu kod parçacığında kullanılan CSP başlığına göre sitemizde yalnızca sunucumuzda yer alan .js dosyaları (‘self’) ile nonce değeri bizim oluşturduğumuz değere eşit olan inline javascript kodları çalışabilecektir. Aksi durumdaki tüm javascript kodları veya dosyaları çalışmayacaktır.

Bu durumda dikkat edilmesi gereken bir nokta da şudur: Örneğin sitenizde Cloudflare yapısı ve Google Analytics kullanıyorsanız yukarıdaki kod parçacığını aşağıdaki şekilde güncellemeniz gerekecektir:

context.Response.Headers.Add("Content-Security-Policy",
new[] { string.Format("script-src 'self' https://ajax.cloudflare.com https://gstatic.com 'nonce-{0}'", nonce) });

Bu sayede Cloudflare ve gstatic sitelerinden gelecek olan script dosyalarına da güvendiğimizi belirtmiş oluruz.

Nonce değerini viewlara nasıl taşırız?

Startup sınıfında oluşturduğumuz nonce değerlerini javascript kodlarımızda kullanabilmemiz için bir HtmlHelper oluşturmamız gerekmektedir. Nonce adınını verdiğimiz bu HtmlHelper sınıfını aşağıdaki kod yardımıyla oluşturabiliriz:

Yukarıdaki kodu biraz açıklamak gerekirse;

  • Nonce değerimizi HttpContext içerisine yerleştirdiğimiz ScriptNonce değeri ile alıyoruz.
  • Bu string değeri HtmlString ile yazdırıyoruz.

Bu html helper sınıfını view dosyamızda aşağıdaki örnekte olduğu gibi kullanabiliriz:

Sayfanın kaynağını görüntülediğimizde şu şekilde gözükmektedir:

Content Security Policy’nin engellediği bir örneği ise aşağıdaki şekilde verebiliriz:

Sitemize nonce değeri olan ve olmayan iki script eklediğimizde CSP sayesinde nonce değeri olmayan script kodunun çalışmadığını göreceksiniz. Konsolunuzu açtığınızda ise aşağıdaki gibi bir hata ile karşılaşacaksınız:

Hatada da bahsedildiği gibi CSP direktifleri gereği sayfada yalnızca nonce değeri belirtilen şekilde olan inline scriptler çalışmaktadır. Nonce değeri olmayan inline script dosyalarını çalıştıramayız.

Yazımın burada sonuna gelmiş bulunmaktayım. Projenizde bu header kullanıldığında sitenize yapılacak pentestlerde güvenlik seviyesinin oldukça yüksek çıkacağından emin olabilirsiniz. CSP hakkında takıldığınız tüm noktaları aşağıdaki yorumlarda bana sorabilirsiniz. Ayrıca bu örnek projemin kodlarına github hesabımdan ulaşabilirsiniz.

--

--

Çeşitli yazılım dillerinde ve platformlarında projeler oluşturmak üzere paylaşımlarda bulunduğum kişisel blog.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store