Tarayıcı Güvenliği: Same Origin Policy vs CORS, Misconfigurations

Ahmet Can KARAAĞAÇLI
6 min readDec 10, 2021

Doğrudan Same origin policy konusuna girmeden önce kısaca web storage ve cookie kullanımı hakkında bilgi edinmek faydalı olabilir.

Web storage HTML5 ile birlikte gelen, verilerin tarayıcı tarafında saklanabileceği ve javascript ile erişilebilen bir database teknolojidir. Local Storage ve Session Storage olmak üzere iki farklı depolama alanı bulunur.

Aslında ikisi de aynı amaçla, yani veri depolamak ve bu verileri tarayıcı tarafında javascript ile kullanmak amacı ile kullanılır. Local Storage içindeki veriler manuel olarak silinmediği sürece ilgili tarayıcıda kalıcıdır. Session Storage ise yalnızca ilgili tab açık kaldığı sürece hayatta kalır. Local Storage içerisindeki veriler tarayıcı üzerinde açık olan tüm tablardan erişilebilirken (yalnızca ilgili domain, ilgili bilgilerine erişir), session storage içerisindeki veriler yanızca ilgili tab tarafından erişilir. Session Storage adı üzerinde yalnızca session hayatta olduğu sürece, ilgili sekme yaşadığı sürece erişilebilir olur, ilgili sekme kapandığında veriler silinir.

Cookie ise HTML5 ten daha önce HTML4 zamanında da var olan, web storage a göre daha eski ve saklama alanı olarak çok daha küçük bir saklama alanıdır. Sunucu yanıtlarından gelen cookie değerlerine göre setlenir ve ilgili domaine yapılan her isteğe eklenerek sunucuya iletilir.

Farklı bir bakış ile:

Burada aklımızda kalmasını istediğimiz nokta tarayıcıdan herhangi bir web sitesine istek iletilirken, eğer tarayıcıda ilgili web sitesine ait cookie bilgisi varsa, request bu cookie değeri eklenerek gider. Dolayısıyla oturum açtığınız websitesine gidecek olan tüm istekler oturum açmış bir şekilde (authenticated) gidecektir. Bu bilgiyi göz önünde bulundurduğumuzda Same Origin Policy daha anlaşılır olacaktır.

Same Origin Policy

Kullandığımız web uygulamaları javascript kullanarak web sayfalarını interaktif hale getirirken aynı zamanda javascript arka planda istek gönderme ve gelen yanıtlara göre web uygulaması arayüzünü güncellemek gibi işlevleri yerine getirir. Biz tarayıcının yenilendiğini görmesekte, arka planda bize sunulan HTML görseli üzerinde değişiklikler yaparken aynı zamanda sunucu ile iletişime geçerek arka tarafta web isteklerinde bulunabilirler. Javascript ile yapılan web istekleri Same Origin Policy kurallarına uymak zorundadır.

Same origin policy, yani aynı kök politikası, tarayıcıların kullanıcının açtığı web sitesi içerisinde çalıştırılan javascript isteklerinin sitenin adresinden (kök) farklı bir adrese istek yapmasını engelleyen bir güvenlik mekanizmasıdır.

Örneğin google.com web uygulamasını açtığımızda, arka tarafta çalışan javascript uygulamaları google.com adresinden başka bir websitesine istek gönderemez. (gönderebilir ama bazı koşullarda) Tarayıcıda çalıştırılan javascript kodları sizin tarayıcınızın üzerinden başka bir siteye istek gönderemez. Bunu denediğimizde “cross origin request blocked” şeklinde hata ile karşılaşırız.

Aynı tarayıcı üzerinde farklı sekmelerde facebook ve online bankacılık hesabımızın açık olduğunu düşünelim. Same origin policy, facebook uygulamasının yan sekmede açık olan bankacılık uygulaması DOM yapısına erişemediği gibi bu banka uygulaması domain adresine javascript ile istek göndermeye çalışamaz. Çünkü gönderebilseydi biliyoruzki bu istekler tarayıcıdaki cookie bilgisi eklenerek gidecek ve kullanıcılar adına işlemler yapılabilecekti. Tarayıcı, javascript ile yapılan web isteklerinin SOP (Same Origin Policy) kuralına uygunluğuna karar verirken websitenin origin bilgisi ve javascript ile istek yapılan websitesinin originlerini karşılaştırır.

Origin: şema (http/https..) + domain (google.com, youtube.com …) ve port numarasının (443,80,8080) birleşiminden oluşur.

Aşağıda daha iyi anlaşılması açısından bazı örnekler incelenebilir.

Google.com adresinde iken javascript HMLHttpRequest ile youtube.com adresine istek göndermeye çalışalım.

Tarayıcı Same Origin Policy kurallarına bakarak bu işlemi yapamayacağımızı belirtiyor.

Dolayısıyla Same Origin Policy bir websiteyi diğerlerinden izole eder. Başka bir siteye gönderilmek istenen requestleri engeller.

CORS İstisnası

Biliyoruzki günümüzdeki web uygulamaları birden fazla sunucudan, domainden veya farklı web uygulamalarından javascript (XHR) istekleri ile veri alışverişi yaparak hizmet veriyor. Ancak yukarıda bahsedildiği gibi Same Origin Policy bu duruma engel bir kural tanımlıyor.

Geliştirilen uygulamalar javascript ile farklı domainlere ve originlere istek yaparak bilgi alışverişi yapmak istiyorsa SOP kuralını burada esnetmek için CORS bize yardımcı olur. CORS için (Cross Origin Resource Sharing), adı üstünde originler arası kaynak paylaşımı diyebiliriz. Bu mekanizmayı anlamak için SOP kuralının nasıl uygulandığına bir tık yakından bakabiliriz.

Tarayıcılar SOP kuralını uygulamak için javascript ile istek gönderilmeye çalışılan web uygulamasına öncelikle options metodu ile preflight isteği gönderir. (Preflight isteği bazı koşullar gerçekleştiğinde gönderilir, bazı http metodları ve başlıklarının set edilmesi gerekir. Preflight isteği gönderilmediği durumlarda da engellemeler devam eder, fark olmaz.) Bu isteğin amacı karşı sunucuya birazdan göndermek istenilen isteğin uygun olup olmadığını sormaktır. Eğer isteğin iletildiği sunucuda gerekli CORS headerları tanımlandıysa bu isteğe izin verecektir. Ancak tanımlanmadıysa options methodu ile gelen isteğe red yanıtını vererek javascriptin asıl göndermeye çalıştığı isteği tarayıcı göndermeyecektir.

Gerçek dünyada örnek göstermek adına google.com adresinden stackoverflow.com web uygulamasına yapılan xmlhttprequest isteği için firefox devtools üzerinden konsol loglarını okuduğumuzda aşağıdaki mesajları görebiliriz. Aslında mesajda direkt olarak stackoverflow.com adresinin google.com adresini CORS Policy sebebiyle reddettiğini, preflight isteğinin access control ünü geçemediğini ifade ediyor.

İlgili options isteğini incelediğimizde tarayıcının isteğin başlık bilgilerine otomatik olarak eklediği headerlar arasında “Access-Control-Request-Method” ve “origin” başlığını görebiliriz. Tarayıcının eklediği bu başlıklara göre karşıda isteği karşılayan sunucu CORS kontrollerini yapacaktır.

Cross Origin Resource Sharing

Cross Origin Resource Sharing bir standarttır. Sunucunun, tarayıcı üzerinden kendilerine kimin javascript istekleri ile ulaşıp ulaşamayacağına karar verebilmesini sağlayan bir mekanizmadır. Dolayısıyla CORS, Same Origin Policy nin sağladığı kısıtlamaya bir çözüm, ihtiyaca göre bir atlatma tekniği olarak kullanılır.

Bir diğer deyişle web uygulamamızın başka web uygulamaları üzerinden gelecek olan javascript isteklerine (XHR) nasıl yanıt vermek istediğini belirtmek için CORS başlıkları kullanılır. Aşağıda sunucu tarafında tanımlanan bu başlık bilgilerini ve alabileceği örnek değerleri biraz inceleyebiliriz.

Access-Control-Allow-Origin

Bu başlık ile hangi originlerin istek gönderebileceği belirlenir.
Access-Control-Allow-Origin: youtube.com -> youtube.com adresinden gelen istekler CORS kontrolünü geçerek iletilir.
Access-Control-Allow-Origin: * -> Tüm originlere izin ver.

Access-Control-Allow-Methods

Bu başlık ile hangi metodlara izin verilmesi gerektiği belirtilir.
Access-Control-Allow-Methods: GET,HEAD,PUT,PATCH,POST,DELETE

Access-Control-Allow-Headers

Bu başlık ile, gelecek olan istek içerisinde hangi başlık bilgilerine izin verileceği belirtilir.
Access-Control-Allow-Headers: Content-Type, Accept

Access-Control-Max-Age

Bu başlık ile preflight isteğine dönen yanıtın ne kadar süre ile cachelenerek tekrar istek atılabileceğini belirtir.
Access-Control-Max-Age: 1728000

Access-Control-Allow-Credentials :

Bu başlık bilgisi ile gelen isteklerin cookie bilgisi ile birlikte kabul edilip edilmeyeceği değerlendirilir. Yani gelen istek authenticated kabul edilebilir mi bunu ifade eder. Yazının başında cookie bilgilerinin otomatik olarak gönderileceğinden bahsetmiştik. İsteği alan sunucunun bu cookie bilgilerini kabul edip etmeyeceğini bu başlık belirleyecektir.

Access-Control-Allow-Credentials: true
Access-Control-Allow-Credentials: false

Sunucu tarafında yukarıdaki response headerları belirlendikten sonra gelen isteğin CORS tarafından kabul edilebilmesi için tüm header kontrollerinden geçmesi gerekir. Yani bu durumda origin doğru ve geçerli olabilir ancak request headerları içerisinde kabul edilmeyen bir header olursa CORS mekanizması false dönecek, istek reddedilecektir.

Bu bilgiler doğrultusunda, karşılaşılabilecek bazı senaryoları, bunların risklerini ve etkilerini daha iyi anlayabilmek için araştırma yaparken denk geldiğim bir tabloyu biraz değişiklik yaparak paylaşmak isterim. Güvenlik araştırması yaparken otomatize tarama araçlarında çıkan CORS bulgularını doğru değerlendirmek adına faydalı olabilir.

https://www.packetlabs.net/cross-origin-resource-sharing-cors/

Kaynaklar

--

--