Takip et

Bu CORS Hatası API’nizi Ortaya Çıkarıyor (Her Yerde Görüyorum)

Cross-Origin Resource Sharing (CORS), tarayıcıların farklı kaynaklardan (domain, protokol veya port) gelen kaynaklara erişimini kontrol eden bir güvenl…

Bu CORS Hatası API’nizi Ortaya Çıkarıyor (Her Yerde Görüyorum)

Web geliştirmenin derinliklerine indikçe, çoğu zaman gözden kaçan veya yanlış anlaşılan kritik güvenlik mekanizmalarıyla karşılaşırız. Bunlardan biri de Cross-Origin Resource Sharing (CORS) politikasıdır. CORS, modern web uygulamalarının temel taşlarından biri olmasına rağmen, yanlış yapılandırıldığında API’lerinizi beklenmedik ve tehlikeli güvenlik açıklarına maruz bırakabilir. Özellikle Access-Control-Allow-Origin: * kullanımı, masum gibi görünse de, çoğu durumda bir güvenlik felaketine davetiye çıkarır. Bu makalede, bu yaygın hatayı, neden tehlikeli olduğunu ve API’lerinizi güvende tutmak için doğru CORS yapılandırmasının nasıl olması gerektiğini detaylıca inceleyeceğiz.

CORS Nedir ve Neden Hayati Önem Taşır?

Cross-Origin Resource Sharing (CORS), tarayıcıların farklı kaynaklardan (domain, protokol veya port) gelen kaynaklara erişimini kontrol eden bir güvenlik mekanizmasıdır. Temelinde, web’in güvenlik modeli olan Same-Origin Policy (SOP) yatar. SOP, bir web sayfasının, yüklendiği kaynak dışındaki bir kaynaktan veri okumasını veya değiştirmesini engeller. Bu, kötü niyetli sitelerin kullanıcıların bankacılık sitelerinden veya e-posta hesaplarından veri çalmasını önlemek için tasarlanmıştır.

Same-Origin Policy (SOP) ve Güvenlik

SOP, bir belgenin veya script’in yalnızca aynı kaynakla (protokol, ana bilgisayar ve bağlantı noktası kombinasyonu) etkileşime girmesine izin verir. Örneğin, https://example.com adresindeki bir sayfa, https://api.example.com adresindeki bir API’ye istek gönderebilir, ancak https://malicious.com adresindeki bir API’ye doğrudan veri okuma amaçlı istek gönderemez. SOP, tarayıcı tabanlı saldırıları, özellikle de siteler arası komut dosyası çalıştırma (XSS) ve siteler arası istek sahteciliği (CSRF) gibi saldırıları önlemede kritik bir rol oynar.

CORS’un Doğuşu ve Amacı

SOP, web güvenliği için hayati olsa da, modern web uygulamaları genellikle farklı kaynaklardaki API’lerle veya kaynaklarla etkileşim kurma ihtiyacı duyar. Örneğin, app.example.com adresindeki bir frontend uygulaması, api.example.com adresindeki bir backend API’sine istek göndermek isteyebilir. SOP bunu engellerdi. İşte burada CORS devreye girer. CORS, sunucuların, farklı kaynaklardan gelen isteklere izin vereceklerini açıkça beyan etmelerini sağlayan bir mekanizma sunar. Bu sayede, SOP’nin katı kuralları, güvenli bir şekilde esnetilebilir.

CORS Nasıl Çalışır? Mekanizmayı Anlamak

CORS, temelde tarayıcı ve sunucu arasında bir dizi başlık değişimiyle çalışır. Tarayıcı, farklı bir kaynaktan bir istek gönderdiğinde, bu isteğin CORS kurallarına uygun olup olmadığını kontrol eder. İki ana istek türü vardır: basit istekler ve ön kontrol (preflight) istekleri.

Basit İstekler (Simple Requests)

Belirli koşulları karşılayan istekler “basit istekler” olarak kabul edilir. Bu koşullar şunlardır:

  • Metot: GET, HEAD veya POST olmalı.
  • Başlıklar: Yalnızca CORS güvenli listesindeki başlıklar (örn. Accept, Accept-Language, Content-Language, Content-Type). Content-Type için sadece application/x-www-form-urlencoded, multipart/form-data veya text/plain izinlidir.

Basit bir istekte, tarayıcı isteği doğrudan gönderir ve sunucudan gelen yanıtta Access-Control-Allow-Origin başlığını arar. Eğer bu başlık, isteği gönderen kaynağı içeriyorsa veya wildcard (*) ise, tarayıcı yanıta erişime izin verir. Aksi takdirde, tarayıcı isteği engeller ve bir CORS hatası fırlatır.

Ön Kontrol (Preflight) İstekleri

Basit istek koşullarını karşılamayan tüm diğer istekler (örn. PUT, DELETE metotları, özel başlıklar veya farklı Content-Type değerleri içeren istekler) bir “ön kontrol” (preflight) isteği ile başlar. Bu, asıl isteği göndermeden önce tarayıcının sunucuya bir OPTIONS isteği göndermesi anlamına gelir. Bu OPTIONS isteği, sunucunun asıl isteği kabul edip etmeyeceğini sorgular.

Ön kontrol isteği, aşağıdaki başlıkları içerir:

  • Access-Control-Request-Method: Asıl isteğin metodunu belirtir (örn. PUT).
  • Access-Control-Request-Headers: Asıl isteğin içereceği özel başlıkları belirtir.
  • Origin: İsteği gönderen kaynağı belirtir.

Sunucu, bu OPTIONS isteğine, asıl isteğin kabul edilebilir olup olmadığını belirten başlıklarla yanıt verir:

  • Access-Control-Allow-Origin: Hangi kaynakların isteklere izinli olduğunu.
  • Access-Control-Allow-Methods: Hangi HTTP metotlarının izinli olduğunu.
  • Access-Control-Allow-Headers: Hangi özel başlıkların izinli olduğunu.
  • Access-Control-Max-Age: Ön kontrol yanıtının ne kadar süreyle önbelleğe alınabileceğini.

Eğer sunucunun yanıtı, asıl isteğin gereksinimlerini karşılıyorsa, tarayıcı asıl isteği gönderir. Aksi takdirde, yine bir CORS hatası fırlatılır.

Yaygın ve Tehlikeli CORS Yapılandırma Hatası: Access-Control-Allow-Origin: *

En sık karşılaşılan ve en tehlikeli CORS yapılandırma hatalarından biri, sunucunun Access-Control-Allow-Origin başlığını * (wildcard) olarak ayarlamasıdır. Bu, “herhangi bir kaynağın bu API’ye erişmesine izin ver” anlamına gelir ve ilk bakışta esneklik sağladığı düşünülebilir. Ancak, çoğu durumda bu, API’nizi ciddi güvenlik risklerine açık hale getirir.

Wildcard Kullanımının Cazibesi ve Yanılgısı

Geliştiriciler, özellikle geliştirme aşamasında veya CORS hatalarından kaçınmak için hızlı bir çözüm arayışında olduklarında Access-Control-Allow-Origin: * kullanmaya yönelebilirler. Bu, tüm CORS hatalarını ortadan kaldırır ve API’nin her yerden erişilebilir olmasını sağlar. Ancak bu kolaylık, genellikle büyük bir güvenlik maliyetiyle gelir.

null Origin ve Diğer Beklenmedik Davranışlar

* kullanımı sadece bilinen domainler için değil, aynı zamanda file:// protokolüyle çalışan yerel dosyalar veya sandboxed iframe’ler gibi “null” origin’e sahip kaynaklar için de erişime izin verir. Bu, saldırganların yerel dosyalar aracılığıyla veya belirli iframe senaryolarında API’nize erişebileceği beklenmedik vektörler yaratabilir.

Bu Hata Neden Bir Güvenlik Açığıdır?

Access-Control-Allow-Origin: * tek başına her zaman bir güvenlik açığı değildir. Ancak, API’niz kimlik bilgileri (çerezler, HTTP kimlik doğrulama başlıkları, istemci sertifikaları vb.) ile çalışan istekleri destekliyorsa, bu yapılandırma kritik bir güvenlik açığına dönüşür.

Kimlik Bilgileriyle İstekler (credentials) ve Tehlike

Bir tarayıcı, farklı bir kaynaktan bir isteği kimlik bilgileriyle (örn. çerezler) göndermek istediğinde, isteğe credentials: 'include' veya withCredentials = true bayrağını ekler. Bu durumda, sunucunun yanıtında Access-Control-Allow-Credentials: true başlığının da bulunması gerekir. Ancak, tarayıcılar, Access-Control-Allow-Origin başlığı * olarak ayarlandığında ve Access-Control-Allow-Credentials: true de varsa, bu isteği reddederler.

Bu, bir güvenlik mekanizmasıdır. Eğer sunucu hem * hem de true değerlerine izin verseydi, kötü niyetli bir web sitesi, kullanıcının tarayıcısında oturum açmış olduğu bir API’ye kendi çerezleriyle istek gönderebilir ve hassas verilere erişebilirdi. Ancak, bazı sunucu tarafı kütüphaneleri veya proxy yapılandırmaları, bu kuralı atlayarak her ikisine de izin verecek şekilde yanlış yapılandırılabilir. Bu durumda, saldırganlar için kapılar ardına kadar açılır.

CSRF (Cross-Site Request Forgery) Senaryoları

Yanlış yapılandırılmış CORS, özellikle Access-Control-Allow-Origin: * ve kimlik bilgileriyle çalışan API’ler, CSRF saldırılarına zemin hazırlayabilir. Bir saldırgan, kullanıcıyı kendi kötü niyetli web sitesine (malicious.com) çekebilir. Bu sitede, kullanıcının oturum açmış olduğu API’ye (api.example.com) bir istek gönderen bir JavaScript kodu çalıştırabilirler. Eğer API, *‘dan gelen isteklere kimlik bilgileriyle erişime izin veriyorsa, saldırgan kullanıcının adına hassas işlemler yapabilir (örn. şifre değiştirme, para transferi). Tarayıcı, normalde bu isteği Same-Origin Policy nedeniyle engellerdi, ancak yanlış CORS yapılandırması bu engeli kaldırır.

Kötü Niyetli Bir Sayfadan API Erişimi Senaryosu:


// malicious.com adresindeki bir sayfa
fetch('https://api.example.com/user/profile', {
    method: 'GET',
    credentials: 'include' // Kullanıcının çerezlerini gönder
})
.then(response => response.json())
.then(data => {
    console.log('Kullanıcı verileri çalındı:', data);
    // Verileri kendi sunucumuza gönder
})
.catch(error => {
    console.error('Hata:', error);
});
    

Eğer api.example.com, Access-Control-Allow-Origin: * ve Access-Control-Allow-Credentials: true başlıklarını aynı anda döndürecek şekilde yanlış yapılandırılmışsa, bu kod kullanıcının hassas verilerine erişebilir.

Doğru CORS Yapılandırması Nasıl Olmalı?

API'nizi güvende tutmak için doğru CORS yapılandırması, her zaman mümkün olan en kısıtlı erişimi sağlamak üzerine kuruludur. İşte doğru yaklaşımlar:

Belirli Originlere İzin Verme

API'nize erişmesi gereken belirli kaynakları açıkça belirtin. Asla * kullanmayın, özellikle de kimlik bilgileriyle çalışıyorsanız. Birden fazla kaynağa izin vermeniz gerekiyorsa, sunucu tarafında gelen Origin başlığını kontrol edin ve yalnızca izin verilen kaynaklardan biriyle eşleşiyorsa o kaynağı Access-Control-Allow-Origin başlığına yazdırın.

Doğru CORS Yapılandırma Örneği (Node.js/Express):


const express = require('express');
const app = express();

const allowedOrigins = ['https://app.example.com', 'https://admin.example.com'];

app.use((req, res, next) => {
    const origin = req.headers.origin;
    if (allowedOrigins.includes(origin)) {
        res.setHeader('Access-Control-Allow-Origin', origin);
    }
    res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
    res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
    res.setHeader('Access-Control-Allow-Credentials', 'true'); // Eğer kimlik bilgileri kullanılıyorsa
    
    // Ön kontrol isteklerini yanıtla
    if (req.method === 'OPTIONS') {
        return res.sendStatus(200);
    }
    next();
});

// API rotalarınız burada
app.get('/data', (req, res) => {
    res.json({ message: 'Güvenli veri!' });
});

app.listen(3000, () => {
    console.log('API dinlemede...');
});
    

Access-Control-Allow-Credentials Kullanımı

Eğer API'niz çerezler veya HTTP kimlik doğrulama gibi kimlik bilgileriyle çalışıyorsa, Access-Control-Allow-Credentials: true başlığını ayarlamanız gerekir. Ancak unutmayın, bu başlık varsa, Access-Control-Allow-Origin başlığı asla * olamaz; belirli bir kaynak belirtilmelidir.

Diğer Önemli CORS Başlıkları

  • Access-Control-Allow-Methods: API'nizin hangi HTTP metotlarını kabul ettiğini açıkça belirtin (örn. GET, POST, PUT, DELETE).
  • Access-Control-Allow-Headers: İstemcilerin göndermesine izin verilen özel HTTP başlıklarını belirtin (örn. Content-Type, Authorization).
  • Access-Control-Max-Age: Ön kontrol (preflight) yanıtının ne kadar süreyle önbelleğe alınabileceğini belirtir. Bu, gereksiz OPTIONS isteklerini azaltarak performansı artırabilir.

CORS Hatalarını Ayıklama ve Çözme

CORS hataları, geliştiricilerin en çok karşılaştığı ve bazen de en kafa karıştırıcı hatalardan biridir. İşte bu hataları ayıklamak ve çözmek için bazı ipuçları:

Tarayıcı Geliştirici Araçları

Tarayıcınızın geliştirici araçları (Console ve Network sekmeleri), CORS hatalarını teşhis etmek için en iyi araçlardır. Konsolda genellikle hatanın nedenini açıklayan net mesajlar bulursunuz (örn. "has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present"). Network sekmesinde ise, isteğin başlıklarını (request headers) ve sunucudan gelen yanıt başlıklarını (response headers) inceleyerek sorunun kaynağını bulabilirsiniz.

Sunucu Logları ve Konfigürasyon Dosyaları

API sunucunuzun loglarını kontrol edin. Gelen isteklerin Origin başlıklarını ve sunucunuzun CORS başlıklarını nasıl ayarladığını gösteren bilgileri arayın. Web sunucunuzun (Nginx, Apache) veya uygulama çerçevesinizin (Express, Flask, Spring Boot) CORS konfigürasyonunu dikkatlice gözden geçirin.

curl ile Test Etme

curl komut satırı aracı, CORS yapılandırmanızı test etmek için çok kullanışlıdır. Belirli bir Origin başlığıyla bir istek göndererek sunucunuzun nasıl yanıt verdiğini görebilirsiniz:


curl -v -H "Origin: https://app.example.com" https://api.example.com/data
    

Bu komut, sunucudan gelen yanıt başlıklarını detaylı bir şekilde gösterir ve Access-Control-Allow-Origin gibi CORS başlıklarının doğru ayarlanıp ayarlanmadığını kontrol etmenizi sağlar.

API Güvenliği İçin Ek İpuçları

CORS, API güvenliğinin sadece bir yönüdür. Kapsamlı bir güvenlik stratejisi için ek önlemler almanız önemlidir:

Kimlik Doğrulama ve Yetkilendirme

Tüm API uç noktalarınıza uygun kimlik doğrulama (Authentication) ve yetkilendirme (Authorization) mekanizmaları uygulayın. JWT (JSON Web Tokens), OAuth 2.0 veya API anahtarları gibi standartları kullanın. Her isteğin kimliğini doğrulayın ve kullanıcının istenen eylemi gerçekleştirme yetkisine sahip olup olmadığını kontrol edin.

Giriş Doğrulama ve Çıkış Temizleme

API'nize gelen tüm girişleri (input) dikkatlice doğrulayın ve temizleyin. SQL enjeksiyonu, XSS ve komut enjeksiyonu gibi saldırıları önlemek için kullanıcı tarafından sağlanan verileri asla doğrudan kullanmayın. Yanıtlardan gönderdiğiniz verileri de temizleyerek bilgi sızıntılarını önleyin.

Rate Limiting (Hız Sınırlandırma)

API'nizin kötüye kullanımını veya DoS (Denial of Service) saldırılarını önlemek için hız sınırlaması uygulayın. Belirli bir zaman diliminde bir kullanıcının veya IP adresinin yapabileceği istek sayısını sınırlayın.

Güvenlik Başlıkları

API yanıtlarınıza ek güvenlik başlıkları ekleyin (örn. X-Content-Type-Options: nosniff, X-Frame-Options: DENY, Content-Security-Policy). Bu başlıklar, tarayıcıların belirli güvenlik özelliklerini etkinleştirmesine yardımcı olur.

Sonuç

CORS, modern web uygulamalarının vazgeçilmez bir güvenlik mekanizmasıdır, ancak yanlış yapılandırıldığında ciddi güvenlik açıklarına yol açabilir. Özellikle Access-Control-Allow-Origin: * kullanımı, kimlik bilgileriyle çalışan API'ler için büyük bir risktir ve API'nizi CSRF saldırılarına ve hassas veri sızıntılarına karşı savunmasız bırakabilir. Geliştiriciler olarak, CORS'un nasıl çalıştığını anlamak, belirli kaynaklara izin vermek ve güvenlik başlıklarını doğru bir şekilde uygulamak, API'lerimizi ve kullanıcılarımızın verilerini güvende tutmak için hayati öneme sahiptir. Unutmayın, güvenlikte "kolay yol", genellikle en tehlikeli yoldur. Her zaman en kısıtlı ve en güvenli yapılandırmayı tercih edin.

SSS (Sık Sorulan Sorular)

CORS hatası nedir?

CORS hatası, bir web sayfasının, yüklendiği kaynak dışındaki bir kaynaktan (farklı bir domain, protokol veya port) veri talep ettiğinde ve sunucunun bu isteğe izin veren CORS başlıklarını (özellikle Access-Control-Allow-Origin) göndermemesi durumunda tarayıcı tarafından ortaya çıkarılan bir güvenlik hatasıdır. Tarayıcı, Same-Origin Policy (SOP) nedeniyle bu isteği engeller.

Access-Control-Allow-Origin: * kullanmak her zaman kötü mü?

Hayır, her zaman kötü değildir. Eğer API'niz tamamen herkese açık (public) ise, hiçbir hassas veri içermiyorsa ve kimlik bilgileri (çerezler, HTTP kimlik doğrulama) ile çalışan istekleri kabul etmiyorsa, * kullanmak sorun teşkil etmeyebilir. Ancak, çoğu API bir şekilde hassas verilerle veya kimlik bilgileriyle çalıştığı için, bu genellikle kötü bir uygulamadır ve güvenlik riski taşır. Güvenlik açısından en iyi uygulama, her zaman belirli kaynaklara izin vermektir.

CORS'u tamamen devre dışı bırakmak güvenli midir?

Hayır, kesinlikle güvenli değildir. CORS, tarayıcı tabanlı saldırıları (özellikle CSRF) önlemek için tasarlanmış kritik bir güvenlik mekanizmasıdır. CORS'u devre dışı bırakmak, web uygulamanızı ve kullanıcılarınızı ciddi güvenlik risklerine maruz bırakır. Sunucu tarafında CORS başlıklarını doğru yapılandırmak, güvenli ve işlevsel bir çözüm sunar.

Birden fazla origin'e izin vermek mümkün müdür?

Evet, mümkündür. Ancak, Access-Control-Allow-Origin başlığı birden fazla değeri virgülle ayrılmış bir liste olarak kabul etmez. Sunucunuzun, gelen isteğin Origin başlığını kontrol etmesi ve bu başlığın izin verilen kaynaklar listenizde olup olmadığını doğrulaması gerekir. Eğer eşleşiyorsa, sunucu yanıt olarak o belirli Origin değerini Access-Control-Allow-Origin başlığına yazmalıdır.

CORS hatalarını nasıl tespit ederim?

CORS hatalarını tespit etmenin en yaygın yolu, web tarayıcınızın geliştirici araçlarını kullanmaktır. Konsol sekmesinde genellikle hatanın nedenini açıklayan açık mesajlar görürsünüz. Ağ (Network) sekmesinde ise, başarısız olan isteği seçerek istek ve yanıt başlıklarını inceleyebilir, sunucudan beklenen CORS başlıklarının gelip gelmediğini kontrol edebilirsiniz. Ayrıca, curl gibi komut satırı araçlarıyla belirli Origin başlıklarıyla test istekleri göndererek sunucunuzun CORS yanıtlarını doğrulayabilirsiniz.

Yorumlar
İçeriği beğendiniz mi? Bir tartışma başlatın veya görüşlerinizi paylaşın.
Yorum Yaz

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

Gönder

E-posta Bülteni
Yazılım Topluluğuna Katılın
En son güncellemeleri, yaratıcı ipuçlarını ve özel kaynakları doğrudan e-posta kutunuza alın. Tasarım ve inovasyonun geleceğini birlikte keşfedelim.
Mobil sürümden çık