Bloga Dön

Sunucusuz Oyun Backend'lerinde Spectre Yan Kanal Saldırıları: Tespit ve Düzeltme Runbook'u

Yayınlanma tarihi 25 Ağustos 2026
Sunucusuz Oyun Backend'lerinde Spectre Yan Kanal Saldırıları: Tespit ve Düzeltme Runbook'u Yapay zekâ yardımıyla oluşturuldu

Özet olarak

Sunucusuz oyun backend'lerinde Spectre yan kanal saldırılarını tespit edin, düzeltin ve önleyin. Pratik runbook ile mimarinizi güvenli hale getirin.

Sunucusuz oyun backend'iniz, oyuncu kimlik doğrulama token'larını, envanter güncellemelerini ve eşleştirme (matchmaking) isteklerini onlarca başka kiracıyla paylaşılan donanım üzerinde işler. Aynı fiziksel CPU üzerinde konumlanmış bir saldırgan, hassas verileri — kodunuz üzerinden değil, silikonun kendisi üzerinden — çıkarabilir. Cloudflare'in son açıklaması bunun teorik olmadığını doğruluyor: araştırmacılar, üretimdeki Cloudflare Workers üzerinden saniyede 12 bit veriyi %99 doğrulukla sızdırmayı başardı.

Oyun mantığınızı herhangi bir sunucusuz veya çok kiracılı platformda çalıştırıyorsanız, bu runbook neyin bozulduğunu, nasıl tespit edileceğini, nasıl düzeltileceğini ve tekrar oluşmasını önlemek için mimarinin nasıl kurulacağını kapsar.

Ne Bozulur: Sunucusuz Oyun Backend'lerinde Spectre

Saldırı Yüzeyi

Spectre, modern CPU'lardaki spekülatif yürütmeyi istismar eder. Bir işlemci koşullu bir dala (conditional branch) ulaştığında, koşul çözülmeden önce her iki yolu da spekülatif olarak yürütür. Spekülasyon yanlışsa, CPU geri alır — ancak CPU önbelleğinde (cache) izler kalır. Önbellek zamanlamasını ölçen bir saldırgan, spekülasyon sırasında hangi verilere erişildiğini çıkarabilir.

Sunucusuz bir ortamda bu tehlikeli hale gelir çünkü:

  • Paylaşılan donanım: Oyun backend fonksiyonunuz, diğer kiracıların koduyla aynı fiziksel CPU çekirdeğinde (farklı zamanlarda) çalışır
  • Yüksek çözünürlüklü zamanlayıcılar: JavaScript'in performance.now() ve SharedArrayBuffer tabanlı zamanlayıcıları, saldırganlara nanosaniye hassasiyetinde önbellek ölçümleri verir
  • Öngörülebilir bellek düzenleri: V8'in JIT derleyicisi, çağrılar arasında tutarlı bellek düzenleri oluşturur ve gadget zincirlerini güvenilir hale getirir

Cloudflare Workers Proof-of-Concept

TU Graz'daki araştırma ekibi, Cloudflare ile birlikte pratik bir saldırı zinciri gösterdi:

  1. Gadget tanımlama: V8 runtime'ında, gizli verilere dayalı olarak saldırgan kontrolündeki belleğe erişen bir spekülatif yürütme gadget'ı bulun
  2. Zamanlayıcı kurulumu: Yüksek çözünürlüklü bir zamanlayıcı (nanosaniye altı hassasiyet) oluşturmak için SharedArrayBuffer kullanın
  3. Önbellek hazırlama: İlgili önbellek satırlarını temizleyin, gadget'ı tetikleyin ve yeniden yükleme sürelerini ölçün
  4. Veri çıkarma: Zamanlama ölçümlerinden gizli bitleri saniyede 12 bit ve %99 doğrulukla yeniden yapılandırın

Sızdırılan veriler arasında kimlik doğrulama token'ları, şifreleme anahtarları ve aynı ortamda çalışan diğer Workers'ların işlediği diğer sırlar yer alıyordu.

Oyun Backend'leri Neden Özellikle Savunmasız

Oyun backend'leri yüksek değerli sırları sürekli işler:

  • Oyuncu kimlik doğrulaması için JWT token'ları (genellikle 300-1000 bayt base64 kodlu veri)
  • Gerçek zamanlı çok oyunculu durum için oturum şifreleme anahtarları
  • Uygulama içi satın alımlar için ödeme işleme token'ları
  • Etkili olması için gizli kalması gereken anti-cheat imzaları

12 bit/s sızıntı hızı yavaş görünebilir, ancak 256 bitlik bir AES anahtarı çıkarmak yalnızca ~21 saniye sürer. 512 bitlik bir JWT token'ı ~43 saniye sürer. 20+ dakika süren bir oyun oturumunda, bir saldırgan önemli miktarda gizli materyal çıkarabilir.

Nasıl Tespit Edilir

Yan Kanal Aktivitesi İzleme

Spectre saldırılarını uygulama günlükleri aracılığıyla doğrudan gözlemleyemezsiniz. Bunun yerine, ön koşulları ve davranışsal imzaları izleyin:

1. Zamanlayıcı Çözünürlüğü Kötüye Kullanım Tespiti

// Detection script: Monitor for high-frequency timer access patterns
// Deploy as a middleware or wrapper around your serverless functions

const TIMER_ACCESS_THRESHOLD = 1000; // accesses per second
const timerAccessLog = new Map();

function monitorTimerAccess(sessionId) {
  const now = Date.now();
  const entry = timerAccessLog.get(sessionId) || { count: 0, windowStart: now };
  
  if (now - entry.windowStart > 1000) {
    // Reset window
    entry.count = 1;
    entry.windowStart = now;
  } else {
    entry.count++;
  }
  
  timerAccessLog.set(sessionId, entry);
  
  if (entry.count > TIMER_ACCESS_THRESHOLD) {
    // Alert: Possible side-channel reconnaissance
    logSecurityEvent({
      type: 'TIMER_ABUSE_SUSPECTED',
      sessionId,
      accessCount: entry.count,
      timestamp: now,
      severity: 'HIGH'
    });
    return true; // Flag for further inspection
  }
  return false;
}

2. SharedArrayBuffer Kullanım İzleme

Oyun backend'iniz meşru olarak SharedArrayBuffer'a ihtiyaç duymuyorsa (çoğu duymaz), oluşturulmasını izleyin:

// Wrap SharedArrayBuffer constructor to detect unauthorized usage
const OriginalSAB = globalThis.SharedArrayBuffer;
let sabCreationCount = 0;

globalThis.SharedArrayBuffer = function(...args) {
  sabCreationCount++;
  
  if (sabCreationCount > 5) { // Legitimate game code rarely creates many
    logSecurityEvent({
      type: 'SAB_CREATION_ANOMALY',
      count: sabCreationCount,
      stackTrace: new Error().stack,
      severity: 'CRITICAL'
    });
  }
  
  return new OriginalSAB(...args);
};

3. Önbellek Zamanlama Deseni Analizi

Ardından hassas zamanlama ölçümleri gelen tekrarlayan bellek yoğun işlem desenlerini izleyin. Bunu uygulama düzeyinde tespit etmek daha zordur, ancak altyapı düzeyinde izleme şunları işaretleyebilir:

  • Ayrılan CPU sürelerinin >%90'ını tutarlı şekilde kullanan fonksiyonlar
  • Olağandışı Atomics.load() ve Atomics.store() çağrı desenleri
  • Belirgin bir uygulama amacı olmadan büyük bitişik bellek bölgelerine erişen fonksiyonlar

Altyapı Düzeyinde Tespit

Altyapı düzeyinde şunlara dikkat edin:

  • Yerleşim desenleri: Aynı saldırgan kontrolündeki fonksiyon, oyun backend'inizle tekrar tekrar aynı fiziksel donanıma yerleşiyorsa, bu bir kırmızı bayraktır
  • Kaynak tüketimi anormallikleri: Spectre PoC'leri genellikle ölçüm yaparken hedef çekirdekte %100 CPU tüketir
  • Ağ dışa sızma: Çıkarılan bitler sistemden bir şekilde çıkmalıdır — sunucusuz fonksiyonlardan olağandışı giden veri desenlerini izleyin

Nasıl Düzeltilir

Acil Eylemler (24 Saat İçinde Dağıtın)

Adım 1: Yüksek Çözünürlüklü Zamanlayıcıları Devre Dışı Bırakın

En etkili tek önlem, saldırganın önbellek zamanlamasını hassas şekilde ölçme yeteneğini ortadan kaldırmaktır:

// serverless-security-hardening.js
// Apply to all game backend serverless functions

// 1. Reduce timer resolution to 100 microseconds (10,000x reduction)
if (typeof performance !== 'undefined') {
  const originalNow = performance.now.bind(performance);
  const TIMER_GRANULARITY = 0.1; // 100 microseconds
  
  performance.now = function() {
    const precise = originalNow();
    return Math.round(precise / TIMER_GRANULARITY) * TIMER_GRANULARITY;
  };
}

// 2. Disable SharedArrayBuffer entirely if not needed
// (Most game backends don't need it server-side)
delete globalThis.SharedArrayBuffer;
delete globalThis.Atomics;

// 3. Add timing jitter to all async operations
const originalSetTimeout = globalThis.setTimeout;
globalThis.setTimeout = function(callback, delay, ...args) {
  // Add random jitter between 0-5ms to prevent timing synchronization
  const jitter = Math.random() * 5;
  return originalSetTimeout(callback, delay + jitter, ...args);
};

Adım 2: Hassas İşlemler için Süreç İzolasyonu Uygulayın

Sırları işleyen işlemleri, sertleştirilmiş bellek düzenlerine sahip ayrı süreçlere izole edin:

// process-isolation-config.js
// Configuration for isolating sensitive game backend operations

const isolationConfig = {
  // Operations that MUST run in isolated processes
  sensitiveOperations: [
    'auth.token.verify',
    'auth.token.generate',
    'payment.process',
    'crypto.encrypt',
    'crypto.decrypt',
    'anticheat.signature.validate'
  ],
  
  // Process pool configuration
  processPool: {
    minProcesses: 2,
    maxProcesses: 8,
    // Each process gets its own memory space — no cross-process cache sharing
    memoryIsolation: true,
    // Randomize process assignment to prevent co-location targeting
    randomAssignment: true,
    // Rotate processes every N requests to disrupt long-running attacks
    rotationInterval: 1000
  }
};

// Implementation: Route sensitive operations to isolated processes
async function executeSensitiveOperation(operationName, payload) {
  if (!isolationConfig.sensitiveOperations.includes(operationName)) {
    throw new Error(`Operation ${operationName} not in sensitive list`);
  }
  
  const worker = await getIsolatedWorker(isolationConfig.processPool);
  
  try {
    const result = await worker.execute(operationName, payload);
    return result;
  } finally {
    // Always return worker to pool — never reuse across operations
    await worker.terminate(); // Fresh process next time
  }
}

Adım 3: Bellek Erişim Desenlerini Sertleştirin

Spekülatif yürütme gadget'larını ortadan kaldırmak için gizli veriye bağlı bellek erişimlerini sabit zamanlı (constant-time) hale getirin:

// constant-time-comparison.js
// Replace all secret-dependent branching with constant-time operations

// VULNERABLE: Branch depends on secret data
function verifyTokenVulnerable(token, expectedHash) {
  const hash = computeHash(token);
  if (hash === expectedHash) { // Branch leaks information via cache
    return true;
  }
  return false;
}

// SECURE: Constant-time comparison — no branch depends on secret
function verifyTokenSecure(token, expectedHash) {
  const hash = computeHash(token);
  
  if (hash.length !== expectedHash.length) {
    return false; // Length mismatch is not secret-dependent
  }
  
  let result = 0;
  for (let i = 0; i < hash.length; i++) {
    // XOR accumulates differences without branching
    result |= hash.charCodeAt(i) ^ expectedHash.charCodeAt(i);
  }
  
  // Final comparison: 0 means all bytes matched
  return result === 0;
}

// SECURE: Constant-time array lookup (prevents cache-timing on index)
function constantTimeLookup(table, index) {
  // Access ALL entries, but only use the one we want
  // This prevents cache line reveals about which index was accessed
  let result = null;
  for (let i = 0; i < table.length; i++) {
    const match = (i === index) ? 0xFF : 0x00;
    // Conditional select without branching
    result = (table[i] & match) | (result & ~match);
  }
  return result;
}

Kısa Vadeli Eylemler (1 Hafta İçinde Dağıtın)

Adım 4: Derinlemesine Savunma Token Mimarisi Uygulayın

Bellekte bulunan sırları en aza indirerek sızdırılan verilerin değerini azaltın:

// token-architecture.js
// Minimize secret material in serverless function memory

class SecureTokenHandler {
  constructor() {
    // Never store the full token — process in chunks
    this.CHUNK_SIZE = 32; // bytes
  }
  
  async verifyTokenChunked(token) {
    const chunks = this.splitIntoChunks(token);
    const expectedChunks = await this.getExpectedChunks(token.id);
    
    let isValid = true;
    for (let i = 0; i < chunks.length; i++) {
      // Each chunk verification is independent
      // Attacker must leak ALL chunks to reconstruct the token
      const chunkValid = await this.verifyChunk(chunks[i], expectedChunks[i]);
      isValid = isValid && chunkValid;
      
      // Immediately overwrite chunk in memory
      chunks[i].fill(0);
    }
    
    return isValid;
  }
  
  splitIntoChunks(token) {
    const buffer = Buffer.from(token, 'base64');
    const chunks = [];
    for (let i = 0; i < buffer.length; i += this.CHUNK_SIZE) {
      chunks.push(buffer.slice(i, i + this.CHUNK_SIZE));
    }
    return chunks;
  }
}

Adım 5: Kanarya Token'ları Dağıtın

Erişildiğinde uyarı tetikleyen sahte sırlar yerleştirin:

// canary-tokens.js
// Deploy fake secrets that detect unauthorized memory reads

const CANARY_PREFIX = 'CANARY_';

function deployCanaryTokens() {
  const canaries = [];
  
  // Generate 10 fake tokens that look like real JWT tokens
  for (let i = 0; i < 10; i++) {
    const canary = {
      id: `${CANARY_PREFIX}${generateUUID()}`,
      value: generateFakeJWT(), // Looks real but is tracked
      deployedAt: Date.now(),
      location: `memory_region_${i}`
    };
    canaries.push(canary);
  }
  
  // Store in predictable memory locations
  // If these values appear in network traffic, we know memory was read
  globalThis.__SECURITY_CANARIES__ = canaries;
  
  return canaries;
}

function checkCanaryIntegrity() {
  const canaries = globalThis.__SECURITY_CANARIES__ || [];
  
  // Verify canaries haven't been exfiltrated by checking
  // if they appear in any outbound network requests
  // (This requires network monitoring integration)
  
  return canaries.every(c => {
    const age = Date.now() - c.deployedAt;
    return age < 3600000; // Rotate canaries every hour
  });
}

Tekrar Oluşması Nasıl Önlenir

Spectre Dirençli Oyun Backend'leri için Mimari Desenler

Desen 1: Sır Minimizasyonu

Spectre'a karşı en iyi savunma, sızdırılacak daha az sırrın olmasıdır:

  • Uzun ömürlü oturum token'ları yerine kısa ömürlü token'lar (5 dakika geçerlilik) kullanın
  • Sızdırılan token'ların başka yerde işe yaramaması için istemci IP/parmak izine token bağlama uygulayın
  • Şifreleme anahtarlarını sunucusuz fonksiyon belleğinde değil, donanım güvenlik modüllerinde (HSM) saklayın
  • Sunucu tarafı oturum depolamayı önlemek için durumsuz kimlik doğrulama (kısa geçerlilikli imzalı JWT'ler) kullanın

Desen 2: Katmanlı İzolasyon

┌─────────────────────────────────────────────────┐
│                  Load Balancer                    │
│         (Random assignment to regions)           │
├─────────────────────────────────────────────────┤
│           Serverless Function Layer              │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐      │
│  │ Function │  │ Function │  │ Function │      │
│  │    A     │  │    B     │  │    C     │      │
│  └────┬─────┘  └────┬─────┘  └────┬─────┘      │
│       │              │              │            │
├───────┼──────────────┼──────────────┼────────────┤
│       ▼              ▼              ▼            │
│           Process Isolation Layer                │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐      │
│  │ Isolated │  │ Isolated │  │ Isolated │      │
│  │ Process  │  │ Process  │  │ Process  │      │
│  │ (Secrets)│  │ (Secrets)│  │ (Secrets)│      │
│  └──────────┘  └──────────┘  └──────────┘      │
│       Randomized memory layout per invocation    │
├─────────────────────────────────────────────────┤
│              HSM / Key Vault Layer               │
│         (Encryption keys never in memory)        │
└─────────────────────────────────────────────────┘

Desen 3: Zamanlayıcı Sertleştirme

Bu önlemleri fonksiyon başına değil, platform düzeyinde dağıtın:

// platform-timer-hardening.js
// Apply at the serverless platform initialization layer

function hardenTimers() {
  // 1. Reduce performance.now() resolution
  const perfNow = performance.now;
  performance.now = () => Math.round(perfNow() / 100) * 100;
  
  // 2. Reduce Date.now() resolution  
  const dateNow = Date.now;
  Date.now = () => Math.round(dateNow() / 10) * 10;
  
  // 3. Disable SharedArrayBuffer
  globalThis.SharedArrayBuffer = undefined;
  
  // 4. Add noise to all timing sources
  const noise = () => Math.random() * 0.05; // 50 microsecond noise
  const originalPerfNow = performance.now;
  performance.now = () => originalPerfNow() + noise();
  
  // 5. Limit Worker thread creation
  const OriginalWorker = globalThis.Worker;
  let workerCount = 0;
  globalThis.Worker = function(...args) {
    if (workerCount >= 2) {
      throw new Error('Worker limit exceeded');
    }
    workerCount++;
    return new OriginalWorker(...args);
  };
}

Sunucusuz Oyun Backend Güvenliği için En İyi Uygulamalar

  1. Yerleşimi varsayın: Sisteminizi, bir saldırganın donanımınızı paylaştığını varsayarak tasarlayın. Bellekteki her sır, yan kanallar aracılığıyla potansiyel olarak okunabilir. Herhangi bir zamanda bellekte bulunanları en aza indirin.

  2. Agresif rotasyon: Maksimum 5 dakikalık token geçerliliği kullanın. Şifreleme anahtarlarını her saat döndürün. Güvenlik açığı penceresi, sırların bellekte kalma süresiyle doğrudan orantılıdır.

  3. Zamanlayıcı erişim desenlerini izleyin: Oyun backend'iniz milisaniye altı zamanlamaya ihtiyaç duymuyorsa (çoğu duymaz), yüksek çözünürlüklü zamanlayıcıları tamamen devre dışı bırakın. Oyun için gerekiyorsa, zamanlamaya duyarlı kodu sır işleyen koddan izole edin.

  4. Spectre PoC'leriyle test edin: Hazırlama ortamınıza karşı proof-of-concept Spectre saldırıları çalıştırın. Cloudflare araştırma makalesi, uyarlayabileceğiniz metodolojiyi içerir. Kendi sırlarınızı sızdırabiliyorsanız, bir saldırgan da sızdırabilir.

  5. Savunmalarınızı katmanlayın: Tek bir önlem yeterli değildir. Zamanlayıcı sertleştirmeyi, süreç izolasyonunu, sabit zamanlı kodu, kısa ömürlü token'ları ve kanarya tespitini birleştirin. Her katman saldırı maliyetini katlanarak artırır.

horizOn'un Sunucusuz Güvenlik Yaklaşımı

horizOn'da bu güvenlik endişelerini platform düzeyinde işliyoruz, böylece her önlemi kendiniz uygulamak zorunda kalmazsınız. Sunucusuz oyun backend altyapımız, varsayılan olarak yapılandırılmış zamanlayıcı sertleştirme, hassas işlemler için süreç izolasyonu ve otomatik token rotasyonu içerir.

horizOn üzerinden kimlik doğrulama işlediğinizde, token'lar sabit zamanlı karşılaştırma ile izole süreçlerde doğrulanır ve şifreleme anahtarları fonksiyon belleğinde saklanmak yerine anahtar kasası katmanımız aracılığıyla yönetilir. Bu, özel güvenlik kodu yazmadan Spectre saldırı yüzeyinin en aza indirildiği anlamına gelir.

İhlallere dayanıklı mimariler geliştiren oyun geliştiricileri için ilke aynıdır: ihlali varsayın, patlama yarıçapını en aza indirin ve erken tespit edin.

Sonraki Adımınız

Sunucusuz oyun backend'inizi bugün denetleyin. Şu üç eylemle başlayın:

  1. Sırlarınızı envanterleyin: Tipik bir oyun oturumu sırasında sunucusuz fonksiyon belleğinde bulunan her hassas veriyi listeleyin
  2. Zamanlayıcı çözünürlüğünü ölçün: Platformunuzun yüksek çözünürlüklü zamanlayıcılar sunup sunmadığını kontrol edin (performance.now()'u bir döngüde çalıştırın ve minimum deltayı ölçün)
  3. Sabit zaman uyumluluğunu test edin: Kimlik doğrulama ve şifreleme kodunuzu gizli veriye bağlı dallar için inceleyin

Spectre saldırı sınıfı ortadan kalkmayacak — modern CPU'ların nasıl çalıştığına işlenmiş durumda. Soru, sunucusuz backend'inizin teorik olarak savunmasız olup olmadığı değil, saldırganların başka yere bakmasını sağlayacak kadar pahalı hale getirip getirmediğinizdir.


Kaynak: Cloudflare Workers üzerinde uzaktan Spectre saldırılarının yeniden incelenmesi