HTTP Güvenlik Headerları

Ziyahan Albeniz - 05 Ocak 2018 -

Header’lar güvenlik dünyasında çok önem görmezler ancak bir çok zafiyetin ve güvenli iletişimin gizli bahçesini barındırırlar.

HTTP Güvenlik Headerları

Headerlar, HTTP'nin hem istek hem de yanıt mesajlarında yer alan ve mesajın meta bilgilerini taşıyan bölümlerdir. Meta, bilgiyi tanımlayan bilgi anlamına gelmektedir. HTTP 1.0 ve 1.1 versiyonları ile protokole eklenmiştir.

Bu meta bilgileri, istekler için, talep edilen mesajın dili, tipi, browserın sakladığı yetki bilgileri, önbellekte tutulan içeriğe ait bilgiler olabileceği gibi; yanıt yani response mesajlarında ise, içeriğin boyutu ve tipi, bellekte saklanma tercihleri, sunucu bilgileri, tarih ve saati, istemci tarafında set edilecek credentiallar gibi bir takım bilgileri içerebilir. Güvenlik headerları ise istemci tarafında bir dizi güvenlik önlemini devreye alan, bir dizi davranışı etkinleştiren ya da deaktif eden HTTP yanıt headerlarıdır.

X-Frame-Options

x-frame-options

2009 yılında Clickjacking başta olmak üzere UI Redressing saldırılarına karşı önerilen ve bugün tüm major browserlar tarafından desteklenen bir güvenlik headerıdır.

UI Redressing saldırıları basit olarak, hedef sitenin bir iframe içerisinde yüklenmesi esasına dayanıyor. Saldırıda amaçlanan, hedef sitedeki bilgilerin, kullanıcı kandırılarak, saldırgan sitesindeki arayüzlere girilmesini sağlamak ya da kullanıcının, MASUM görünümlü saldırgan site üzerinde gerçekleştirdiğine inandığı/düşündüğü hareketleri, hedef siteye yönlendirmek ve kullanıcı yetkileriyle işlem gerçekleştirmektir.

Clickjacking saldırı yönteminde saldırgan hedef siteyi opacity değeri düşük bir iframe içerisinde yükleyerek, ziyaretçinin transparan hale gelen hedef sitenin altında gördüğü masum sitede işlem yapıyormuş hissine kapılmasını sağlar. Böylece saldırgan, kurbanı zararsız görünen bağlantılara tıklamaya ikna ederken, hedef sitedeki bir dizi aksiyonun tetiklenmesine yol açar.

x-frame-options-2

Resim: https://www.tinfoilsecurity.com/blog/what-is-clickjacking

Resimde görülen örnekte eBay sitesi opacity değeri düşük bir iframede yükleniyor. Bu sebeple kullanıcı tarafından görülemiyor. eBay'in yüklendiği iframe'in opacity değeri düşük olduğu için Buy butonunu değil de Free butonunu görüyor. Kullanıcı Free butonuna bastığında, aslında bu butonun üzerine binen eBay'deki Buy butonuna tıklamış oluyor. Buy butonuna tıklandığında da eBay sitesi, bu buton için kurgulanan gerekli işlemleri yapıyor.

Bu işlemlerin tamamı kullanıcının (ya da kurbanın) kendi browserı üzerinden gerçekleştiği için eBay için tetiklenen bu isteğe, browser kendisinde tuttuğu credentials (örneğin Cookie) bilgilerini de ekleyecek. (Not: Bu anlatılan tamamen hayali, anti-CSRF token gibi güvenlik mekanizmalarının söz konusu olmadığı ve X-Frame-Options güvenlik headerının olmadığı bir örnek vakadır.)

Clickjacking, kullanıcılarımızı, yani zincirin zayıf halkasını hedef alan bir saldırıdır. Bu saldırıdan korunmak için Frame Busting başta olmak üzere, pek çok yöntem denenmiştir. Bunlardan en geçerli olan X-Frame-Options yöntemi ise 2009 yılında Microsoft tarafından IE browserlarına eklenmiştir.

Ziyaretçilerimizi Clickjacking vb. saldırılardan korunmanın en temel yolu, sayfalarımızın iframe, frame gibi yollarla embed edilmesini engellemek ya da buna bir kısıtlama getirmektir. Bunu yapmak için güvenlik headerlarından biri olan X-Frame-Options'ı kullanabiliriz.

X-Frame-Options değerinin, alabileceği üç farklı değer vardır.

X-Frame-Options: DENY | SAMEORIGIN | ALLOW-FROM URL

DENY: Sitenin hiçbir şekilde iframe ya da benzeri bir yol ile embed edilmesine izin vermez.

SAMEORIGIN: Sitenin yalnızca şema + hostname + port olarak eşleştiği bir site tarafından embed edilmesine izin verir. Örneğin, https://www.example.com yalnızca https://www.example.com üzerinden yüklenebilir.

ALLOW-FROM URL: Yalnızca belirtilen URL tarafından sitenin embed edilmesine izin verir.

X-Frame-Options'da iki önemli noktayı hatırlatmakta fayda var. Chromium tabanlı browserlarda X-Frame-Options kısmi olarak desteklenmektedir. Örneğin ALLOW-FROM özelliği kullanılamamaktadır.

ALLOW-FROM URL Parametresi ile yalnızca 1 adet domain'i whitelist edip, sitemizi iframe içerisinde yüklemesine izin verebiliriz.

Önemi noktalar

  • X-Frame-Options headerı bütün sayfaların HTTP yanıtlarında yer almalıdır.
  • X-Frame-Options yerine, Content-Security-Policy frame-ancestors direktifi kullanılabilir.
Content-Security-Policy: frame-ancestors 'none'; // Hiçbir URL sayfayı iframe içerisinde yükleyemez.
Content-Security-Policy: frame-ancestors 'self'; // SAMEORIGIN parametresindeki işlevin aynısı.

X-Frame-Options ile birlikte yalnızca bir URL'i whitelist'e alırken, CSP frame-ancestors ile birden fazla domain'i, güvenilir URL'ler listesinde belirtip, sayfalarımızı iframe olarak yüklemelerine izin verebiliriz.

X-Frame-Options 'ı Hangi Browserlarda Kullanabilirim?

x-frame-options-3

Kaynak: https://caniuse.com/#search=x-frame-options

X-XSS-PROTECTION

x-xss-protection

Tarayıcıda Reflected XSS güvenlik filtresini etkinleştirir. Reflected XSS, kullanıcıdan alınan girdinin sayfa context'inde bir script kodu olarak yorumlanması ile ortaya çıkan zafiyet türüdür.

Bir script kodu gibi yorumlanan bu zararlı girdi vasıtası ile, kullanıcının oturumunun ele geçirilmesinden, klavye ve fare hareketlerinin izlenmesi başta olmak üzere, bir dizi zararlı işlem yapılabilir.

Örneğin;

<p>Hosgeldin <?php echo $_GET["isim"];?></p>

http://www.example.com?isim=<script>alert(1);</script>

X-XSS-Protection Çeşitli parametre varyasyonları ile davranış değiştirebilmek mümkündür.

x-xss-protection-2

X-XSS-Protection: 1;

Tarayıcıda XSS güvenlik filtresini devreye alarak, olası bir XSS payloadunun sayfada çalışmasını engeller.

X-XSS-Protection: 1; mode=block

Tarayıcıda XSS güvenlik filtresini devreye alır. Olası bir XSS payloadunun sayfada çalışmasını tüm sayfanın gösterilmesini engelleyerek bloke eder. XSS payloadu gönderildiğinde, ziyaretçi browserda beyaz bir ekran ile karşılaşır.

X-XSS-Protection: 1; mode=block; report=https://domain.tld/folder/file.ext

Chromium tabanlı browserlarda, CSP violation report özelliğinin implementasyonu kullanılarak, report parametresi ile belirtilen URL'e XSS enjeksiyon girişimi raporlanır.

X-Content-Type-Options

Mime Type Sniffing, sunulan içeriğin tipi belirtilmediği durumlarda, browserların sayfa görüntülenmesinde en doğru yolu bulabilmek için, içeriği değerlendirmesi işlemidir.

Kısaca sunulan belgede Content-Type headerı ile içeriğin tipi belirtilmediği takdirde, browser içeriği "koklayarak", kaynağı en doğru biçimde görüntülemeye çalışır.

Özellikle de upload fonksiyonlarıyla beraber, sniffing işlemi bir takım tehlikeler arz edebilir.

Örneğin, kullanıcının zararsız addedilen bir text dosyası upload ettiğini varsayalım. Eğer bu text dosyası HTML ve script tagları, Javascript kodları içeriyorsa ve biz bu yüklenen dosyayı tekrar kullanıcıya sunarken bir Content-Type belirtmiyorsak, browser bu sayfanın içeriğini koklayarak bunun pek tabii bir text/html tipinde bir dosya olduğuna karar verecektir ve bu sayfadaki kodlar da çalışacaktır.

Yine sitemize upload edilen resim dosyaları dahi, kullanıcıya geri sunulurken, Content-Type headerı içermelidir. Yoksa EXIF data olarak tabir edilen, imajın meta datalarını içeren kısma script kodları enjekte edilerek, zararlı kodlar çalıştırılabilir.

İşte bu gibi durumlarda, browserın sayfa içeriğini koklayarak, inceleyerek servis edeceği tipe karar vermesinin önüne geçmek için X-Content-Type-Options headerı kullanılmaktadır.

X-Content-Type-Options: nosniff

X-Download-Options

Internet Explorer 8 ve üzeri sürümlerde geçerli olan bu özellik sayesinde, talep edilen içeriğin browserda görüntülenmek yerine download edilmesi sağlanabilir.

Özellikle de kullanıcıların içerik yüklediği sistemler için bir ekstra güvenlik (defence-in-depth) mekanizması olarak düşünülebilir.

Örnek bir senaryo olarak, sayfamızda stealcookie.php adında kullanıcı tarafından yüklenmiş bir dosya bulunduğunu varsayalım. Bu dosyanın download edilmesini zorlamak için, aşağıdaki headerı da kullandık:

Content-Disposition: attachment; filename=stealcookie.php

Güvenilir olmayan içerikler için bir parça çözüm olduğu düşünebilir. Ama download'ı zorlasak dahi, kullanıcı karşısına Open ve Save, Aç / Çalıştır ve Kaydet gibi seçenekler gelecektir.

Kullanıcı direkt Open 'ı tıkladığında ise bu dosya sitemizin contextinde çalışacak ve bu dosyanın içerisindeki zararlı kod DOM'a ve sayfamıza ait kaynaklara erişebilecektir.

x-download-options

Bunu engellemenin yolu, Open seçeneğinin, seçenekler arasından kaldırılması ile mümkündür.

X-Download-Options: noopen

Aklınıza şöyle bir soru gelebilir: Kaydedip, dosyayı tekrar açabilir mi? Evet açabilir, fakat bu takdirde zararlı kod bizim sitemizin kontekstinde değil, kullanıcının dosya sistemi üzerinden çalışacaktır:

x-download-options-2

Content-Security-Policy (CSP)

2012 Kasım ayında ilk versiyonu hayatımıza giren CSP, başta XSS olmak üzere, Clickjacking, Protocol Downgrading, Frame Injection vb bir dizi zafiyete karşı istemci tarafında ekstra güvenlik katmanı sunmaktadır.

X-Frame-Options, X-XSS-Protection, gibi standartta olmayan pek çok güvenlik headerının muadilini bünyesinde barındıran CSP, yakın gelecekte, istemci taraflı güvenliğin en önemli araçlarından biri olacağa benziyor.

Örnek bir CSP headerı aşağıdaki gibidir:

Content-Security-Policy: KONTROL_ALANI degerler

CSP headerı ile birlikte, aşağıda sıralayacağımız kontrol alanlarındaki kaynak kullanımlarını sınırlandırabilir, tanımlayabiliriz.

CSP'de kurallar tanımlarken whitelist (beyaz liste) olarak bilinen bir yaklaşım kullanılmaktadır. Whitelist yaklaşımı sayesinde, yalnızca kabul ettiğimiz kaynakları belirtip, bu kural ile eşleşmeyen tüm kaynakların kullanımını engelleyebiliriz. Bu kaynakların hangileri olacağını HTTP response'ları ile beraber döndürdüğümüz CSP talimatlarında belirtmemiz yeterli.

Content-Security-Policy: script-src 'self' https://apis.google.com

Yukarıdaki CSP talimatı ile sadece kendi domainimiz ve https://apis.google.com üzerinden script yüklemelerine izin verdik. Yanı sıra inline scriptler de çalıştırılmayacaktır.

CSP headerı ile birlikte, aşağıda sıralayacağımız kontrol alanlarındaki kaynak kullanımlarını sınırlandırabilir, tanımlayabiliriz.

base-uri: Base elementi, sayfadaki tüm relative URL'lerin kendisine çözümleneceği absolute URL'i belirten bir değerdir. <base> element'inde kullanılacak değer ile ilgili kısıt tanımlamamıza yardımcı olur. Böylece Base Tag Hijacking saldırıları engellenebilir.

child-src: Sayfaya embed edilecek olan framelerin alabileceği kaynak değerleri tanımlar. Sayfamızı Frame Injection saldırılarına karşı koruyabilmek için, ek bir tedbir olarak kullanabiliriz.

connect-src: XHR, WebSockets, EventSource ile bağlanılabilecek kaynakları kısıtlar.

font-src: Fontların yüklenebileceği kaynakları belirtir.

form-action: Form tagları için geçerli action'ları belirtir.

frame-ancestors: Mevcut sayfayı frame, iframe, embed ve applet olarak yüklemeye yetkili kaynakları belirtir. X-Frame-Options'ın muadilidir. Clickjacking vb UI Redressing saldırılarını engellememize yardımcı olur.

img-src: Resimlerin yüklenebileceği kaynakları tanımlar.

media-src: Video ve ses yüklenebilecek kaynakları tanımlar/kısıtlar.

object-src: Flash ve diğer plugin'lerin yükleneceği kaynakları tanımlar/kısıtlar.

plugin-types: Yüklenebilecek plugin tiplerinini belirler/limitler.

report-uri: CSP'nin ihlal edildiği durumda, raporun gönderileceği adresi belirtir.

style-src: Stil dosyaları için kaynak tanımlaması/kısıtlaması yapar.

upgrade-insecure-requests: HTTP isteklerini HTTPs olarak değiştirir.

Bu değerlerde varsayılan olarak benimsenen yaklaşım "Wide Open" olarak bilinen yaklaşımdır. Yani CSP headerlarında, yukarıdaki alanlar için bir değer belirtilmez ise, bu alanlar için herhangi bir kaynaktan yapılan yüklemelere izin verilecektir. Örneğin style-src için bir değer belirtilmezse, bu style-src: * olarak kabul edilecek ve tüm kaynaklardan stil yüklemeye izin verilecektir.

Bu davranışı değiştirmek için default-src direktifini kullanabiliriz. Burada tanımlanan değer, -src ile biten pek çok direktifi override ederek, bu direktifler için default bir değer tanımlar. Eğer default-src'i http://www.example.com olarak tanımladı isek ve font-src'ye bir değer vermediysek bu durumda fontlar da yalnızca https://www.example.com adresinden yüklenebilir.

Aşağıdakiler, default-src tanımınının override edemeyeceği direktiflerdir:

base-uri
form-action
frame-ancestors
plugin-types
report-uri
sandbox

Bir veya birden çok direktifi bir HTTP header'ı içerisinde, her talimatı birbirinden noktalı virgül (;) ile ayırarak kullanılabiliriz.

script-src https://host1.com https://host2.com; style-src https://www.example.com

Bir direktifin alacağı muhtelif değerler, boşluk ile birbirinden ayrılmalıdır:

script-src https://host1.com https://host2.com;

Önemli birkaç nokta:

CSP her sayfa için özel tanımlanmalı ve bu sayfanın HTTP yanıtında gönderilmelidir.

Bu, her sayfaya yönelik, onun spesifik ihtiyaçları için en optimum policy'yi tanımlamamıza yardımcı olacaktır.

Burada özet haliyle anlatmaya çalıştığımız Content-Security-Policy (CSP) konusunda ayrıntılı bilgiye Netsparker Türkiye Blogu'nda yayınlanan Content-Security-Policy (CSP) başlıklı makalemiz üzerinden ulaşabilirsiniz.

HSTS (HTTP Strict Transport Security)

HSTS yani HTTP Strict Transport Security, adından da anlaşılacağı üzere, güvenli web iletişimini zorlayan bir mekanizmadır. Hatta HSTS için, güvenli web iletişim zincirinin eksik halkası da diyebiliriz.

Peki neden?

SSL, uçtan uca bir şifreleme sunarak, bütünlük, gizlilik ve yetkilendirme için elverişli bir yol sunar. İdeal bir SSL implementasyonunda, trafik boyunca transfer edilen verilerin, aktarım esnasında değişmediğinden, bir üçüncü kişi tarafından izlenemediğinden ve gerçekten de iletişim kurduğumuz kişinin bizim arzu ettiğimiz kişi olup olmadığından emin olabiliriz.

İdeal bir SSL implementasyonu tabirini bilerek kullandık. Çünkü web uygulamalarındaki kısmi implementasyonlar örneğin sadece ödeme ve login sayfalarının güvenli bağlantılar üzerinden çağrılmasını zorlamak, eksik bir implementasyon olarak hala pek çok saldırıya kapı aralamaktadır.

Bunun yol açabileceği riskler Defcon 24 konsefransındaki HTTP Cookie Hijacking'in Güvenlik ve Gizliliğe Etkileri sunumu ile açıkça ortaya konulmuştur. Bu sunum ile ilgili bir değerlendirme yazısına Netsparker Türkiye Blogu'ndan ulaşabilirisiniz.

Sayfalarımızın tamamını güvenli bağlantıya zorlamadığımız takdirde, saldırganlar kolaylıkla hedeflerindeki kişilerin güvensiz bağlantı üzerinden web gezinimi yapmasını sağlayabilir ya da MITM saldırıları ile HTTPS üzerinden akan bir trafiğin HTTP olarak devam ettirilmesini (sslstrip) sağlayabilirler.

Yalnız bu kadar değil, süresi dolmuş sertifikalar ve geçersiz sertifikalar da güvenlik vadettiğiniz bağlantılarınız için bir risk arz etmektedir. Kullanıcıların kolayca, bir tıkla aştıkları bu tarz browser engelleri, sizin uygulamalarınız açısından büyük bir itibar kaybına yol açabilir.

Tüm bunları engellemenin bir yolu yok mu?

Web uygulamalarınız için SSL'i layığıyla implemente etmek istediğinizde, siteye yönelen tüm HTTP isteklerini HTTPS olarak değiştirmeniz, bunun dışında web sayfalarınız içerisine yüklenen, imaj, script, stil dosyaları gibi pek çok dosyaların da yine güvenli bir protokol üzerinden yüklenmesini sağlamanız gerekiyor. Ayrıca, sertifika hatalarında da, güvenlik daha önemlidir diyerek, bu tarz durumlarda gerekirse kullanıcının site gezinimini dahi engellemeniz gerekmektedir.

Bütün bunları manual olarak yapabilmek çok zor. Özellikle de olası bir sertifika hatası durumunda kullanıcının sitenizdeki gezinimini engellemek.

Bu noktada imdadımıza HSTS yetişiyor. Kasım 2012 yılında geliştirilen HSTS özelliği sayesinde, web sayfamızın yanıtında bir güvenlik headerı (Strict-Transport-Security) set etmemiz yeterli.

Bu yanıtla birlikte browserımıza şu talimatı vermiş oluyoruz: Sayfalarımıza yönelen tüm isteklerin HTTPS bağlantıya çevir. Ayrıca, olası bir sertifika hatalarında (güvensiz sertifika, süresi dolmuş sertifika vb..) kullanıcının web gezinimine devam etmesine izin verme.

Örnek kullanım:

Strict-Transport-Security: max-age=31536000; 

max -age değeri ile birlikte, bu direktifin browser hafızasında tutulacağı süreyi saniye cinsinden belirtiyoruz.

HSTS implementasyonunda dikkat çeken iki özellik daha var. Bunlardan biri includeSubdomains parametresi, diğeri ise preload parametreleri.

includeSubdomains parametresi ile HSTS'in yani katı aktarım güvenliği talimatının sitenin bütün subdomainleri için uygulanmasını belirtiyoruz.

İlk İstek Sorunu ve preload özelliği

HSTS headerını ancak güvenli bir bağlantı üzerinden set edebiliyoruz. Güvenli iletişim ile ilgili diğer bir header olan Public Key Pinning gibi HSTS de Trust On First Use (TOFU) yöntemine dayanıyor. Yani ilk HTTP isteği web stemize yapıldığında, biz bunu hardcoded olarak güvenli bağlantıya yönlendireceğiz. Bu güvenli bağlantının yanıtında da HSTS headerı olacak ve browserlar artık bu talimatı belleklerinde saklayıp, bir dahaki güvensiz (HTTP) isteği doğrudan kendileri güvenli bağlantıya yönlendirecekler.

Peki bu ilk yapılan HTTP isteğinin MITM saldırıları ile engellenmesi söz konusu değil mi? Maalesef evet.

İşte bununla ilgili olarak da karşımıza preload özelliği çıkıyor.

preload özelliği sayesinde browserlarla birlikte deploy edilen HSTS listesine sitemizin de dahil edilip, bu ilk HTTP isteğine gerek kalmadan HSTS'in uygulanmasını sağlayabiliriz.

Bunun belirli şartları var:

  • Öncelikle geçerli bir SSL sertifikasına sahip olmalıyız.
  • HTTP'den HTTPS'e redirect ederken aynı host'u kullanmalıyız. (Yani HTTPS trafiği example.com için secure.example.com üzerinden değil, yine example.com üzerinden devam etmeli.).
  • www subdomain'i başta olmak üzere, tüm altdomainlerin güvenli bağlantı üzerinden sunuluyor olması,
  • Base domain (ana) domainden güvenli bağlantı üzerinden sağlanan HSTS headerımızdaki max-age değerinin en az 18 hafta yani 10886400 saniye olarak set edilmesi, includeSubdomains ve preload seçeneklerinin HSTS headerında bulunması gerekmektedir:

    Strict-Transport-Security: max-age=10886400; includeSubDomains; preload

PKP - Public Key Pinning

Public Key Pinning 'i anlamak için aslında güvenli bağlantı ne vaad ediyor ve bu nasıl gerçekleşiyor tekrar gözden geçirelim.

Kullanıcılarımız bizim sitemize güvenle erişmek istediklerinde, biz kendimizi tanıtan ve şifrelemede kullanılacak ortak anahtarın kendisi ile şifreleneceği public anahtarımızı gönderiyoruz. Buna sertifika diyoruz. Bu sertifikada, sitemizin adı, sertifikanın ne zamana kadar geçerli olacağı, kaç bitlik bir kriptografik anahtar kullanıldığı gibi bilgiler var.

Bu sertifikada bir bilgi daha var. Onu da şöyle izah edelim. Biz istemciye, browser'a, bu benim sertifikam, diye açık anahtar bilgilerimizi gönderdiğimizde, istemci haliyle "Nereden bileceğim, gerçekten senin example.com olduğunu?" diye soruyor. Biz de inanmazsan, büyüklerine sor, diyerek browserların güvenilir sertifikalar listesinde yer alan ve sertifika otoriteleri (CA) denen zincire müracaat etmesini sağlıyoruz. İşte bizim sertifikamızda bulunan bilgilerden biri de browserın ispat kabilinden sertifikamızın doğruluğunu danışacağı issuer'ın yani sertifikayı imzalayan firmanın adı. Browser buradan hareketle sertifikanın geçerli bir sertifika olup olmadığını kontrol ediyor ve şayet bir problem yoksa güvenli iletişime devam ediyor.

Dünya maalesef bu kadar masum bir yer değil. Aralıklarla yaşanan (en son 2013'de, hem de Türkiye'de) gördük ki, herhangi bir saikle, bu sertifika otoritelerinden biri bir başka web sitesi adına sertifika imzalayabiliyor.

İlk örneğimiz 2011 yılından. Hollandalı yetkili sertifika dağıtıcısı DigiNotar hack ediliyor. Ve bu hack eylemi sonrasında, 500 'e yakın sertifika imzalanıyor. Bu sertifikalarla 300 bin İran'lının Gmail de dahil olmak üzere pek çok Google servisi kullanımları izleniyor.

Yine benzer bir olay 2008 ve 2011 yıllarında yine bir sertifika otoritesi olan StartCom'un da başına geliyor. Bu saldırılarla birlikte, paypal.com ve verisign.com domainleri için sertifikalar üretiliyor. 2011'deki saldırıda StartCom'un rootkey'ine ulaşılıyor. Böylece sadece istedikleri site için sertifika üretebilmek değil, aynı zamanda üretilen sertifikaları geçersiz kılabilmek ya da tekrar imzalayabilmek şansına sahip oluyorlar.

Bu sertifika otoriteleri, sertifika geçerliliğini teyit etmelerinin yanında bir de kendi yetkilerini devretmek kabilinden ara yetki sertifikaları imzalayabiliyor ve bu sertifika imzalama hakkını paylaşmış oluyor.

Son örneğimiz maalesef Türkiye'den ve yukarıda bahsettiğimiz ara sertifika sağlayıcılığı türünden bir sorun. Özetle Ağustos 2011'de Türk Trust şirketi, biri e-islem.kktcmerkezbankasi.org diğeri ise ego.gov.tr olmak üzere iki adet SSL sertifikası oluşturuyor. Fakat sistemde oluşan bir hatadan ötürü bunlar SSL sertifikaları olarak değil, ara sağlayıcı sertifikaları olarak üretiliyor.

Kktcmerkezbankasi.org için üretilen sertifikanın kullanılamadığı ama ego.gov.tr için üretilen sertifikanın aynı tarihlerde kullanımının devam ettiği belirtiliyor.

Checkpoint cihazı kendisine yüklenen sertifikalar sayesinde, şifreli trafiği izlemek için sertifikalar üretmeye başlıyor. Ürettiği sertifikalardan biri de Google'a ait.[1], [2]

Google için üretilen sertifikalardan biri, 26 Aralık 2012 tarihinde, Chrome tarayıcı üzerinden Google’a bildiriliyor.

Peki ama nasıl? Public Key Pinning yani PKP ile.

Chrome'un 13 versiyonundan itibaren desteklenen bu özellik sayesinde siteler kendi sertifikalarının fingerprint yani hash değerlerini Public-Key-Pinning response headerı ile tarayıcılara bildirebiliyor.

Tarayıcılar bu sertifikaları hafızalarına alıp, bundan sonra bu sitelere herhangi bir istekte bu belirtilen sertifikalar dışında bir sertifika iddia edilirse, güvenli bağlantı kurmayı reddediyor, hatta bu örnekte olduğu gibi belirtilen URL'e rapor ediyor.

İşte Public-Key-Pinning özelliği, güvenli iletişim için mecbur olunan otoritelerin, bir şekilde sahte sertifika imzalamaya zorlandığı durumlarda, kullanıcı ve sitelerimizi korumamızı sağlıyor.

PKP Headerımızı Nasıl Set Edebiliriz?

Public-Key-Pinning'in de bir güvenlik headerı olduğundan söz ettik. Yine güvenli bir bağlantı üzerinden (HTTPS) gönderdiğimiz Public-Key-Pinning headerı ile PKP özelliğini etkinleştirebiliriz:

Public-Key-Pins: pin-sha256="d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=";
pin-sha256="E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g=";
report-uri="http://example.com/pkp-report"; max-age=10000; includeSubDomains

Alanları inceleyecek olursak,

pin-sha256="<sha256>" : Sertifikamıza ait açık anahtar parmakizinin (fingerprint) base64 encoded hali. Burada birden fazla genel anahtar bilgisi, yedek sertifika bilgileri de tanımlayarak, sertifikalarımızdan birinin expire olması durumundaki aksaklıkları yönetebiliriz.

max-age : Saniye cinsinden, sertifika bilgilerinin browser belleğinde tutulacağı süreyi belirtir.

includeSubdomains : Domaine ait altdomainler için de bu sertifika pinning işleminin uygulanıp uygulanmayacağını belirtir.

report-uri : Google örneğinde olduğu gibi, olası bir ihlal durumunun bildirileceği adresi tanımlar. İhlal bilgileri, burada belirtilen adrese POST metodu ile gönderilecektir.

Public-Key-Pinning mekanizmasını Report-Only modunda tanımlayarak, browserın sertifika zorlaması yapmasını engelleyebilir, yalnızca olası bir ihlal durumunda report-uri'de belirtilen adrese bildirimde bulunmasını sağlayabilirsiniz:

Public-Key-Pins-Report-Only:
pin-sha256="d6qzRu9zOECb90Uez27xWltNsj0e1Md7GkYYkVoZWmM=";
pin-sha256="E9CZ9INDbd+2eRQozYqqbQ2yXLVKB9+xcprMF+44U1g=";
report-uri="http://example.com/pkp-report"; max-age=10000; includeSubDomains

HPKP 'yi açıklayan RFC'ye göre en az 2 pinlemeniz öneriliyor. Biri hali hazırda kullandığınız sertifika için, diğeri de backup sertifikanız için. Şayet bu 1 sertifika pinlerseniz bu değer ignore edilecektir:

The given set of Pins contains at least one Pin that does NOT refer to an SPKI in the certificate chain. (That is, the host must set a Backup Pin; see Section 4.3.) (RFC 7469)

Araştırmaya göre aralarında Facebook.com ve WhatsApp.com 'un da bulunduğu devlerde dahi implementasyon eksiklikleri var. Alexa Top 1 Milyon'da yapılan araştırmaya göre HPKP headerlarında, hiç sertiifka pinlemeyen siteler de var, 17 adet sertifika pinleyenler de. HPKP'nin bu tür implementasyon sorunları ve çözüm önerilerine bir sonraki bölümde değineceğiz.

PKP Güvenlik Headerı Hangi Browserlarda Kullanılabilir?

PKP-Guvenlik-Headeri

Kaynak: https://caniuse.com/#search=Public%20Key%20Pinning

Expect-CT

Yukarıda PKP'yi ayrıntıları ile inceledik ancak bugünlerde HPKP 'nin deprecate edilmesi tartışılıyor.

HPKP - HTTP Public Key Pinning Ölüyor mu?

Bu tartışmanın başlamasından bir yıl sonra HPKP'nin yokluğunu tolere edebilecek imkanlarımız daha fazla. Certificate Authority Authorization (CAA), Certificate Transparency gibi güvenlik mekanizmaları ile birlikte, HPKP olmadan da izin ve bilgimiz dışında sitemiz adına imzalanmış sertifikalardan haberdar olabiliyoruz.

Peki HPKP olmadan bu işlemi nasıl yapabileceğiz? Yani yasa dışı sertifika imzalanması için, site sahibinin onayına ihtiyaç duyulmayan bu olasılığı nasıl devre dışı bırakacağız?

İlk tavsiyeye göre, Google'ın önce Ekim 2017'yi milat olarak kabul ettiği, sonra Nisan 2018'e kadar uzattığı Certificate Transparency teknolojisini kullanarak.

Buna göre Nisan 2018'den itibaren imzalanan her sertifika için CA genel erişime açık olan Certifate Transparency Log'una bu kaydı eklemek zorunda. Belirttiğimiz gibi bu kayıtlar genel erişime açık. Bu logda yapılacak olan taramalar ve alarm sistemleri ile siteleriniz adına herhangi bir CA tarafından imzalanan sertifika olup olmadığını görebilecek, haberdar olabileceksiniz.

Peki, domain sahipliğini doğrulamak zorunda olmayan CA'lar, loglara neden kayıt yazmak zorunda olsun?

Expect-CT burada devreye giriyor zaten. Tasarlanan şekliyle CA'lar her yeni imzaladıkları sertifika kaydını bu loga eklemek zorunda. CT mekanizmasının üç sac ayağı var. Bunlardan birincisi, logları beslemek ki bu CA'ların görevi, diğeri monitör ve denetleme. Ki bunu site sahipleri ve siteyle bağlantı kuran araçlar yapmak zorunda. Site sahibi olarak bizim payımıza düşenlerden biri Expect-CT headerını eklemek ve denetimde bunu zorlamak. UA'lar da (User-Agent), kendilerine bildirilen sertifikaların bu şartı taşıyıp taşımadığını kontrol edecek. Bu işi kolay kılmak adına el sıkışma esnasında, sertifikanın kendisi ile beraber, sertifikanın bu logdaki kaydına ilişkin kanıt olarak SCT (Signed Certificate Timestamp) bilgisi sunulmakta. Bu bilgi, bu sertifika imza kaydının loga yazıldığı zaman damgası bilgilerini taşıyor. Browser da bu SCT bilgisinden hareketle kaydın doğruluğunu teyit etmiş oluyor.

Risk Nerede?

Şayet web sayfamız adına, Google'ın bu başlangıç saydığı tarihten önce yani Nisan 2018'den önce bir sertifika imzalandı ise ve bu sertifikanın zaman aşımı örneğin 10 yıl olarak set edildi ise, sertifika imzalanma tarihi itibari ile Google bunun CT loglarında olup olmadığını kontrol etmeyecek, HPKP gibi mekanizmalar da deprecate olacağı için sitemiz adına imzalanan böylesi bir sertifikadan normal şartlarda haberdar olamayacağız.

Ama şayet Expect-CT headerını set eder ve enforce edersek, max-age ile de bunun belirli bir süre browserda saklanarak zorlayıcı bir madde olarak uygulamasını istersek, sitemiz ile bağlantı kurulurken browser tarafından karşılaşılan ve CT log şartlarını taşımayan sertifikalar kabul edilmeyecek. Böylece riski ortadan kaldırmış olacağız.

Nasıl İmplemente Edilir?

Öncelikle hali hazırda sertifikamız CT destekli mi ona bakmalıyız, bunun için SSL Labs'in raporundan istifade edebiliriz.

https://www.ssllabs.com/ssltest/analyze.html?d=netsparker.com

Akabinde:

HTTP Response'unda aşağıdaki gibi bir header kullanılarak Expect-CT headerı devreye alınabilir:

Expect-CT headerı üç opsiyonla birlikte kullanılıyor

Expect-CT: enforce,max-age=30,report-uri="https://ABSOLUTE_REPORT_URL"

max-age: Yönergenin browser belleğinde ne kadar süre ile (saniye cinsinden) saklanacağını belirtiyor.

report-uri: Uyumsuzluk durumunda, ihlalin raporlanacağı adres. Absolute URL olmak zorunda.

enforce: Eğer CT'ye uyumlu bir sertifika belirtilmedi ise bağlantının sonlandırılıp sonlandırılmayacağı belirtiliyor.

Başlangıçta enforce metodunu kullanmayan report only mode'da çalıştırabilirsiniz.

Expect-CT: max-age=30,report-uri="https://ABSOLUTE_REPORT_URL"

Şayet sizin sertifikanız ile ilgili her şey beklendiği gibi ise enforce edebilirsiniz:

Expect-CT: max-age=30,report-uri="https://ABSOLUTE_REPORT_URL", enforce

Referrer-Policy

Referer, maalesef hem yanlış yazılan (bir hata sonucu Referrer kelimesi Referer olarak implemente edilmiştir.), hem de yeterince anlaşılmayan bir istek (request) headerı.

Bir site, kendisi üzerinden başka bir siteye erişim yapıldığında, Referer headerı ile kendi adresini belirtir. Hedef site de yine Referer headerı ile bu gezinime kaynak teşkil eden siteyi görebilir. Referer headerı sadece site üzerindeki bir link tıklandığında değil, aynı zamanda stil, imaj ve script yüklemelerinde, form gönderimlerinde de yapılan isteğe eklenecektir. Örneğin A.com üzerinde B.com 'a ait bir reklam varsa, bu reklam üzerinden B.com 'a erişiliyorsa, B.com 'a yapılan istekte Referer headerı gözükecektir.

GET / HTTP/1.1
Host: B.com
Referer: A.com

Güvenlik, gizlilik ya da geri izleme bağlantıları verebilmek gibi nedenlerden ötürü Referer headerını kontrol etmek isteyebilirsiniz.

Bir response headerı olarak Referrer-Policy, aşağıdaki opsiyonları sunarak, "Referer" istek headerını kontrol etmemizi sağlıyor.

Referrer-Policy headerı, HTTP yanıt mesajında aşağıdaki gibi set edilebilir:

Referrer-Policy: no-referrer

Referrer-Policy headerının alabileceği muhtemel değerler şunlardır:

"" (empty)

Referrer-Policy'nin set edilmediğini ve Referer'ı konrol edecek direktifin, <meta> tagları ile ya da rel ya da referrerpolicy attributeları ile isteği tetikleyen HTML elemanı tarafından tanımlanabileceğini belirtir.

Referrer-Policy:

"no-referrer"

Siteden kaynaklanan hiçbir isteğe, kendisi ile aynı originine sahip bir kaynağa yönlenmiş bile olsa, Referer headerı eklenmemesini sağlar. Bu durumda Referer alanı gönderilmeyecektir.

Referrer-Policy: no-referrer

"no-referrer-when-downgrade"

Protocol down grading olarak bilinen, daha güvenli bir protokolden daha az güvenli bir protokole geçişte, örneğin HTTPS'den HTTP protokolüne geçişte Referer headerı gönderilmeyecektir.

Referrer-Policy: no-referrer-when-downgrade

Bu aynı zamanda browserların varsayılan (default) davranışıdır.

"same-origin"

Origin; şema, domain ve port birleşiminden oluşan tanımlayıcı bir string. Netsparker Türkiye Blogu'nda yayınlanan Same Origin Policy isimli yazımızda ayrıntılı bilgiler bulabilirsiniz.

Referrer-Policy 'nin alabileceği same-origin seçeneğinde yalnızca aynı origin'e sahip bir siteye istek yapıldığında, Referer headerı gönderilecektir.

Referrer-Policy: same-origin

"origin"

URL'deki path kısmı atılarak, yalnızca şema-domain ve port'dan oluşan origin, istekteki Referer alanına eklenecektir.

Referrer-Policy: origin

Protocol-down-grading, yani HTTPS'den HTTP'e geçişte sadece origin bilgisi (PATH bilgisi çıkarılarak) istek yapılan HTTP siteye Referer ile gönderilecektir.

"strict-origin"

Origin'de belirttiğimiz protocol-down-grading case'ini tölere etmek için sunulan bir seçenektir. Referer'de origin bilgisi, ancak kaynak siteden, aynı protokol kullanan (örneğin HTTP->HTTP ya da HTTPS-HTTPS), ya da kaynak isteden daha güvenli bir protokol kullanan hedef sitelere (HTTP->HTTPS) sitelere erişilmek istenildiğinde gönderilecektir.

Referrer-Policy: strict-origin

"origin-when-cross-origin"

Hedef ve kaynak aynı origin'e sahip ise Referer headerında FULL URL (şema+domain+path); eğer farklı bir origin'e sahip ise sadece şema ve domain bilgisi gönderilecektir.

Referrer-Policy: origin-when-cross-origin

Protocol-down-grading, yani HTTPS'den HTTP'e geçişte de origin bilgisi, istek yapılan HTTP siteye Referer yolu ile gönderilecektir.

"strict-origin-when-cross-origin"

origin-when-cross-origin çok benzer olan bu seçenek, protocol-down-grading'de karşılaşılan case'i tolere etmektedir. Buna göre, Referer bilgisinde origin, kaynak site ve hedef aynı protokole ya da hedef daha yüksek bir protokole sahip olduğunda gözükecektir.

Referrer-Policy: strict-origin-when-cross-origin

"unsafe-url"

Browser, her koşulda kaynak siteden hedef siteye yapılan isteğin Referer bilgisinde full URL'i paylaşacaktır.

Referrer-Policy: unsafe-url

Bu seçenekte, güvenli bağlantılardan güvensiz bağlantılara erişimde full URL'in paylaşılacağını unutmamalısınız. Sizi browserların varsayılan davranışından da (protocol-down-grading'de URL ifşasının engellenmesi) geri düşüren bu seçenek dikkatle kullanılmalıdır.

Referrer-Policy Güvenlik Headerı Hangi Browserlarda Kullanılabilir?

Referrer-Policy-Guvenlik-Headeri

Kaynak: https://caniuse.com/#feat=referrer-policy

Referrer-Policy güvenlik headerının ayrıntıları hakkında Netsparker Türkiye Blogu'nda yayınlanan yazımızı okuyabilirsiniz.


[1] http://teknoloki.com/634-turktrust-ve-sertifika-sorunu.html
[2] http://www.turktrust.com.tr/tr/hakkimizda/haber/teknik-aciklama