PCI/DSS ile Payment Gateway’ler Arasındaki HTTP Security Headers Tartışmaları

Son zamanlarda tüm payment gateway firmalarındaki tanıdığım/sevdiğim insanlardan aldığım telefon aramalarının ana konusu olan hususa dair bir takım doğru şeyleri yazmaya ihtiyaç duydum. Kuvvetle muhtemel uzunca bir süre daha bu blog’da yazı yayınlamıyor olacağımdır. (Tüm teknik makaleleri https://pentest.blog adresinde yayınlıyorum artık)

Hikayenin başlangıcı şöyle; güzide ülkemizde PCI/DSS taraması gerçekleştiren firma(lar?), özellikle OWASP’ın yeni top 10 listesi yayınlaması sonrasında, HTTP başlık bilgilerinde kendisine yer edinen güvenlik header’larının eksikliğini bulgu olarak raporlamaya başladı. Pek tabi bu hareketi, güvenliği ileriye taşıyan force eden bir yaklaşım olduğu için takdir etmiştim. Lakin bir süre sonra birlikte çalıştığımız payment gateway firmalarından bir çok soru alınca aslında fikrim biraz değişmeye başladı.

Şimdi öncelikle http security header’larına vakıf olmayan arkadaşlar için söz konusu başlık bilgilerini, birer cümle ile açıklayayım. Bu bilgileri bilen okurlar / istemeyenler direk bir sonraki bölüme geçebilir.

1 – Strict-Transport-Security (HSTS)

HTTP Strict Transport Security, nâmı diğer HSTS, kullanıcıların internet tarayıcılarını her talep için HTTPS kullanmaya zorlayarak downgrade adı verilen saldırılara karşı çözüm üretmek ve tüm trafiğin güvenliğini sağlamak adına güzel bir çözümdür. ( Daha detaylı bilgi için; https://www.mehmetince.net/hsts-http-strict-transport-security-ile-https-trafik-guvenligi/ )

2 – X-Frame Options

Web uygulama güvenliği konularından bir tanesi olan Clickjacking (UI Redressing), X-Frame-Options başlık bilgisi ile doğrudan ilişkilidir. Saldırganın kendi kontrolü altında olan web sitesi içerisinde iframe çağrısı gerçekleştiren saldırganlar, kullanıcılara istemedikleri aksiyonları aldırmaya çalışırlar.

Bu nedenle web sitemizi iframe içerisinde kimlerin çağırabileceğine karar vermek ve bu kararımızı internet tarayıcılarına belirtmek gerekmektedir.

3 – X-XSS-Protection

Modern tarayıcılar, uygulama tarafından oluşturulan içerik üzerinde filtreleme gerçekleştirerek potansiyel XSS payloadlarını tespit edebilirler. Bu özelliği aktifleştirmek içinse X-XSS-Protection başlık bilgisi kullanılır. Pek tabi özellikle sadece Reflected XSS  zafiyetleri için engelleyici olacaktır.

4 – X-Content-Type-Options

Özellikle Internet Explorer başta olmak üzere internet tarayıcıları kendilerine web uygulaması tarafında sunulan içerik üzerinde MIME Type Sniffing adı verilen analizi gerçekleştirerek, içeriğin tipine karar vermeye çalışmaktadır. Örneğin bir PDF dosyası veya JPEG dosyasına erişim talebi olduysa, HTTP cevabı üzerinde analiz gerçekleştirerek dosya tipi tahmin edilmeye çalışılır.

Örneğin; Uzantısı jpeg olan ama içeriği text/html olan bir dosyayı düşündüğümüzde, upload modülünde ki korumalar uzantılı ile aşılarak dosyanın yüklenmesi başarıyla sağlanır. Yüklenen dosya URL üzerinden çağırıldığında MIME Type sniffing sonuç olarak text/html döndürecek ve içeriği HTML olarak render edecektir. En nihayetinde ise Stored XSS zafiyeti oluşacaktır.

5 – Content-Security-Policy

Kullanıcıların internet tarayıcılarının hangi kaynaklardan JS, CSS, resim vb kaynaklara erişebileceğinin kurallarının tanımlama yöntemidir. Yani sizin sitenizi ziyareten eden kullanıcı, HTML içeriğinde yazıyor olsada hacker.com/saldiri.js adresinden javascript içerik alamaz, diyebilme imkanımız vardır. Özellikle XSS saldırılarında, saldırganların uzak sistemden kendi JS kodlarını inject etmeyi engellemenin en güzel yollarından birisidir.

6 – Public Key Pinning (PKP)

TürkTrust vakasını hatırlayan var mı ? İnternet tarayıcıları tarafından otorite olarak tanınan TürkTrust firması, 2013 yılında *.google.com adresi için sertifika imzaladı!

The TURKTRUST SSL certificate fiasco – what really happened, and what happens next?

Yani korktuğumuz ve korunmak istediğimiz risk şu; ben full HTTPS servis veriyorum. Lakin olurda birisi (state sponsored hacker/goverments?) mehmetince.net için yetkili bir firmadan (türktrust gibi) sertifika imzalatmayı başarırsa ?

Chrome’un yeni versiyonuyla birlikte siteler kendi sertifikalarınınhash değerlerini Public-Key-Pinning ile tarayıcılara bildirebilmekteler. Böylece tarayıcı bu bilgiyi hafızasına kayıt eder. Sizinle yapılan her iletişimde bu değer tarayıcı tarafından kontrol edilecektir. Olurda birisi veya biriler, sizin domain adınız için kendi ürettiği bir sertifikayı otoritelere imzalatmayı başarsa bile, internet tarayıcısı hash değeri tutmadığı için iletişimi sonlandıracaktır.

PCI/DSS Testleri

Bildiğini üzere PCI/DSS testleri otomatize bir süreç olmuş durumda. Yani aslında basitleştirilmiş bir “vulnerability assessment” süreci diyebiliriz. Pek tabi otomatize edilmiş, detaylı analize tabi tutulmadan, vulnerability scanning sonuçlarını yani Qualys ile tara sonuçlarını rapor al ve ilet bir başka iş modelidir. Özetle kemiksizdir. Bunda da kötü olan bir şey yoktur.

Tahminimce, OWASP’ın yeni top 10 yayınlamasından sonra Security Header’ları PCI/DSS testlerinde PASS/FAIL’a tabi olmaya başladı. Açıkcası PCI’ın bu konuda özel ifade ettiği bir check var mı diye araştırıp bulamadım (var ise bana ulaştırabilir misiniz ?). Yani PCI’nın hangi security header’larının olmasını zorunlu tuttuğunu şu anda bilemiyorum. Bu testleri gerçekleştiren arkadaşların da yaptığı işin, aşağıdaki akış çerçevesinde yaşandığını düşünüyorum.

1- PCI/DSS kapsamına tâbi olan URL/IP listesini al.

2 – Qualys’e ver. (Authenticated web app scan ? Umarım öyledir. Lakin kimle görüştüysem, biz yılda 4 defa yapılan bu external test için test hesabı vermemekteyiz demekte.)

3 – Qualys hepsini gezer. Aradığı security header’larını bulamaz.

4 – Security Header’larının olmadığını gören tester, FAIL olarak raporlar.

“İlgili security header’ının olmayışı, uygulamanın bu header’ı koymak zorunda olduğu anlamına gelmez!”

Bu kontroller otomatize yapıldığı için; uygulamanın özellikleri ve business’ı göz önüne alınmadan, sadece security header’ın var olmamasından mütevellit FAIL olarak ifade edilmesi yanlıştır. Ayrıca bu header’lardan bazılarının ise kullanımına artık gerek yoktur.

Gerçek örneklerle anlatayım;

Örnek #1 – All in for SSL or not ? HSTS

HSTS’e aktifleştirelim. Tamam gayet kolay. Peki ben includeSubdomain‘i kullanmak istemiyorsam ? Çünkü developer arkadaşlarımız hosts dosyalarında dev-odeme-v2.payment.com yazarak, yerel test isimlerinin çözümlendirmesi yapıyorlar. Ben includeSubdomain‘i kullanırsam yazılımcılarımızın bu sistemi sorun yaşayacak yada sertifika üretip imzalatmam gerekecek (HSTS enable iken, imzasız sertifika varsa “riski kabul ediyorum, devam et” butonu çıkamz). Ayrıca ben blog.payment.com adresimde SSL kullanmak istemiyorum. Hele ki preload konusuna hiç girmeyelim.

Peki includeSubdomain ve preload flag’lerine ses etmiyoruz denildi. Gayet güzel. Peki ben bir reverse proxy ile payment uygulamama mapping’i www.payment.com/odeme adresinden yapıyorum. HSTS’de URI değil domain bazında bir konfigürasyon. Nasıl olacak ?

Çözüm: Ödeme yazılımlarınızı alt alan adında çalıştırın ve sadece subdomain’lerinizde Strict-Transport-Security: max-age=31536000; set edin geçin. Herhangi bir ek flag kullanmayın.

Örnek #2 – Ben kullanıcılarımdan dosya almıyorum ki ? Niye X-Content-Type-Options set edeyim ?

Bildiğiniz üzere X-Content-Type-Options olmadığı zaman bir “siber saldırı” düzenlemek için, uygulamanın kullanıcı olarak benden aldığı dosyayı aynı isimli başka bir yerden download ettiyor olması gerekiyor. Yahu bir başka şekilde uygulama sunucusuna dosya yüklemeyi başarmak durumundasınız.

Ayrıca, tüm JS ve CSS dosyalarımı sunarken doğru content-type değerini sunuyorum. Öte yandan benim uygulamam (hemen hemen bir çok payment gateway servisinde olduğu gibi) kullanıcıdan dosya alımı, download olarak sunulmuyor. O durumda bu flag’i niye set etmek zorundayım ???

Çözüm: set etmeyin.

Örnek #3 – Yahu bu benim API/CDN servisim. Niye Content-Security-Policy vs sunayım ?

Evet, en çok şaşırdığım vaka buydu. http://api.payment.com adresinde niye X-Frame-Options, efendime söyleyeyim Content-Security-Policy, X-XSS-Protection header’ları yokmuş ? Sadece JSON ve XML dönülen, herhangi renderable bir (HTML) içerik sunulmayan API servisi için bu header’ların olması zorunlu değildir. Hatta olmamalıdır. Hiçbir API client kütüphanesi bu header’ları kullanmaz, aramaz. Dediğim gibi, uygulamanın business’ını ve amacını anlamadan sadece header var mı ? yok mu ? diye bakmak çok yanlıştır.

Öte yandan CSP çok ama çok tricky bir özelliktir. Ciddi bir test süreci ve teknik analiz gerektirir. Yani atılan taş ürkütülen kuş, bir diğer deyişle maliyet hesabı ve önceliklendirme açısından bakıldığında, minimum 3 ay maksimum 1 yıl içerisinde yapılabilecek bir task’tır. Bu nedenle “30 gün içerisinde çözülmeli” noktasına varan retest takvimi hiç ama hiç adil değil. Tamam, CSP olsun. Herkes yapsın çok güzel. Ama en azından ön bilgilendirme yapılarak firmalara geniş bir süre zarfı verilebilir. Şu anda tam anlamıyla CSP’i bilen yazılım geliştiriciler bile yok. İnsanlara biraz zaman lazım. (Son 1 yıl içerisinde 4 farklı yazılım geliştiricisi grubuna client-site security eğitimi organize edildi, CSP’i nedir bilen henüz çıkmadı.)

Çözüm: Bu tür servisler için set edilmemeli.

Örnek #4 – X-XSS-Protection

Günümüzde X-XSS-Protection ve unsafe-inline’ı aktifleştirilmiş bir Content-Security-Policy ‘nin bir arada kullanılmasına gerek yoktur. Nedenlerini anlatmaya dilim yetmeyeceği için, şu linke bakıp bana inanmanızı isterim. (https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection) Bu iki header birbiriyle olan ilişiğine bakılmaksızın, yoksa FAIL varsa PASS raporlaması yapılıyor anladığım kadarıyla.

Ayrıca X-XSS-Protection sadece Chrome, Safari ve IE için geçerli(ydi). Evet, browser bazlı XSS blacklisting filter’ları ilk çıktığında disabled bir feature idi. Yani sizin manuel bir şekilde elle aktifleştirmeniz gerekiyordu. Günümüzde ise X-XSS-Protection: 1  değerinin olmayışı ciddi bir risk değil. Zira Chrome, Safari ve IE bu özellik by default enabled’dır. Yani kapatmak isterseniz X-XSS-Protection: 0 yollamak gerekir ki, bunu yapmayın.

Çözüm: Denetimi yapan firma bu detayları anlamıyorsa, set edin geçin. Uygulamanızın herhangi bir özelliğinizi bozmaz.

Örnek #5 – Oskar Adayı; X-Frame Options

Biliyorsunuz değil mi, payment gateway servislerinin en önemli özelliklerinden birisi, doğrudan e-ticaret sitenizin checkout sayfasında ödeme formunu sizin yerinize generate edebiliyor olması. Yani siz ödeme ekranları ile uğraşmazsınız. Ödeme sayfasına gelen adamın karşısına, kredi kartı vb bilgileri gireceği ekran https://merchant.paymentgateway.com/XXX adresinin IFRAME ile çağırılmasıyla oluşur. Yani günümüz modern browserlar üzerinden yapılması çok zor olan UI Redressing ataklarının düşük olan bu riskleri payment gateway sektöründe by default kabul edilmelidir (bence)

Çözüm: Uygulama genelinde aktifleştirebilirsiniz. Yalnızca Checkout url’lerinizin controller’larında bu özelliği override edin ve kaldırın. Aklıma gelen başka daha tatlı yöntemler var lakin, %100 çalışırlığından emin değilim o nedenle ifade etmeyeceğim. Zira ilk dediğim çözüme de FAIL denirse, ne diyeyim. Vurun.

Örnekler uzarda gider. Zira bir takım başka örnekleri, firmaya özel bilgileri ifşa etmeden anlatılamayacağı için yer veremiyorum.

ÖZET

Sadece HTTP response header’lara bakarak “Aaaa X-XSS-Protection yok, FAIL” denilmesi başlı başına bir FAIL’dir. Her uygulama kendi özelinde farklı riskleri ve feature’ları barındırır. Bu özellikler göz ardı edilere mass bir test, özellikle bu konuda yapılmamalı. Sizler, her header’ı kendi uygulamanızın özellikleri ve business’ına göre set edip etmeyeceğiniz belirleyebilirsiniz. Akabinde de her header’ın etkileri ve teknik çalışması yapılabilir. Set edilmeyecek durumlarda ise doğru gerekçeler ile denetimi yapan firmaya bilgi verilebilir.