Ana içeriğe geç

Aynı Kaynak Politikası ve Web Proxy: Teknik Güvenlik Analizi

Yazan
Smith
Smith
Okuma süresi
13 dk okuma
Yayınlanma tarihi
2 Mar 2026
Aynı Kaynak Politikası ve Web Proxy: Teknik Güvenlik Analizi

ProxyOrb'u geliştirirken her tasarım kararında temel bir paradoksla yüzleştik: bir web proxy, tarayıcıyı üçüncü taraf içeriğin aynı kaynaktan geldiğine inandırarak çalışır. Bu, tanımı gereği tarayıcının temel güvenlik modelini kandırmaktır. Oysa modern tarayıcılar tam olarak bu tür kaynak karışıklığına karşı on beş yıldır giderek daha sofistike savunmalar geliştiriyor.

Bu makale söz konusu gerilimi temel ilkelerden ele alıyor. Eğer web proxy'lerinin aynı kaynak politikasıyla gerçekte nasıl etkileşime girdiğini — kavramsal düzeyde değil, HTTP başlıkları, Chromium kaynak kodu ve üretim mühendisliği dengelerinin düzeyinde — anlamak isteyen bir güvenlik araştırmacısı, sızma testi uzmanı ya da tarayıcı güvenlik mühendisiyseniz bu yazı tam size göre.

SOP temelini, URL yeniden yazımını, CORS'u, CORB/CORP'u, COEP/COOP'u, Service Worker'ları, iframe'leri ve hem proxy operatörleri hem de kullanıcılar için güvenlik sonuçlarını inceleyeceğiz.


1. Aynı Kaynak Politikasının Temelleri

Aynı kaynak politikası (SOP), üç bileşenli bir tanımla ifade edilir: şema + host + port. İki URL'nin aynı kaynak sayılabilmesi için bu üç bileşenin birebir eşleşmesi gerekir. https://example.com:443 ile http://example.com:80, aynı sunucuya işaret etmelerine rağmen farklı kaynak olarak değerlendirilir.

Sık yanlış anlaşılan nokta, SOP'un gerçekte neyi önlediği, neye izin verdiğidir. SOP şunları engellemez:

  • Kaynaklar arası görsel yükleme (<img src>)
  • Kaynaklar arası betik yükleme (<script src>)
  • Kaynaklar arası stil sayfası yükleme (<link rel="stylesheet">)
  • Kaynaklar arası iframe gömme (gömülü belgenin içeriği yalıtılmış olsa da)
  • Kaynaklar arası form gönderimi (<form action>)

SOP'un önlediği şey, fetch() veya XMLHttpRequest aracılığıyla yapılan çapraz kaynak isteklerinin yanıtının okunmasıdır. İstek gönderilir — ağ gidiş-dönüşü gerçekleşir — ancak yanıt gövdesi ve başlıkları, farklı bir kaynakta çalışan JavaScript'ten gizlenir.

Bu ayrım, web proxy güvenliği açısından son derece önemlidir. Proxy'nin tüm görevi, iki kaynağı (proxy sunucusu ve hedef sunucu) tek bir kaynakta birleştirerek çapraz kaynak sınırını ortadan kaldırmaktır. Tüm kaynaklar https://proxyorb.com'dan geliyormuş gibi göründüğünde, tarayıcının SOP tabanlı yanıt okuma kısıtlamaları artık devreye girmez.

Web proxy'lerinin yararlandığı "meşru alan" URL yeniden yazımıdır: https://example.com/api/data yerine her istek https://proxyorb.com/api/data?__pot=aHR0cHM6Ly9leGFtcGxlLmNvbQ== biçimini alır. Tarayıcının perspektifinden bu aynı kaynak isteğidir. SOP atlatılmamıştır — tüm içeriğin görünür kaynağı değiştirilerek SOP geçersiz kılınmıştır.


2. ProxyOrb'un URL Yeniden Yazım Mimarisi

Güvenlik sonuçlarını anlayabilmek için kodlama mekanizmasını kavramak gerekir. ProxyOrb, hedef kaynağın Base64 ile kodlanmış halini içeren __pot (proxy origin token) adlı bir URL parametresi kullanır.

__pot Parametresi

__pot parametresi her zaman tam URL'yi değil, hedefin kaynağını (şema + host, yol olmadan) kodlar. Bu, https://example.com/some/deep/path?foo=bar ile https://example.com/other/page adreslerinin aynı __pot değerini ürettiği anlamına gelir: aHR0cHM6Ly9leGFtcGxlLmNvbQ== (https://example.com'un Base64 kodlaması). Gerçek yol ve sorgu dizisi, proxy URL'sinin kendi yolu ve sorgu dizisinde olduğu gibi korunur.

Kullanıcı https://proxyorb.com/?__pot=aHR0cHM6Ly9leGFtcGxlLmNvbQ== adresine gittiğinde, ağ geçidi bunu çözümleyerek orijinal URL'yi yeniden oluşturur:

-- Gateway pseudocode: decoding the proxy request

function resolve_original_url(proxy_url):
    pot_value = parse_query_param(proxy_url, "__pot")
    if not pot_value:
        return error("Missing origin token")

    original_origin = base64_decode(pot_value)
    -- e.g. "https://example.com"

    validate_not_private_ip(original_origin)  -- SSRF protection

    -- Replace the proxy host with the target host, keep path/query intact
    original_url = replace_origin(proxy_url, original_origin)
    return original_url

Ağ geçidi ardından isteği gerçek hedef sunucuya iletir ve Origin başlığını yeniden yazar; böylece üst akış sunucusu proxy etki alanı yerine kendi etki alanını görür:

-- Set outbound headers toward the target server

request.headers["Host"]   = target_host
request.headers["Origin"] = target_origin   -- e.g. "https://example.com"
-- Remove all internal proxy headers before forwarding

Service Worker Aracılığıyla İstemci Tarafı URL Yeniden Yazımı

Ağ geçidi sunucu tarafını ele alır. İstemci tarafı — HTML, JavaScript ve CSS yanıtlarındaki URL'leri yeniden yazarak tüm alt isteklerin proxy üzerinden geçmeye devam etmesini sağlamak — bir Service Worker tarafından yönetilir.

Temel dönüşüm, sayfa içeriğinde karşılaşılan herhangi bir URL'yi proxy biçimine çevirir:

-- Service Worker pseudocode: toProxyURL()

function toProxyURL(originalUrl, currentPageUrl):
    if isSameOrigin(originalUrl, currentPageUrl):
        return originalUrl   -- already proxy-origin, no rewrite needed

    -- Extract path/query/hash from the original URL
    -- Build a new URL rooted at the proxy origin
    proxyPath   = extractPathAndQuery(originalUrl)
    potValue    = base64encode(extractOrigin(originalUrl))
    proxyUrl    = proxy_origin + proxyPath + "?__pot=" + potValue

    return proxyUrl

Örneğin proxy üzerinden erişilen bir sayfada referans verilen https://cdn.example.com/bundle.js, https://proxyorb.com/bundle.js?__pot=aHR0cHM6Ly9jZG4uZXhhbXBsZS5jb20= biçimini alır.

Bu yeniden yazım kapsamlıdır: fetch(), XMLHttpRequest, <script src>, <img src>, WebSocket bağlantıları ve <link> etiketlerini kapsar. Sayfadaki tüm URL'ler proxy kaynağına işaret ettiğinde, tarayıcı hiçbir zaman çapraz kaynak isteği göndermez — her istek, yapısal olarak aynı kaynaktan kabul edilir.

Tam Gezinti Olmadan __pot'un Geri Kazanılması

Proxylenen bir sayfanın içinden kaynaklanıp __pot parametresi taşımayan isteklerde ince bir uç durum ortaya çıkar — örneğin Service Worker URL'yi yeniden yazmadan önce tetiklenen göreli bir fetch('/api/data') çağrısı ya da URL yeniden yazıcısını atlayan dinamik olarak enjekte edilmiş bir betikten gelen istek.

Service Worker, eksik token'ı basamaklı bir arama yoluyla çözümler:

-- Service Worker pseudocode: recovering the origin token

function resolveMissingPot(fetchEvent):
    candidates = [
        getUrlOfControlledTab(fetchEvent.clientId),   -- most reliable
        inferUrlFromFetchEvent(fetchEvent),             -- from clientId / resultingClientId
        fetchEvent.request.referrer,                    -- referrer header
    ]

    for url in candidates:
        pot = extractQueryParam(url, "__pot")
        if pot: return pot

    return null   -- cannot recover; let the gateway handle or reject

Ağ geçidinin paralel bir geri kazanım yolu daha vardır: __pot içermeyen ancak __pot barındıran aynı kaynaklı bir URL'ye işaret eden Referer başlığı taşıyan bir istek geldiğinde, ağ geçidi token'ı referrerdan çıkararak mevcut isteğe ekler. Bu, sayfanın kendi JavaScript'inin ağ geçidine ulaşmadan önce token'ı kırptığı gezinti senaryolarını ele alır.


3. CORS: Açık Çapraz Kaynak İzin Sistemi

CORS (Cross-Origin Resource Sharing), sunucuların belirli yanıt başlıkları göndererek çapraz kaynak erişimine onay vermesine izin verecek şekilde tasarlanmıştır. Proxy açısından CORS, iki farklı sorun yaratır.

Sorun 1: CORS Preflight İstek Durdurma

Bir sayfada çalışan JavaScript, fetch() ile basit olmayan başlıklar içeren (örn. Authorization, Content-Type: application/json) bir istek gönderdiğinde, tarayıcı önce bir OPTIONS preflight isteği gönderir. Hedef sunucunun preflight yanıtı izin verici CORS başlıkları içermiyorsa gerçek istek engellenir.

ProxyOrb mimarisinde Service Worker, tüm OPTIONS isteklerini ağ geçidine bile ulaşmadan önce yakalar ve gerçek isteğin önünü açan sentetik bir yanıt döner:

-- Service Worker pseudocode: synthetic CORS preflight

function handlePreflight(request):
    origin = request.headers["Origin"] or "*"

    return Response(status=204, headers={
        "Access-Control-Allow-Origin":      origin,
        "Access-Control-Allow-Methods":     "GET, POST, PUT, DELETE, OPTIONS, PATCH, HEAD",
        "Access-Control-Allow-Headers":     "*",
        "Access-Control-Allow-Credentials": "true",
        "Access-Control-Max-Age":           "86400",
        "Vary":                             "Origin",
    })

Ağ geçidi düzeyinde, proxylenen her yanıt eşdeğer CORS başlıklarını alır:

-- Gateway pseudocode: set CORS on outbound response

response.headers["Access-Control-Allow-Origin"]      = original_origin
response.headers["Access-Control-Allow-Headers"]     = "*"
response.headers["Access-Control-Allow-Credentials"] = "true"

Sorun 2: Kimlik Bilgili İstekler

Access-Control-Allow-Credentials: true ile joker karakter olmayan Access-Control-Allow-Origin kombinasyonu önemlidir. CORS, kimlik bilgileri dahil edildiğinde * yerine açık bir kaynak değeri gerektirir. Service Worker tüm giden istekleri credentials: 'include' ile gönderdiğinden, ağ geçidi joker karakter yerine tam istekte bulunan kaynağı yansıtmak zorundadır.

Bu, proxyorb.com altında depolanan tüm çerezlerin — kullanıcının proxy üzerinden ziyaret ettiği her hedef siteden birikenlerin — her proxylenen istekte gönderildiği anlamına gelir. Bu kasıtlıdır (oturum açılmış siteler için oturum durumunu korur), ancak Bölüm 8'de ele aldığımız önemli bir web proxy güvenliği konusudur.

CORS Başlığı Sil-ve-Değiştir Kalıbı

Proxylenen bir yanıt, hedef sunucudan gelen ve tarayıcının perspektifinden yanlış olan CORS başlıkları içerebilir (proxy kaynağını değil, hedef kaynağı referans alırlar). Service Worker bunları siler ve yenileriyle değiştirir:

-- Service Worker pseudocode: sanitize response headers

function sanitizeResponseHeaders(response):
    headers = copy(response.headers)

    -- Remove target-site directives that would confuse the browser
    headers.delete("Content-Security-Policy")
    headers.delete("Content-Security-Policy-Report-Only")
    headers.delete("X-Frame-Options")
    headers.delete("X-Content-Type-Options")

    -- Replace with proxy-origin-correct CORS headers
    headers.set("Access-Control-Allow-Origin",      proxy_origin)
    headers.set("Access-Control-Allow-Credentials", "true")
    headers.set("Access-Control-Allow-Headers",     "*")
    headers.set("Vary", "Origin")

    return headers

4. CORB ve CORP: Chromium'un Daha Sert Savunmaları

CORS, sunuculardan açık onay üzerine çalışır. Chromium, CORS yapılandırmasından bağımsız olarak varsayılan aktif olan iki mekanizma daha ekledi.

Cross-Origin Read Blocking (CORB)

CORB, Spectre azaltımlarının bir parçası olarak Chrome 67 (2018) ile tanıtıldı. Temel fikir şu: bir çapraz kaynak yanıtının gövdesi JavaScript tarafından hiç okunmasa bile, tarayıcı işleme süreci tarafından getirilip çözümlenmiş olması, o sürecin adres alanında var olduğu anlamına gelir. Spectre sınıfı saldırılar daha sonra bunu yan kanallar aracılığıyla çıkarabilir.

CORB, belirli çapraz kaynak yanıtlarının oluşturma sürecine hiç girmesini engeller. Özellikle, bir <script> veya <img> etiketi çapraz kaynak bir yanıt getirdiğinde ve bu yanıtın Content-Typetext/html, text/xml veya application/json olduğunda, Chromium gövdeyi inceler (CORB spesifikasyonunda tanımlanan MIME türü algılayıcısını kullanarak) ve tür eşleşirse yanıtı oluşturucu görmeden önce boş bırakır.

Bir web proxy için, istekler gerçekten çapraz kaynak olsaydı CORB yıkıcı olurdu. application/json döndüren bir API uç noktası, bir <script> etiketinden getirildiğinde sessizce boş dönerdi. Ancak ProxyOrb tüm URL'leri aynı kaynak olacak şekilde yeniden yazdığından, CORB'un çapraz kaynak koşulu hiçbir zaman tetiklenmez — tarayıcı çapraz kaynak JSON yanıtı görmez, çünkü onun perspektifinden tüm yanıtlar proxyorb.com'dan gelir.

CORB'un önem taşıdığı tek durum, Service Worker tam olarak kaydedilip istekleri yakalamaya başlamadan önceki geçiş döneminde ortaya çıkar. Bu pencerede URL yeniden yazımından kaçan herhangi bir istek CORB tarafından engellenebilir. Bu yarış koşulu, ProxyOrb'un aynı zamanda herhangi bir sayfa JavaScript'inden önce eş zamanlı olarak XMLHttpRequest, fetch ve DOM nitelik ayarlayıcılarını yamayan bir ana iş parçacığı kesme katmanı korumasını da neden sürdürdüğünü açıklar — Service Worker başlatılırken bir yedek sağlamak için.

CORB'un kısmen Opaque Response Blocking (ORB) tarafından yerini aldığını belirtmek gerekir; Chromium bu geçişi uygulamaktadır. ORB, CORB kurallarını yanlış pozitifleri azaltacak şekilde iyileştirirken Spectre korumalarını sürdürür. Proxy uyumluluğu açısından sonuçlar benzerdir.

Cross-Origin Resource Policy (CORP)

Fetch spesifikasyonunda tanımlanan CORP, sunucuların kaynaklarının yalnızca aynı kaynaklı veya aynı siteli bağlamlarca yüklenmesi gerektiğini beyan etmesine olanak tanır:

Cross-Origin-Resource-Policy: same-origin

Chromium bu başlıkla çapraz kaynak alt-kaynak isteğiyle karşılaştığında, yanıtı tamamen engeller. Bu, CORB'dan daha agresiftir — içerik türünden bağımsız olarak uygulanır ve MIME algılamayla atlatılamaz.

Yine, ProxyOrb'un URL yeniden yazımı tüm isteklerin tarayıcı perspektifinden aynı kaynaklı olmasını sağladığından, hedef sunuculardan gelen CORP başlıkları engellemeyi tetiklemez. Ağ geçidi ayrıca bu başlıkları yanıtlardan savunma amaçlı olarak kaldırır; URL yeniden yazımı olmadan sızan isteklerdeki uç durumları ele alır.

CORP ile ilgili daha derin sorun aslında proxy mimarisinin uyumluluğa yardımcı olduğu bir durumdur: https://api.example.com ve https://www.example.com ikisi de proxyleniyor olsaydı, her ikisi de aynı proxy kaynağıyla eşleşirdi; böylece birinden diğerine yapılan bir fetch artık gerçek anlamda aynı kaynaktan kabul edilir — aralarında CORP kısıtlamaları artık geçerli olmaz.


5. COEP ve COOP: Çapraz Kaynak İzolasyonu

Chrome 92'den (2021) itibaren SharedArrayBuffer'a erişim — ve bununla birlikte belirli performans API'leri için kullanılan yüksek çözünürlüklü zamanlayıcılar — çapraz kaynak izolasyonu seçeneğine geçen sayfalarla kısıtlandı. Bu tercih, uyumlu çalışan iki yanıt başlığı gerektirir.

Cross-Origin-Embedder-Policy (COEP)

Cross-Origin-Embedder-Policy: require-corp

Bir sayfa bu başlığı gönderdiğinde, tarayıcı o sayfanın yüklediği her alt kaynağın şunlardan birini yapmasını zorunlu kılar:

  1. Aynı kaynaktan gelmesi, VEYA
  2. Açıkça Cross-Origin-Resource-Policy: cross-origin göndermesi, VEYA
  3. Kimlik bilgili fetch için izin verici CORS yanıtı içermesi

Web proxy'ler için sorun şudur: bir hedef site ana belgesinde COEP: require-corp gönderdiğinde ve bu belge başlık korunarak proxy aracılığıyla sunulduğunda, tarayıcı artık o sayfa tarafından yüklenen her alt kaynağın da onay vermesini talep eder. Bunu yapmayan herhangi bir kaynak — ve çoğu yapmaz — ağ hatasına yol açar.

Cross-Origin-Opener-Policy (COOP)

Cross-Origin-Opener-Policy: same-origin

COOP, bir sayfanın çapraz kaynaklı sayfalarla tarayıcı bağlam grubunu paylaşıp paylaşamayacağını denetler. same-origin olarak ayarlandığında, çapraz kaynak bir gezinti yeni bir tarayıcı bağlam grubu açar; sayfa ile çapraz kaynaklı açıcılar arasındaki window.opener referansları ve postMessage kanalları kesilir.

Bir proxy için COOP, COEP kadar hemen yıkıcı değildir; ancak yine de çapraz kaynaklı postMessage akışlarına dayanan siteleri (en yaygın örnek OAuth açılır penceresi akışları) bozar.

Proxy Operatörünün İkilemi

Bu, ProxyOrb'da karşılaştığımız en zor dengedir:

Seçenek A: Yanıtlardan COEP ve COOP'u kaldırın.

  • Artısı: Alt-kaynak yüklemesi normal çalışır; proxylenen sayfa bu kısıtlamaları uygulamaz.
  • Eksisi: Hedef sitenin kasıtlı olarak koyduğu güvenlik başlıklarını kaldırıyoruz. Site, hassas verileri Spectre sınıfı saldırılardan korumak için çapraz kaynak izolasyonu kullanıyorsa, bu başlıkları kaldırmak riski yeniden açığa çıkarır.

Seçenek B: COEP ve COOP'u koruyun.

  • Artısı: Hedef sitenin güvenlik niyeti korunur.
  • Eksisi: Açıkça CORP: cross-origin ayarlamayan herhangi bir alt-kaynak yüklenemez; çoğu karmaşık web uygulaması bozulur.

ProxyOrb'un mevcut stratejisi Seçenek A'dır: ağ geçidi yanıtlardan Cross-Origin-Embedder-Policy ve Cross-Origin-Opener-Policy'yi kaldırır. Bu, site uyumluluğunu en üst düzeye çıkarır. Güvenlik dengesi bilinçli olarak kurulmuştur: bir web proxy kullanan kullanıcılar, içeriği hedeflenen dağıtım bağlamından farklı bir ortamda çalıştırdıklarını kabul etmiş olurlar.

Her yeni tarayıcı güvenlik mekanizması bir kalıbı izler: önce isteğe bağlı olarak tanıtılır (siteler isterlerse başlığı gönderebilir), ardından yeni API'ler için kademeli olarak zorunlu hale getirilir ve nihayetinde zorunlu uygulama için değerlendirilir. COEP bu yolu izledi: Chrome 83'te isteğe bağlı, Chrome 91'de SharedArrayBuffer için zorunlu. Üçüncü taraf içeriği koordinasyonsuz gömmeye çalışan siteler içeriklerinin bozulduğunu gördü. Web proxy'leri bu sorunu daha da artırır, çünkü tanımları gereği üçüncü taraf içeriğe aracılık ederler.

Tarayıcı güvenlik topluluğu bu sorunun farkındadır. Ortaya çıkan Document-Isolation-Policy önerisi, süreç yalıtımını çapraz kaynak yalıtımı gereksinimlerinden ayırmayı amaçlar; bu, tüm alt kaynakların onay vermesini gerektirmeksizin Spectre azaltımları elde etmeyi mümkün kılabilir. Bu özellik yayına girdiğinde, izolasyon başlıklarıyla proxy uyumluluğu iyileşebilir.


6. Service Worker: Tarayıcı Tarafı Güven Katmanı

Service Worker yalnızca bir optimizasyon değildir — ProxyOrb'un güvenlik modelinin mimarı açıdan vazgeçilmez bir bileşenidir. İşte nedeni.

Kayıt Kapsamı Kaynağa Bağlıdır

Bir Service Worker, her zaman kayıt yapan sayfanın kaynağı içinde kalan bir scope ile kaydedilir. ProxyOrb Service Worker'ını kaydettiğinde kapsam https://proxyorb.com/'dur; yani bu kaynak altındaki herhangi bir sayfanın her fetch isteğini yakalar.

URL'leri aynı kaynağa yeniden yazmanın temel olarak neden işe yaradığı budur: SW bir istemciyi kontrol etmeye başladığında, sayfadaki JavaScript ne tür bir URL fetch etmeye çalışırsa çalışsın, her ağ isteği önce Service Worker'dan geçer.

// Service Worker entry point
self.addEventListener('fetch', (event) => {
  event.respondWith(handleProxyRequest(event))
})

Yakalama Boru Hattı

Service Worker bir isteği yakaladığında, birkaç karar aşamasından geçirir:

-- Service Worker pseudocode: request interception pipeline

function handleProxyRequest(fetchEvent):
    request = fetchEvent.request

    -- Stage 1: Synthetic CORS preflight (never hits the network)
    if request.method == "OPTIONS":
        return syntheticCORSResponse(request)

    -- Stage 2: Pass through requests that shouldn't be proxied
    if shouldBypass(request.url):
        return originalFetch(request)

    -- Stage 3: Ensure __pot is present; recover from context if missing
    enrichedRequest = attachOriginToken(request, fetchEvent)

    -- Stage 4: Forward to gateway
    response = originalFetch(enrichedRequest)

    -- Stage 5: Strip and replace security headers in the response
    return sanitizeAndReturn(response)

Şeffaf Başlık İletimi

İnce bir zorluk daha var: tarayıcı, JavaScript'in Fetch API aracılığıyla belirli "yasaklı" istek başlıklarını (Host, Origin, Referer vb.) ayarlamasını kısıtlar. Service Worker bu sorunu, kısıtlı başlıkları tek bir özel geçiş başlığında kodlayarak aşar; ağ geçidi ardından bunları hedef sunucuya iletmeden önce çözer ve uygular:

-- Pseudocode: encode browser-restricted headers for the gateway

function addPassthroughHeaders(request, outboundHeaders):
    restricted = {}
    for name, value in request.headers:
        if name not in COMMON_ALLOWED_HEADERS:
            restricted[name] = value

    if restricted is not empty:
        outboundHeaders["X-Proxy-Passthrough"] = json_encode(restricted)

-- Gateway side: decode and apply before forwarding upstream
function applyPassthroughHeaders(incomingHeaders):
    encoded = incomingHeaders["X-Proxy-Passthrough"]
    if encoded:
        for name, value in json_decode(encoded):
            request.headers[name] = value
        request.headers.delete("X-Proxy-Passthrough")

SW'nin Güvenilir Aracı Olarak Güvenlik Sonuçları

Güvenlik perspektifinden Service Worker ayrıcalıklı bir konumdadır: kapsamındaki herhangi bir sayfadan yapılan herhangi bir isteği inceleyebilir, değiştirebilir ve sahte olarak oluşturabilir. Meşru proxy kullanımı için tam olarak amaçlanan budur. Kötü niyetli bir proxy için ise bu son derece güçlü bir saldırı yüzeyi olurdu.

Bu yüzden Service Worker betiğinin güvenilirliği kritik önem taşır. ProxyOrb, interceptor betiğini kendi kaynağından HTTPS üzerinden sıkı önbellek kontrolleriyle sunar. Bir saldırgan değiştirilmiş bir Service Worker enjekte edebilseydi, etkilenen kullanıcıların tüm trafiğini yakalayabilirdi — yalnızca proxy trafiğini değil, bu kaynak altındaki sayfalardan yapılan her isteği.


7. iframe'ler: Frame-Ancestors Sorunu

iframe'ler, normal alt kaynaklardan farklı bir zorluk oluşturur; çünkü kendi gezintisi, kendi SOP sınırı ve kendi gömme kısıtlamaları olan iç içe bir tarayıcı bağlamını içerirler.

X-Frame-Options ve frame-ancestors

Sayfaların iframe'lere gömülmesini engelleyen iki mekanizma vardır:

Eski yöntem: X-Frame-Options: DENY veya X-Frame-Options: SAMEORIGIN

Modern yöntem: Content-Security-Policy: frame-ancestors 'none' veya frame-ancestors 'self'

Ağ geçidi bu başlıklardan herhangi birini gönderen bir hedef sayfayı proxylediğinde, sayfa proxy kaynağının altındaki bir iframe'e gömülemez. X-Frame-Options: SAMEORIGIN hedef kaynağa (example.com) atıfta bulunduğundan ve proxy sayfayı proxyorb.com'dan sunduğundan, tarayıcının aynı kaynak denetimi başarısız olur.

Proxy, bu başlıkları proxylenen yanıtlardan kaldırmalı ve CSP'yi izin verici bir sürümle değiştirmelidir:

-- Gateway pseudocode: override embedding-restrictive headers

response.headers.delete("X-Frame-Options")
response.headers.delete("Content-Security-Policy")
response.headers.delete("Content-Security-Policy-Report-Only")

-- Set a permissive replacement that allows the proxy to embed content
response.headers["Content-Security-Policy"] =
    "upgrade-insecure-requests; frame-ancestors 'self'; " +
    "default-src * data: blob: about: ws: wss: 'unsafe-inline' 'unsafe-eval'"

iframe Yakalama ve Betik Enjeksiyonu

Gömülü iframe'ler ikinci bir sorun daha yaratır: içerikleri proxy'den yüklenir, ancak iframe'in tarayıcı bağlamı otomatik olarak aktif Service Worker veya ana iş parçacığı interceptor'ına sahip değildir. Proxylenen sayfa <iframe src="https://widget.example.com/..."> oluşturursa, bu iframe URL'si de proxy biçimine yeniden yazılmalı ve proxy'nin interceptor betikleri iframe'in belgesine enjekte edilmelidir.

iframe interceptor iki düzeyde çalışır:

Düzey 1 — Prototip yaması (programlı iframe oluşturmaları yakalar):

-- Pseudocode: intercept iframe src assignment

override HTMLIFrameElement.prototype.src setter:
    if value is not already a proxy URL:
        value = toProxyURL(value)   -- rewrite to proxy format
    call original setter(value)
    scheduleProxyInjection(this)    -- inject interceptor into iframe document

Düzey 2 — MutationObserver yedek (DOM'a eklenen iframe'leri yakalar):

-- Pseudocode: observe DOM for dynamically added iframes

observer = new MutationObserver(mutations):
    for mutation in mutations:
        for node in mutation.addedNodes:
            if node is an <iframe>:
                rewriteSrcIfNeeded(node)
                injectProxyScript(node)

observer.observe(document, { childList: true, subtree: true })

sandbox Niteliği Sorunu

HTML sandbox niteliği, bir iframe'in yapabileceklerini kısıtlar: sandbox="allow-scripts allow-same-origin", betik yürütmeyi, form gönderimini, çapraz kaynak erişimini vb. denetler. Proxy enjeksiyonunun çalışabilmesi için iframe'in betik çalıştırabilmesi ve üst proxy bağlamına erişebilmesi gerekir.

allow-same-origin token'ı özellikle nüanslıdır: allow-scripts ile birlikte mevcut olduğunda sandbox'ın kaynak yalıtımını ortadan kaldırır — iframe, gömme sayfanın kaynağıyla çalışır. Mevcut olmadığında iframe benzersiz opak bir kaynak alır; bu, proxy betik enjeksiyonunu tamamen bozar.

ProxyOrb'un sandbox nitelikleri için mevcut yaklaşımı, proxy betiği enjekte etmeden önce sandbox niteliğini tamamen kaldırmaktır:

-- Pseudocode: handle sandbox attribute before proxy injection

function handleSandboxedIframe(iframe):
    if iframe.hasAttribute("sandbox"):
        -- Remove so the proxy can inject scripts and access contentWindow
        iframe.removeAttribute("sandbox")
    injectProxyScript(iframe)

Bu önemli bir güvenlik dengesidir: sandbox, gömülü içeriğin yeteneklerini kısıtlamak amacıyla orijinal site tarafından kasıtlı olarak yerleştirilmişti. Kaldırmak, o içeriğin yapabileceklerini genişletir. Son kullanıcılara görünmez olan ama proxy oturumunun güvenlik duruşunu somut olarak etkileyen bir karardır.


8. Proxy Operatörleri için Güvenlik Sonuçları

Saldırı Yüzeyi Panoraması

Kullanıcılar ProxyOrb üzerinden gezinirken çeşitli kategorilerdeki hassas veriler proxy'nin kaynağından akar:

Oturum Çerezleri: Tüm hedef siteler proxyorb.com üzerinden proxylendiğinden, çerezler bu kaynak altında depolanır. Kullanıcının bankası, e-postası ve sosyal medyasıyla olan kimlik doğrulanmış oturumlarının tamamı tek bir etki alanı altındaki çerezlerdir. Service Worker'ın credentials: 'include' ayarı, bu çerezlerin her proxylenen isteğe eşlik ettiği anlamına gelir.

Referer Başlıkları: Üst akış sunucularına gönderilen Referer başlığı, kullanıcının hangi sayfayı görüntülediğini ortaya koyar. Proxy, hedef sunucuya iletmeden önce referer değerlerinden kendi etki alanını dikkatlice siler. Bir istek https://proxyorb.com/some/path?__pot=... adresinden kaynaklanıyorsa, giden Referer başlığı orijinal hedef URL (https://example.com/some/path) olarak yeniden oluşturulur — proxy etki alanı hiçbir zaman üst akış sunucularına sızdırılmaz.

-- Pseudocode: normalize referer before forwarding upstream

function sanitizeReferer(referer):
    if referer is a proxy URL:
        return reconstruct_original_url(referer)   -- e.g. "https://example.com/path"
    if referer's origin equals proxy_origin:
        return ""   -- suppress: don't leak proxy domain to upstream
    return referer

JavaScript Yürütme Bağlamı: Proxy üzerinden sunulan her JavaScript dosyası değiştirilerek (URL'ler yeniden yazılarak) proxy'nin kaynağında yürütülür. evil.example.com'dan ProxyOrb aracılığıyla proxylenen kötü niyetli bir betik, proxyorb.com kaynağında çalışır ve kullanıcının proxy üzerinden eriştiği her diğer hedef siteden gelen yerel depolama, çerezler ve IndexedDB verilerinin tamamına tam erişime sahip olur.

Kötü Niyetli Proxy Tehdit Modeli

Eğitim amaçlı olarak, kötü niyetli bir proxy'nin yapabileceği ama ProxyOrb'un kasıtlı olarak yapmadığı şeyleri açıkça belirtmek faydalıdır:

  1. Kimlik Bilgisi Toplama: Kötü niyetli bir proxy, ağ geçidinden geçerken şifreleri ve form verilerini içeren her istek gövdesini kaydedebilir.

  2. Oturum Ele Geçirme: Tüm hedef site çerezleri proxy etki alanı altında depolandığından, kötü niyetli bir proxy operatörü bu çerezlere ağ geçidi aracılığıyla sunucu tarafında erişebilir.

  3. İçerik Enjeksiyonu: Proxy, sayfa içeriğini zorunlu olarak değiştirir (Service Worker'ı enjekte etmek ve URL'leri yeniden yazmak için). Kötü niyetli bir proxy, kullanıcıya görünmez keylogger'lar, kripto madencileri, reklam sahtekarlığı betikleri gibi keyfi JavaScript enjekte edebilir.

  4. SSL Soyma: Proxy, ağ geçidi-kullanıcı bacağı için HTTPS bağlantılarını HTTP'ye düşürürse, tüm trafik düz metin halinde iletilir.

ProxyOrb uçtan uca HTTPS üzerinden çalışır ve istek gövdelerini kaydetmez. Herhangi bir web proxy'nin operatörü bu yeteneklere sahiptir; bu nedenle güvenilir bir proxy operatörü seçmek, güvenilir bir VPN sağlayıcısı seçmek kadar önem taşır.

Karışık İçerik

Modern tarayıcılar karışık içerik engellemesini zorunlu kılar: HTTPS sayfası HTTP alt kaynaklarını yükleyemez. ProxyOrb bunu, hedef URL HTTP kullansa bile ağ geçidinden giden tüm bağlantılarda HTTPS'yi zorunlu kılarak ele alır. CSP geçersiz kılma, tarayıcıya herhangi bir HTTP alt kaynak URL'sini yüklemeden önce HTTPS'ye yükseltmesini bildiren upgrade-insecure-requests ifadesini içerir.

Bu genel olarak istenen bir şeydir; ancak kasıtlı olarak HTTP üzerinden kaynak sunan siteleri (eski CDN'ler, localhost kaynakları vb.) bozabilir.


9. Süregelen Silahlanma Yarışı: Sonuç

ProxyOrb'u oluşturmaya başladığımızda, temel uyumluluk zorlukları CORS ve X-Frame-Options'dı. O günden bu yana Chromium, CORB, CORP, COEP ve COOP'u kullanıma sundu; Document-Isolation-Policy üzerinde çalışmaya devam ediyor. Gidişatın yönü açık: tarayıcılar çapraz kaynak sınırlarını uygulamada giderek daha agresif hale geliyor ve her yeni mekanizma proxy altyapısının adapte olmasını gerektiriyor.

Önümüzdeki en önemli zorluk, muhtemelen COEP'in büyük web uygulamalarına tam olarak yayılmasıdır. Performans için SharedArrayBuffer kullanan siteler (video editörler, IDE'ler, işbirliği araçları) giderek artan oranda COEP: require-corp ayarlıyor. ProxyOrb uyumluluğu korumak için bu başlığı kaldırdıkça, COEP'in etkinleştirdiği yüksek performans özelliklerine ihtiyaç duyan kullanıcılar bu özelliklerin proxy bağlamında bozulduğunu görecek.

Güvenlik araştırmacıları için proxy mimarisi önemli bir şeyi ortaya koyar: aynı kaynak politikası bir güvenlik duvarı değildir. URL yapısına dayanan bir güven modelidir. Web proxy'leri şu gerçeği sömürür: SOP, "bu iki kaynak meşru olarak aynı kaynaktan" ile "bu iki kaynak aynı kaynaktan görünmesi için URL yeniden yazımına tabi tutulmuş" arasında herhangi bir içsel ayrım yapmaz. SOP'un üzerindeki tüm tarayıcı güvenlik yığını — CORS, CORB, CORP, COEP, COOP — URL tabanlı kaynak kimliğinden daha sağlam savunmalar ekleme girişimi olarak görülebilir.

Bunu anlamak, proxy hizmetlerini denetleyen, tarayıcı güvenlik politikaları tasarlayan ya da proxy'ler aracılığıyla erişilebilecek uygulamaların gerçek dünya güvenlik duruşunu değerlendiren herkes için zorunludur.


Sıkça Sorulan Sorular

Web proxy, aynı kaynak politikasını atlatır mı?

Tam olarak değil. Bir web proxy, URL yeniden yazımıyla çalışır: tüm çapraz kaynak URL'lerini aynı kaynak URL'lerine dönüştürerek SOP'un çapraz kaynak kısıtlamalarını atlatmak yerine geçersiz kılar. Tarayıcının perspektifinden tüm içerik proxy'nin kendi kaynağından geliyor gibi görünür; dolayısıyla hiçbir çapraz kaynak sınırı aşılmaz. Bu, bir atlatmadan mimarısal olarak farklıdır — SOP hâlâ kurallarını uygulamaktadır; proxy yalnızca bu kuralların hiçbir zaman tetiklenmeyeceği şekilde içeriği mühendislik açısından düzenlemektedir.

CORS web proxy sunucularını nasıl etkiler?

CORS, proxy sunucularını iki düzeyde etkiler. Birincisi, proxy OPTIONS preflight isteklerini yakalamalı ve izin verici CORS başlıklarıyla yanıt vermelidir; çünkü gerçek hedef sunucunun preflight yanıtı (hedef kaynağa atıfta bulunan), tarayıcının proxy kaynağı için yaptığı CORS denetimini karşılamaz. İkincisi, proxy hedef sunucu yanıtlarından CORS başlıklarını silerek proxy kaynağına atıfta bulunanlarla değiştirmelidir. Service Worker'daki credentials: 'include' ile kombinasyonuyla Access-Control-Allow-Credentials: true ayarı, proxy kaynağından gelen tüm çerezlerin her proxylenen isteğe eşlik ettiği anlamına gelir.

CORB nedir ve proxy hizmetlerini nasıl etkiler?

Cross-Origin Read Blocking (CORB), çapraz kaynak alt kaynaklar olarak yüklendiğinde belirli hassas çapraz kaynak yanıtlarının (HTML, JSON, XML) oluşturma sürecine girmesini engelleyen bir Chromium savunmasıdır. Doğru yapılandırılmış web proxy'ler için CORB genellikle tetiklenmez; çünkü URL yeniden yazımı tüm istekleri aynı kaynak yapar. Ancak CORB, Service Worker tam olarak kaydedilmeden önceki dönemde sorunlara yol açabilir; bu sürede bazı istekler URL yeniden yazımından kaçarak gerçek çapraz kaynak istekleri olarak gönderilebilir. CORB bir Spectre azaltımı olarak tanıtılmış olup WHATWG Fetch spesifikasyonunda tanımlanmaktadır.

Web proxy'ler HTTP-only çerezlere erişebilir mi?

Hayır. HttpOnly çerezler hedef sunucu tarafından ayarlanır ve Service Worker'da çalışanlar da dahil olmak üzere JavaScript tarafından okunamaz. Ancak ağ geçidi, kullanıcı adına iletme yaparken bu çerezleri alır; çünkü tarayıcı bunları istek başlıklarında gönderir. HttpOnly bayrağı, istemci tarafı JavaScript hırsızlığını önler; ancak proxy sunucusunun geçişte çerez değerlerini görmesini engellemez. Bu, HttpOnly'nin XSS'e karşı koruma sağladığı ama sunucu tarafı dinlemeye karşı değil durumuna analojiktir.

Tarayıcı güvenliği açısından web proxy kullanmak güvenli midir?

Tehdit modeline bağlıdır. Tarayıcı perspektifinden, bir web proxy üzerinden sunulan tüm içerik proxy'nin kaynağında çalışır; bu, proxylenen bir sitedeki JavaScript'teki bir güvenlik açığının, aynı kaynağın çerez deposu ve depolama alanını paylaştıkları için potansiyel olarak proxylenen başka bir sitedeki oturum verilerine erişebileceği anlamına gelir. Proxy'nin operatörü de geçişteki tüm trafiğe erişimi olan güvenilir bir taraftır. Kısıtlı ortamlarda hassas olmayan içeriğe erişmek için risk genellikle kabul edilebilir. Hassas hizmetlerle (bankacılık, sağlık, devlet) kimlik doğrulanmış oturumlar için kullanıcılar, proxy operatörünün bu trafiği teknik olarak gözlemleme kapasitesine sahip olduğunu anlamalı ve yalnızca denetlenebilir günlük tutmama politikalarına ve güçlü operasyonel güvenlik uygulamalarına sahip proxy hizmetlerini kullanmalıdır.


Bu makale, 2026 başı itibarıyla ProxyOrb'un mimarisini yansıtmaktadır. Tarayıcı güvenlik mekanizmaları hızla gelişmektedir; okuyucuların en güncel bilgi için WHATWG Fetch Standard, W3C Content Security Policy spesifikasyonu ve Chromium'un güvenlik tasarım belgelerini incelemesi önerilir.