Dil seçin

İlerleyici Web Uygulaması Güvenliği Sanatında Ustalaşma

İlerleyici Web Uygulamaları (PWAs), açık web üzerinde uygulama‑benzeri deneyimler sunmanın de‑facto standardı haline geldi. Çevrim‑dışı çalışma, push bildirimleri ve kurulabilirlik gibi temel avantajları, geleneksel web sitelerinin nadiren karşılaştığı yeni saldırı yüzeylerini de beraberinde getiriyor. Bu makale, bir PWA’nın güvenlik yaşam döngüsünü derinlemesine inceliyor; ağ‑seviyesi güçlendirmeyi, çalışma‑zamanı korumalarını ve operasyonel en iyi uygulamaları birleştiriyor. Sonuna geldiğinizde, basit bir haber okuyucudan karmaşık bir e‑ticaret platformuna kadar herhangi bir projeye uygulayabileceğiniz bir kontrol listesine sahip olacaksınız.

TL;DR: PWA’nızı HTTPS ile güvence altına alın, katı CSP uygulayın, servis çalışanlarını sandbox’layın, tüm girdileri doğrulayın ve sürekli izleme rutinini benimseyin.


1. Taşıma Katmanı – İlk Savunma Hattı

1.1 HTTPS’yi Her Yerde Zorunlu Kullanın

Tüm modern tarayıcılar, servis çalışanı kaydı için HTTPS zorunluluğu getirir. Ancak bazı varlıklar (örneğin üçüncü‑taraf analitikler) hâlâ HTTP üzerinden yüklenebilir; bu da karışık‑içerik uyarılarına ve ortadaki adam (MITM) saldırılarına kapı aralar.

Ana adımlar:

  1. Güvenilir bir TLS sertifikası edinin (Let’s Encrypt, Cloudflare vb.).
  2. Sunucu yapılandırmasıyla tüm http:// isteklerini https://‘a yönlendirin.
  3. HSTS (HTTP Strict Transport Security)’yi etkinleştirerek tarayıcıların belirli bir süre boyunca sadece HTTPS kullanmasını zorlayın.
# Example NGINX snippet
server {
    listen 80;
    server_name example.com www.example.com;
    return 301 https://$host$request_uri;
}
server {
    listen 443 ssl http2;
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    # TLS settings ...
}

Not: HSTS, sürüş (downgrade) saldırılarını ortadan kaldırır, ancak bir kez ayarlandığında tarayıcılar belirlenen süre boyunca HTTP üzerinden bağlanmayı reddeder; bu yüzden planlaması dikkat gerektirir.

1.2 Sertifika Sabitleme (Opsiyonel)

Bankacılık, sağlık kayıtları gibi son derece hassas PWAlar için Public Key Pinning Extension for HTTP (HPKP) aracılığıyla sertifika sabitlemeyi değerlendirin. HPKP dağıtım riskleri nedeniyle kullanım dışı bırakılıyor olsa da, benzer güvenliği Expect‑CT başlıklarıyla sağlayabilirsiniz.

Expect-CT: max-age=86400, enforce, report-uri="https://example.com/report"

2. Servis Çalışanı Sertleştirme

Servis çalışanları, bir PWA’nın çevrim‑dışı yeteneklerinin kalbidir. Arka planda yükseltilmiş yetkilerle çalışan bu iş parçacığı, saldırganlar için cazip bir hedef oluşturur.

2.1 Kapsamı Sınırlama

Servis çalışanı kaydederken mümkün olan en dar scope değerini belirleyin. Bu, çalışanın hedeflenen alan dışındaki istekleri yakalamasını önler.

navigator.serviceWorker.register('/sw.js', { scope: '/app/' })
  .then(reg => console.log('SW registered with scope:', reg.scope));

2.2 Alt Kaynak Bütünlüğü (SRI) ile Doğrulama

Servis çalışanı betiğini bir CDN üzerinden yüklüyorsanız, beklenen hash değeriyle eşleştiğini garantilemek için SRI kullanın.

<script src="https://cdn.example.com/sw.js"
        integrity="sha384-abc123..."
        crossorigin="anonymous"></script>

2.3 Servis Çalışanları İçin İçerik Güvenliği Politikası

Katı bir CSP, çalışanın kötü amaçlı betik yüklemesini veya istenmeyen origin’lere bağlanmasını engelleyebilir.

Content-Security-Policy: script-src 'self' https://trusted.cdn.com; 
                         connect-src 'self' https://api.example.com;

İpucu: Yeni tarayıcılarda worker-src yönergesini kullanarak çalışan betiği kaynaklarını açıkça beyaz listeye ekleyin.

2.4 Durum Yönetimi ve Önbellek Doğrulama

Önbellek girdilerine körü körüne güvenmeyin. Özellikle kimlik doğrulama token’ları veya kişisel veriler için önbellek yanıtının tazeliğini her zaman doğrulayın.

self.addEventListener('fetch', event => {
  const url = new URL(event.request.url);
  if (url.pathname.startsWith('/api/')) {
    // Dinamik veriler için önbelleği atla
    event.respondWith(fetch(event.request));
    return;
  }
  // Statik varlıklar için varsayılan cache‑first stratejisi
  event.respondWith(
    caches.match(event.request).then(cached => cached || fetch(event.request))
  );
});

3. Çalışma Zamanı Koruması – CSP, İzinler ve Sandbox

3.1 Tam Özellikli CSP

İyi tasarlanmış bir CSP, Cross‑Site Scripting (XSS) ve Data Injection saldırı risklerini azaltır. Aşağıdaki örnek politika tipik bir PWA için özelleştirilmiştir:

Content-Security-Policy:
  default-src 'self';
  script-src 'self' 'sha256-XYZ' https://analytics.example.com;
  style-src 'self' 'unsafe-inline';
  img-src 'self' data:;
  font-src 'self' https://fonts.gstatic.com;
  connect-src 'self' https://api.example.com wss://socket.example.com;
  frame-ancestors 'none';
  base-uri 'self';
  form-action 'self';
  • script-src satırında satır içi betikler için bir hash bulunur; bu sayede unsafe-inline kullanılmaz.
  • frame-ancestors 'none' clickjacking’i engeller.
  • connect-src API ve WebSocket uç noktalarını beyaz listeye alır.

3.2 İzinler Politikası (Eski Feature‑Policy)

PWA’nın istemeden miras alabileceği güçlü tarayıcı özelliklerini kısıtlayın.

Permissions-Policy: geolocation=(), microphone=(), camera=(), payment=()

3.3 Gömülü İçerik İçin Sandbox Özniteliği

PWA’nız üçüncü‑taraf iframe’ler barındırıyorsa, script çalıştırmayı ve yönlendirmeyi önlemek için sandbox’layın.

<iframe src="https://maps.example.com"
        sandbox="allow-scripts allow-same-origin"
        loading="lazy"></iframe>

4. Kimlik Doğrulama & Yetkilendirme

4.1 JWT ile Token‑Tabanlı Kimlik Doğrulama

Stateless kimlik doğrulama için JSON Web Token (JWT) kullanın, ancak bunları localStorage yerine Secure, HttpOnly çerezlerde saklayarak XSS çalınmasını önleyin.

Set-Cookie: token=eyJhbGciOi...; HttpOnly; Secure; SameSite=Strict; Path=/; Max-Age=3600

4.2 Refresh Token Döndürme

Kompromize olmuş bir token’ın zararını sınırlamak için dönen (rotating) refresh token’ları uygulayın.

  1. İstemci refresh token gönderir.
  2. Sunucu doğrular ve yeni bir erişim token’ı ve yeni bir refresh token verir.
  3. Eski refresh token veritabanında geçersiz kılınır.

4.3 CSRF Önleme

Aynı‑site çerezlerine rağmen, durum değiştiren POST istekleri için Anti‑CSRF tokenları kullanın.

<input type="hidden" name="csrf_token" value="{{ .CSRFToken }}">

Sunucu tarafında token’ın oturumla eşleştiğini kontrol edin.


5. Güvenli Veri Depolama

PWAlar, IndexedDB, Cache API ve Web Storage üzerinden veri depolayabilir. Her birinin kendine özgü güvenlik hususları vardır.

DepolamaUygunlukGüvenlik İpuçları
Cache APIStatik varlıklar, çevrim‑dışı yedekYalnızca değişmez kaynakları önbellekle. Sürüm‑isimli önbellekler kullanarak eski veriyi temizle.
IndexedDBYapılandırılmış veri, kullanıcı tercihleriHassas alanları istemci‑tarafında Web Crypto API ile şifrele.
LocalStorage / SessionStorageKüçük, hassas olmayan veriGizli bilgileri saklamaktan kaçının. Sayfadaki herhangi bir betik bu verilere erişebilir.

5.1 Örnek: IndexedDB Verisini Şifreleme

async function encryptAndStore(key, value) {
  const cryptoKey = await crypto.subtle.generateKey(
    { name: "AES-GCM", length: 256 },
    true,
    ["encrypt", "decrypt"]
  );
  const iv = crypto.getRandomValues(new Uint8Array(12));
  const encoded = new TextEncoder().encode(value);
  const ciphertext = await crypto.subtle.encrypt(
    { name: "AES-GCM", iv },
    cryptoKey,
    encoded
  );
  const db = await openDB('secure-store', 1, {
    upgrade(db) { db.createObjectStore('secrets'); }
  });
  await db.put('secrets', { iv, ciphertext }, key);
}

6. İzleme, Denetleme ve Olay Müdahalesi

Güvenlik tek seferlik bir yapılandırma değildir; devamlı bir döngüdür.

6.1 Otomatik Tarama

  • OWASP ZAP veya Burp Suite ile XSS, CSRF ve güvenlik başlığı eksikliklerini tarayın.
  • Lighthouse denetimlerini CI/CD boru hatlarına entegre ederek PWA uyumluluğunu zorunlu kılın.

6.2 Çalışma Zamanı Günlüğü

Servis‑worker hatalarını yakalayın ve analiz için güvenli bir uç noktaya gönderin.

self.addEventListener('error', event => {
  fetch('https://logs.example.com/collect', {
    method: 'POST',
    body: JSON.stringify({ message: event.message, stack: event.error.stack })
  });
});

6.3 Olay Yanıt Kılavuzu

  1. Tespit: Anormal trafik veya CSP ihlal raporları tarafından tetiklenen uyarı.
  2. İzolasyon: Kompromize olmuş JWT’leri iptal edin, API anahtarlarını döndürün.
  3. Kök Neden: Açık kodu yamalayın, servis‑worker önbelleğini güncelleyin.
  4. Kurtarma: Yeni sürümü dağıtın, tekrarı izleyin.
  5. Post‑mortem: Kök nedeni belgeleyin, güvenlik kontrol listesini güncelleyin.

7. Görsel Genel Bakış – Bir PWA’da Güvenlik Katmanları

  flowchart TB
    subgraph "Transport Layer"
        H["\"HTTPS\""]
        S["\"HSTS\""]
    end
    subgraph "Service Worker"
        SW["\"Scope Limitation\""]
        CS["\"Cache Validation\""]
    end
    subgraph "Runtime"
        CSP["\"Content Security Policy\""]
        PP["\"Permissions Policy\""]
        SAN["\"Sandboxed iFrames\""]
    end
    subgraph "Auth & Data"
        JWT["\"Secure Cookies\""]
        REF["\"Refresh Rotation\""]
        ENC["\"IndexedDB Encryption\""]
    end
    subgraph "Monitoring"
        SCAN["\"OWASP ZAP\""]
        LOG["\"Runtime Logging\""]
    end

    H --> SW --> CSP --> JWT --> SCAN
    S --> SW
    CS --> PP
    PP --> ENC
    LOG --> SCAN

Bu diyagram, her bir güvenlik kontrolünün bir öncekine nasıl inşa edildiğini ve savunma‑derinliği mimarisini gösterir.


8. Kontrol Listesi – Güvenli bir PWA İçin Hızlı Başvuru

  • Tüm içerik HTTPS üzerinden sunulmalı ve HSTS etkinleştirilmeli.
  • Servis çalışanları en dar kapsamla (scope) kaydedilmeli.
  • CDN üzerinden alınan servis çalışanı betikleri SRI ile korunmalı.
  • Katı bir CSP uygulanmalı; worker-src ve betik hash’leri eklenmeli.
  • Kullanılmayan tarayıcı özellikleri Permissions‑Policy ile devre dışı bırakılmalı.
  • Kimlik doğrulama token’ları Secure, HttpOnly çerezlerde saklanmalı; localStorage’da olmamalı.
  • Refresh token’lar döndürülmeli ve CSRF token’ları durum‑değiştirici isteklerde doğrulanmalı.
  • Hassas veriler IndexedDB’de şifrelenmeli.
  • Her PR’da otomatik OWASP ZAP taraması çalıştırılmalı.
  • Servis‑worker hatalarının gerçek‑zamanlı günlüğü ayarlanmalı.
  • Olay müdahale planı belgelenmiş ve güncel tutulmalı.

9. Sıkça Sorulan Sorular

S1: PWAlar için bir Servis Çalışanı mutlaka gerekli mi?
Hayır. HTTPS, CSP ve güvenli çerezler gibi güvenlik önlemleri bağımsız olarak çalışır. Ancak çalışma‑zamanı saldırıların çoğu servis çalışanında ortaya çıkar; bu yüzden ek sertleştirme önemlidir.

S2: CSP’de unsafe-inline stilleri kullanabilir miyim?
Mümkün olduğunca kaçının. Bunun yerine satır içi stiller için hash ya da nonce kullanın ya da stilleri harici CSS dosyalarına taşıyın.

S3: TLS sertifikalarını ne sıklıkta yenilemeliyim?
Let’s Encrypt 90‑günlük sertifikalar sunar; yenilemeyi otomatikleştirin. Kendinden imzalı ya da ticari sertifikalar için en fazla 1 yıl geçerlilik tavsiye edilir.


10. Sonuç

İlerleyici Web Uygulamaları, yerel ve web deneyimlerini birleştirerek güçlü yetenekler sunar; aynı zamanda saldırı yüzeyini de genişletir. Taşıma güvenliğini katmanlamak, servis‑worker kapsamını daraltmak, katı bir Content Security Policy uygulamak ve sağlam kimlik doğrulama uygulamaları benimsemek, performanstan ödün vermeden PWA’nızı korumanın anahtarıdır.

Unutmayın: güvenlik bir varış noktası değil, bir yolculuktur. Bağımlılıkları güncel tutun, kodunuzu düzenli olarak denetleyin ve yeni ortaya çıkan tehditlerden haberdar olun. Burada paylaşılan uygulamaları izlediğiniz sürece, PWA’nız yaygın web‑tabanlı saldırılara karşı dayanıklı olacaktır.


Bak Ayrıca

yukarı
© Scoutize Pty Ltd 2025. All Rights Reserved.