Series · 3 partsBrowser-to-Native Trust BoundariesPart 1 · You are here
  1. 1Extension Sandbox'taydı. Native Host Değildi.You are here
  2. 2Sayfanın İzni Yoktu. Extension'ın Vardı.
  3. 3Paket İmzalıydı. Güncelleme Yine de Bir Güvenlik Kararıydı.

60 saniyede browser güven sınırı

Bir browser extension doğru şekilde paketlenmiş, imzalanmış, incelenmiş ve web sayfasından izole edilmiş olabilir. Buna rağmen işletim sistemine uzanan tehlikeli bir yetki yolu açabilir.

Native Messaging bilinçli olarak güçlü tasarlanmıştır. Browser, kayıtlı native uygulamayı ayrı bir süreç olarak başlatır ve standart girdi/çıktı üzerinden uzunluk bilgisi eklenmiş JSON mesajları aktarır. Native host bundan sonra sıradan web içeriğinin ulaşamadığı dosyalara, cihazlara, kimlik bilgilerine, socket’lere, child process’lere ve yerel yönetim arayüzlerine erişebilir.

Bu mimari tek başına zafiyet değildir. Zafiyet, ayrı soruları cevaplayan geçerli kararların tek bir authorization kararı gibi değerlendirilmesiyle ortaya çıkar:

  1. Bir sayfada content script çalışabilir.
  2. Content script extension service worker’a mesaj gönderebilir.
  3. Service worker kayıtlı native host’a bağlanabilir.
  4. Native host manifest ilgili extension ID’ye izin verir.
  5. Host bir JSON operasyonunu kabul eder.
  6. İşletim sistemi ortaya çıkan etkiye izin verir.

Bu kararların hiçbiri, isteği başlatan sayfanın, frame’in, kullanıcı hareketinin, nesnenin, dosya yolunun veya operasyonun yetkili olduğunu kanıtlamaz.

Temel araştırma sorusu şudur:

Web tarafından kontrol edilen niyet hangi noktada native işletim sistemi etkisine dönüşüyor ve nihai authorization kararını hangi bileşen veriyor?

Bu çalışma, yerel bir kanıtı kontrolsüz gerçek dünya istismarına dönüştürmeden bu soruyu cevaplayabilen tekrarlanabilir bir vulnerability research yöntemi kurar.

Tek özellik, beş ayrı principal

BROWSER → NATIVE YETKİ GRAFİĞİ İZOLASYON EXECUTION CONTEXT'İ DEĞİŞTİRİR; SONRAKİ ETKİYİ YETKİLENDİRMEZ. WEB SAYFASIorigin · frameDOM · kullanıcı girdisi CONTENT SCRIPTisolated worldDAHA AZ GÜVENİLİR SERVICE WORKERextension API'leriPOLİTİKA NOKTASI STDIO JSONlength frameSERIALIZED HOSTnative UIDOS erişimi Browser tarafı gerçekleri sender.id · sender.url · tab.id frameId · documentId · gesture REQUEST'E BAĞLANMAZSA KAYBOLUR Native request contract version · operation · resource nonce · expiry · approval ALLOWLISTED SCHEMA İşletim sistemi etkisi dosya · süreç · cihaz credential · socket · config BAĞIMSIZ DOĞRULAMA HOST MANIFEST EXTENSION'I SEÇER; ORİJİNAL WEB AUTHORIZATION CONTEXT'İNİ KORUMAZ.
Extension ID zincirdeki principal'lardan yalnızca biridir. Sayfa origin'i, frame, extension bileşeni, native süreç kimliği, talep edilen nesne ve ortaya çıkan etki ayrı kalmalıdır.

Chrome, content script’leri sayfanın JavaScript ortamından izole çalışan bileşenler olarak tanımlar. Bu bir execution isolation özelliğidir. Chrome’un mesajlaşma güvenliği rehberi ise content script’lerin service worker’dan daha az güvenilir kabul edilmesini ve onlardan gelen mesajların saldırgan tarafından hazırlanmış olabileceğinin varsayılmasını ister.

Bu ayrım kritiktir. İzole bir content script yine de sayfa kontrollü DOM değerlerini okuyabilir, window.postMessage olaylarını alabilir veya ele geçirilmiş bir origin üzerinde tetiklenebilir. Service worker sender bilgisini ve operasyonu doğrulamadan mesajı iletirse isolated world bir güvenlik sınırı değil, yalnızca relay haline gelir.

Native Messaging gerçekte neyi garanti eder?

Platform kontrolleri değerlidir; ancak her biri dar bir soruyu yanıtlar.

MekanizmaKanıtladığı şeyKanıtlamadığı şey
Extension nativeMessaging izniExtension Native Messaging API’yi kullanabilirHer extension bileşeninin her native operasyonu çağırabileceği
Host allowed_origins / allowed_extensionsBelirtilen extension ID host’u başlatabilirİsteğin hangi sayfa, frame, tenant veya kullanıcı akışından geldiği
Isolated content-script worldSayfa JavaScript’i content script değişkenlerini doğrudan okuyamazSayfadan türetilen verinin güvenilir olduğu
sender.id ve sender.urlBrowser’ın gözlemlediği sender contextOperasyonun, yolun veya nesnenin yetkili olduğu
Length-prefixed JSONMesaj sınırları olan bir transport formatıGüvenli schema, semantic authorization veya replay koruması
Native süreç UID’siHost’un çalıştığı OS kimliğiBrowser caller’ın bu kimliğin tüm erişimini devralması gerektiği
Extension mağaza incelemesiDağıtım ve politika kontrol noktasıAyrı kurulan native uygulamanın doğru olduğu

Chrome native host’u ayrı bir süreç olarak başlatır. Mesaj UTF-8 JSON’dur ve önüne native byte order ile 32-bit uzunluk eklenir. Belgelenmiş browser-to-host sınırı 64 MiB, host-to-browser sınırı ise 1 MiB’dir. Bunlar güvenli uygulama limitleri değil, transport tavanlarıdır. 2 KiB’lık command envelope bekleyen bir host kendi limitini 2 KiB olarak uygulamalıdır.

Chrome host’a ilk argüman olarak extension origin’ini geçirir. Firefox benzer ancak farklı bir contract ve manifest alanı kullanır. Cross-browser uyumluluk kodu bu kimlikleri sessizce birleştirmemelidir. Chrome extension mesajlaşması JSON serialization kullanırken diğer implementasyonlarda structured clone davranışı görülebilir.

Zafiyet kalıbı: origin laundering

En yaygın hata memory corruption değil, origin laundering davranışıdır:

güvenilmeyen sayfa değeri
  → content-script nesnesi
  → extension mesajı
  → native JSON request
  → yerel dosya veya süreç etkisi

Her geçişte sonraki bileşen daha güvenilir görünen bir principal’dan mesaj alır:

  • service worker kendi content script’ini görür;
  • browser kurulu extension’ı görür;
  • native host izin verilen extension origin’ini görür;
  • işletim sistemi yerel native süreci görür.

Orijinal sayfa ve resource authorization bilgisi korunup yeniden doğrulanmazsa context kaybolurken güven seviyesi yükselir.

Zafiyet sınıfıTehlikeli tasarımOlası sonuç
Confused deputyHer content-script mesajı host’a iletilirSayfa extension ve host yetkisini ödünç alır
Eksik object authorizationCaller keyfi path, device ID, profil veya hesap seçerCross-user veya cross-tenant erişim
Argument injectionHost mesaj alanlarını shell string’e eklerHost kimliğiyle native code execution
Path traversal / link followingSon nesne doğrulanmadan yol birleştirilip açılırYetkili root dışından okuma veya yazma
ReplayAyrıcalıklı request’te nonce, expiry veya state binding yokturÖnceki etki tekrar oluşturulur
Parser asymmetryBrowser ve host tipleri veya boyutları farklı yorumlarDoğrulanan nesneyle çalıştırılan nesne farklılaşır
Lifecycle confusionLong-lived port navigation sonrasında state taşırYeni sayfa eski authorization context’i devralır
Installation boundary failureYazılabilir manifest veya host path binary’yi yönlendirirPersistence veya privilege boundary geçişi

Sınırlandırılmış sentetik laboratuvar

Üretim extension’ına veya üçüncü taraf hedefe ihtiyaç yoktur. Laboratuvar şunlardan oluşur:

  • unpacked bir Manifest V3 extension;
  • loopback üzerinde veya https://lab.invalid origin’inde bir test sayfası;
  • yalnızca laboratuvar extension ID için kayıtlı native host;
  • hassas olmayan canary dosyalarının bulunduğu dizin;
  • isimlendirilmiş bir canary okuma operasyonu;
  • gerçekte hangi dosyanın açıldığını kaydeden bağımsız observer.

Güvensiz service worker güven context’inin nasıl kaybolduğunu gösterir:

chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
  if (request.type !== "native") return;

  chrome.runtime.sendNativeMessage(
    "com.jankesec.native_lab",
    request.payload,
    (response) => sendResponse(response),
  );
  return true;
});

Kod yalnızca routing label kontrol eder. Sender bileşeni, origin, frame, operasyon, nesne, boyut, state ve kullanıcı hareketi doğrulanmaz.

Sentetik native host ikinci hatayı görünür hale getirir:

from pathlib import Path

def handle(message):
    if message.get("op") == "read_file":
        return {"data": Path(message["path"]).read_text()}
    return {"error": "unknown operation"}

Bu tam bir exploit değildir; minimal authorization oracle’dır. Positive test /tmp/nmh-lab/canary.txt dosyasını ister. Negative test izin verilen root dışındaki farklı bir canary’yi ister. Finding, yalnızca ikinci request host’a ulaştığında ve bağımsız file observer yanlış nesnenin açıldığını kanıtladığında vardır.

Gerçek browser verileri, SSH anahtarları, password store veya kullanıcı belgeleriyle etki gösterilmemelidir. Zafiyet ödünç alınan dosyanın hassasiyeti değil, yetkisiz nesne geçişidir.

Web sayfasının izole extension odalarından ve çerçeveli mesaj kanalından geçerek native dosya ve süreç mekanizmasına ulaştığı mimari kesit.
Sınır görseli / 01 Browser-to-native yol tek bir pipe değildir. Her oda principal'ı, mevcut context'i ve yetkiyi değiştirir.

Etkileşimden önce envanter

Mesaj göndermeden önce extension ve native host kurulum durumunu statik kanıtlarla kaydedin.

Extension envanteri

AlanKanıt
Extension ID ve kurulum kaynağıBrowser extension sayfası, enterprise policy, imzalı paket metadata
Manifest ve updateManifest version, update URL ve managed-extension policy
İzinlerpermissions, optional_permissions, host_permissions
Content-script erişimiMatch pattern, excluded match, frame ve execution world
Harici caller’larexternally_connectable ID ve page pattern’leri
Message listener’laronMessage, onConnect ve external varyantları
Native operasyonlarTüm connectNative ve sendNativeMessage call site’ları
Sender kontrollerisender.id, URL origin, tab, frame, document, incognito state
State bindingGesture, nonce, expiry, selected object, active tab, tenant

Native host envanteri

AlanKanıt
Manifest konumu ve sahibiOS path veya registry key, ownership ve ACL
Host executableAbsolute ve resolved path, son dosya kimliği
Allowed extension ID’leriallowed_origins veya allowed_extensions
Runtime kimliğiUID, token, integrity level, sandbox veya service account
ParserLength handling, UTF-8, JSON type ve maximum size
DispatcherOperation allowlist ve default-deny davranışı
Object authorizationResource ID’nin path, device veya account’a dönüşümü
Process creationShell kullanımı, argument array, environment ve working directory
OutputVeri sınıflandırması, truncation, error ve stderr logging
Update pathInstaller identity, signature verification ve yazılabilir parent path

Bu envanter false positive’leri de kapatır. Ayrıcalıklı görünen bir host yalnızca sabit durum sorgusu sunabilir. Buna karşılık user-level bir host browser profilleri, developer credential’ları, cloud CLI’ları ve local socket’lere erişerek yüksek etkili bir yol oluşturabilir.

Browser context’i request içinde koruyun

Service worker ilk güvenilir politika noktasıdır. Page-defined nesneyi forward etmek yerine browser’ın gözlemlediği gerçekleri küçük bir request contract’a dönüştürmelidir.

const ALLOWED_ORIGINS = new Set(["https://lab.invalid"]);

chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
  const origin = sender.url ? new URL(sender.url).origin : "";
  const validSender =
    sender.id === chrome.runtime.id &&
    sender.tab?.id !== undefined &&
    sender.frameId === 0 &&
    ALLOWED_ORIGINS.has(origin);

  if (!validSender || message?.type !== "read-canary") {
    sendResponse({ ok: false, error: "denied" });
    return false;
  }

  const request = {
    version: 1,
    operation: "canary.read",
    resource: String(message.resource),
    origin,
    tabId: sender.tab.id,
    documentId: sender.documentId,
    nonce: crypto.randomUUID(),
    expiresAt: Date.now() + 5_000,
  };

  chrome.runtime.sendNativeMessage(
    "com.jankesec.native_lab",
    request,
    sendResponse,
  );
  return true;
});

Bu daha güçlüdür ancak tek başına yeterli değildir. Native host, alanları extension oluşturduğu için körlemesine güvenemez. Contract sabit schema, bounded value, kısa lifetime, replay tracking ve operation-to-resource authorization tablosuna ihtiyaç duyar.

Browser contract içinde kullanıcı kontrollü path taşımayın. canary-a gibi sabit resource ID kullanın ve path’i host içinde çözümleyin:

RESOURCES = {
    "canary-a": Path("/tmp/nmh-lab/canary-a.txt"),
    "canary-b": Path("/tmp/nmh-lab/canary-b.txt"),
}

def handle(message):
    if set(message) != {
        "version", "operation", "resource", "origin",
        "tabId", "documentId", "nonce", "expiresAt",
    }:
        return {"ok": False, "error": "schema"}

    if message["version"] != 1 or message["operation"] != "canary.read":
        return {"ok": False, "error": "operation"}

    path = RESOURCES.get(message["resource"])
    if path is None:
        return {"ok": False, "error": "resource"}

    return {"ok": True, "data": path.read_text()}

Yüksek etkili operasyonlarda origin yazan JSON alanı kanıt değildir. Browser-observed state ile brokered session oluşturun; approval’ı çözümlenmiş operation ve object’e bağlayın; native capability’yi host’un ambient OS identity’sinden daha dar tutun.

Transport’u hostile input olarak parse edin

Native host parser tam dört header byte okumalı, allocation öncesi oversized mesajı reddetmeli, ilan edilen body boyutunu eksiksiz okumalı, strict UTF-8 decode etmeli, JSON object zorunlu kılmalı, tipleri doğrulamalı ve tek framed response üretmelidir.

import json
import struct
import sys

MAX_REQUEST = 16 * 1024

def read_exact(stream, count):
    chunks = bytearray()
    while len(chunks) < count:
        part = stream.read(count - len(chunks))
        if not part:
            raise EOFError("truncated native message")
        chunks.extend(part)
    return bytes(chunks)

def read_message():
    header = read_exact(sys.stdin.buffer, 4)
    length = struct.unpack("@I", header)[0]
    if length == 0 or length > MAX_REQUEST:
        raise ValueError("invalid message length")

    payload = read_exact(sys.stdin.buffer, length)
    value = json.loads(payload.decode("utf-8", errors="strict"))
    if not isinstance(value, dict):
        raise TypeError("message must be an object")
    return value

Parser testleri zero/truncated/oversized header, hatalı body length, invalid UTF-8, extra field, yanlış tip, aşırı nested JSON, arka arkaya frame, mid-frame EOF ve stdout contamination senaryolarını içermelidir. Debug çıktısı stderr’e yazılmalıdır; stdout’a düşen tek bir debug satırı framing kanalını bozar.

Authorization her hop boyunca yaşamalıdır

NATIVE ETKİ KARAR HATTI NATIVE CAPABILITY OLUŞMADAN ÖNCE CONTEXT'İ DOĞRULA 1 · SENDERorigin · framedocument · gesture 2 · SCHEMAversion · typessize · unknown keys 3 · RESOLVEoperation IDresource ID 4 · POLICYallow · expiryreplay gate 5 · EXECUTEnarrow UIDno shell DENIAL RECORDgate · reason · request IDoperasyon yok · etki yok EFFECT VERIFIERbeklenen object değişti mi?diğerleri değişmedi mi? EVIDENCE BUNDLErequest · decision · effectnegative control · cleanup FAIL CLOSED: UNKNOWN SENDER · STALE DOCUMENT · EXTRA FIELD · UNKNOWN RESOURCE · REPLAY · AMBIENT ADMIN · EFFECT MISMATCH
Geçerli extension origin'i yalnızca ilk gate'tir. Sender, schema, object, policy, runtime identity ve expected effect aynı kararda birleşmeden native yetki oluşturulmaz.

Kanıt matrisi

Savunulabilir sonuç; observed fact, inference, positive execution, negative control ve belirsizliği birbirinden ayırır.

İddiaPositive evidenceNegative controlGüçlü sonuç
Sayfa extension listener’a ulaşabiliyorTab, frame, document ve origin ile gözlenen mesajEşleşmeyen origin’den aynı mesaj reddedilirReachability kaydedilen sender kümesiyle sınırlıdır
Extension host’u başlatabiliyorRequest ID ile korele host process creationListede olmayan extension ID access denial alırHost manifest extension identity filtreler
Host operasyon sunuyorGeçerli schema beklenen canary sonucunu döndürürUnknown operation ve extra field reddedilirDispatcher explicit ve default-deny çalışır
Resource authorization çalışıyorAllowed ID mapped canary’yi açarTraversal, absolute path, symlink ve unknown ID başarısızdırCaller test edilen varyantlarla keyfi nesne seçemez
Replay kontrol altındaFresh nonce yalnızca bir kez başarılıdırAynı nonce ve expired request etki oluşturmazRequest lifetime içinde single-use’dur
Native authority sınırlıdırRuntime identity ve system-call trace beklenen object’e uyarKorunan ve ilgisiz nesnelerin değişmediği doğrulanırEtki test edilen capability ile sınırlıdır
Cleanup tamamdırManifest, extension, canary, process ve log kaldırılırCleanup sonrası reconnect başarısızdırLaboratuvar bridge’i artık erişilebilir değildir

Denied JSON response tek başına “etki oluşmadı” kanıtı değildir. Canary, filesystem event, process tree veya device state bağımsız doğrulanmalıdır.

Test matrisi

KatmanTestGüvenli sonuç
Web originAllowed ve unallowed origin’den aynı mesajYalnızca exact allowed origin ilerler
FrameTop frame, embedded frame ve stale frameUygun olmayan frame/document reddedilir
Extension senderContent script, extension page, external extension, external pageHer sender sınıfı için ayrı explicit policy vardır
SchemaMissing, extra, wrong-type, nested ve oversized değerOperation resolution öncesi reddedilir
OperationKnown read, unknown operation, deprecated versionYalnızca güncel allowlisted operasyon vardır
ResourceKnown ID, arbitrary path, traversal, symlink, race targetAçılan son object authorized set içinde kalır
ProcessArgument array ve shell stringAttacker-controlled shell interpretation oluşmaz
LifecycleNavigation, reconnect, worker ve browser restartAuthorization bağlı olduğu context’ten uzun yaşamaz
ReplayDuplicate nonce ve expired messageİkinci etki yoktur
InstallationWritable manifest, parent ve redirected host pathACL veya integrity control substitution’ı engeller
OutputOversized response, stdout noise, malformed JSONProtocol desync olmadan bounded failure
CleanupExtension veya host registration kaldırılırBrowser host’u tekrar başlatamaz

Sertleştirme sırası

  1. Gereksiz Native Messaging erişimini kaldırın. Kurulu olmayan capability gelecekteki extension bug’ından çağrılamaz.
  2. Content script ve host erişimini daraltın. Match pattern, frame, host permission, external caller ve optional permission kapsamını azaltın.
  3. Browser-observed sender context’i doğrulayın. Page-provided origin veya tab claim kabul etmeyin.
  4. Versioned operation schema tanımlayın. Unknown key, yanlış tip, büyük boyut ve deprecated operation fail closed olmalıdır.
  5. Identifier’ları trusted component içinde çözün. Page-supplied path, command, URL ve device handle authority injection’dır.
  6. Policy ve execution’ı ayırın. Dispatcher küçük implementation’ı çağırmadan önce operation ve resource’u yetkilendirmelidir.
  7. Shell ve ambient administrator identity kullanmayın. Fixed executable, argument array, sanitized environment, controlled working directory ve least privilege kullanın.
  8. Yüksek etkili işlemleri state’e bağlayın. Gesture, selected object, nonce, expiry ve approval aynı request’i tanımlamalıdır.
  9. Etkiyi bağımsız doğrulayın. Beklenen object değişimini ve komşu object’lerin değişmediğini kaydedin.
  10. Installation path’i koruyun. Manifest, registry key, executable path, update package ve parent directory güvenlik sınırının parçasıdır.

Detection ve forensic sinyaller

  • extension install source, ID, version, permission ve update değişiklikleri;
  • connectNative / sendNativeMessage operation name ve request ID;
  • native host process parent, command line, origin argümanı, UID, hash ve signature;
  • Native Messaging manifest veya registry değişiklikleri;
  • host tarafından başlatılan child process’ler;
  • host’a atfedilen file, socket, device, credential veya configuration etkileri;
  • gate ve reason bazında denied operation;
  • anormal message size, parse failure, reconnect rate ve replay detection;
  • browser idle iken veya approved workflow yokken host execution.

Log’lar secret payload değil identifier ve decision kaydetmelidir. Native mesajlar token, file content, account name veya local path içerebilir. Evidence collection ikinci bir veri sızıntısı yolu oluşturmamalıdır.

Finding nasıl raporlanmalı?

Güçlü başlık kaybolan sınırı açıkça söyler:

Browser content script, extension attacker-controlled path’i forward ettiği ve host object authorization uygulamadığı için Native Messaging host’a approved resource set dışındaki bir nesneyi okutabiliyordu.

Rapor şunları içermelidir:

  • extension ve native host version;
  • installation ve runtime identity;
  • erişilebilir sender context’leri;
  • minimal request schema;
  • approved ve unauthorized canary object’leri;
  • positive effect evidence;
  • negative control;
  • gerçek hassas veri kullanmadan gösterilen maksimum etki;
  • extension ve host tarafındaki root cause;
  • string filter değil operation contract’ı değiştiren remediation;
  • cleanup kanıtı.

Severity, nativeMessaging izninin varlığından değil reachable effect’ten gelir. Yalnızca status döndüren host informational olabilir. Developer credential okuyabilen user-level host high impact yaratabilir. Broad dispatcher üzerinden erişilen system service privilege boundary aşabilir.

Son model

Native Messaging, extension ve host tek bir dar, versioned authorization protocol gibi davrandığında güvenlidir:

browser-observed sender
  → allowed operation
  → trusted resource resolution
  → bounded native identity
  → independently verified effect

Browser sandbox değerlidir. Extension ID değerlidir. Host manifest değerlidir. Ancak bunların hiçbiri keyfi native etkiyi yetkilendirmez.

Bridge yalnızca orijinal web context native tarafın deliberate, testable ve observable karar vermesine yetecek kadar uzun yaşadığında güvenilirdir.

Kaynaklar ve güncellik

Bu teknik not ne kadar güncel?

Kontrol edilen kaynaklar31 Ağustos 2026

En son kaynak incelemesi, içerik güncellemesi veya yayın tarihi gösterilmektedir.

İnceleme DurumuKamuya açık kaynaklar incelendi

Birincil kamu kayıtları kontrol edildi. Ortama özgü davranış, ayrıca yeniden üretilmedikçe iddianın dışındadır.