Ctrl K
ComunidadGuías…

docs/SECURITY_REVIEW_2026-10-13.md

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# Güvenlik İncelemesi — 2026-10-13

Kapsam: `main` @ `7798270` (PR #105 dahil): web uygulaması ve API rotaları,
ws-gateway, plugin worker sandbox'ı, etkinlikler ve eklenti etkileri
(zamanlayıcı, depo, uygulama mesajı), botlar ve webhook'lar, pazar yeri
kurulumu ve çerçeve (aşama 1–3), resmi hub, Tauri masaüstü, Docker / nginx /
coturn / LiveKit, `install.sh`, `lfctl` ve CI.

Önceki incelemeden (2026-10-03, [SECURITY_REVIEW_2026-10.md](SECURITY_REVIEW_2026-10.md))
bu yana gelenler özellikle incelendi:

- Bot API v2 ve olay akışı;
- pazar yeri sandbox'ı ve eklenti kilidini açma aşamaları 1–3;
- CAPTCHA ve e-posta doğrulama;
- sohbet anketleri;
- hesap dili;
- kopma dayanıklılığı (P0).

**Yöntem:**

- **Altı salt-okunur inceleyici:**
  - kimlik doğrulama;
  - yetkilendirme ve topluluk;
  - botlar;
  - etkinlikler ve gerçek zamanlı akış;
  - pazar yeri ve sandbox;
  - yükleme, altyapı, masaüstü, CI ve hub.
- Hepsi `security-review` becerisinin kuralıyla çalıştı. Saldırgan girdisi
  uçtan uca izlendi; yalnızca **yüksek güvenli** bulgular raporlandı.
- Emin olunamayanlar "doğrulanmalı" diye ayrıldı.
- Önceki raporun §12'de düzeltildi denen maddeleri yeniden kontrol edildi.
  Hiçbiri geri gelmemiş.
- Her bulgu düzeltilirken koda karşı yeniden doğrulandı.

## 1. Karar

**Kritik ya da yüksek önemde açık yok.** Bulgular çoğunlukla:

- servis dışı bırakma (DoS);
- yetki sınırlarında ince boşluklar;
- sertleştirme.

İnceleme bir de **işlevsel bir hata** çıkardı: giriş yapan kullanıcı bir
saat sonra oturumdan düşüyordu (§3). O da düzeltildi.

| Önem | Sayı | Bulgular |
|---|---|---|
| Kritik | 0 | — |
| Yüksek | 0 | — |
| Orta | 7 | BOT-001 (= AUTHZ-007), BOT-002, BOT-003, PLUG-001, PLUG-002, FILE-001, AUTHZ-008 |
| Düşük | 11 | BOT-004, PLUG-003, PLUG-004, AUTHZ-009, AUTHZ-010, ACT-001, ACT-002, AUTH-001 (= INFRA-V-02), DESK-V-01, FILE-V-01, HUB-V-01 |

## 2. Bulgular

| ID | Önem | Bulgu | Düzeltme |
|---|---|---|---|
| BOT-001 / AUTHZ-007 | Orta | "Topluluğu yönet" yetkisi olup "kanalları yönet" yetkisi olmayan biri, gizli (rolle kapalı) bir kanala erişimi olan botun token'ını yenileyip o kanalı okuyabiliyor ve oraya yazabiliyor | #112 |
| BOT-002 | Orta | Sızan bir token yenilense ya da iptal edilse bile saldırganın kaydettiği olay adresi çalışmaya devam ediyor; senkron etkileşim cevabıyla bot adına yazabiliyor | #112 |
| BOT-003 | Orta (resmi hub) | Bot olay teslim kuyruğunda bot başına adalet yok; yavaş ama başarılı cevap veren adresler diğer kiracıların teslimlerini düşürtüyor | #112 |
| PLUG-001 | Orta | İnceleme anında paket sınırsız açılıyor (gzip bombası); web süreci bellek yüzünden düşebiliyor | #112 |
| PLUG-002 | Orta | Herkese açık eklenti dosya rotası her istekte paketi yeniden doğruluyor ve dosyayı baştan sona belleğe okuyor; hız sınırı yok | #112 |
| FILE-001 | Orta | Misafir hesaplar (IP başına saatte 10) her biri ~14 MiB resim saklayabiliyor; kurulum geneli üst sınır yok; disk dolabiliyor | #112 |
| AUTHZ-008 | Orta | Üyeler her mesaja ~1 MB'a kadar keyfi `metadata` ekleyebiliyor (depo, bant genişliği, bellek DoS) | #112 |
| BOT-004 | Düşük | Olay adresi kaydında çözümleyici hatası iç IP ve ana bilgisayar adlarını yansıtıyor | #112 |
| PLUG-003 | Düşük | Tar ön taraması GNU tar'dan farklı sınırlar okuyabiliyor (sağlama toplamı yok, gevşek sayı ayrıştırma) | #112 |
| PLUG-004 | Düşük | "Çerçevenin ağı yok" iddiası CSP ile sağlanamıyor (WebRTC kapsam dışı) | #112 |
| AUTHZ-009 | Düşük | Engellemeler canlı sohbette uygulanmıyor (bildirimler dahil) | #112 |
| AUTHZ-010 | Düşük | Denetim kaydı davet kodlarını ve gizli kanal ayrıntılarını denetim kaydı yetkisi olanlara gösteriyor | #112 |
| ACT-001 | Düşük | Kullanılmayan SSE akışı, iptal edilmiş oturumu ilk 30 sn kabul ediyor | #112 |
| ACT-002 | Düşük | Bir eylem, vadesi gelmiş bir zamanlayıcının önüne geçebiliyor | #112 |
| AUTH-001 / INFRA-V-02 | Düşük | Geliştirme stack'i herkesin bildiği oturum sırrıyla tüm arayüzlerde açılıyor; uygulama yer tutucu sırları kabul ediyor | #112 |
| DESK-V-01 | Düşük | Masaüstü pencere, bağlanılan kurulumun dışına (her adrese) götürülebiliyor | #112 |
| FILE-V-01 | Düşük | GIF doğrulaması yalnız mantıksal ekran boyutuna bakıyor; büyük bir kare tarayıcıyı kilitleyebilir | #112 |
| HUB-V-01 | Düşük | Eklenti dosyaları `Vary`'yi yok sayan bir CDN'de (Cloudflare) uygulamanın kendi kökeninde önbelleğe girebilir | #112 |

**"Doğrulanmalı" listesinden düzeltilenler:**

- **Yetkilendirme:**
  - Rol silme hatası gizli kanalların adını veriyordu.
  - `@everyone`'ın sırası değiştirilebiliyordu.
  - Sohbet aboneliği mesaj geçmişi yetkisi istemiyordu.
  - Ortak sunucu olmadan DM açılabiliyordu; bilinmeyen kullanıcı 500 dönüyordu.
  - Yazıyor göstergesi engellemelere ve gizliliğe bakmıyordu.
  - Susturulmuş biri moderasyon yapabiliyordu.
- **Etkinlikler:**
  - Susturulmuş biri etkinliğe katılabiliyordu.
  - Kaldırılan uygulamanın oturumları sürüyordu.
  - Uygulama mesajı sınırı oturum başınaydı.
  - Zamanlayıcı birikmesi artış yaratıyordu.
  - Panel takılı vadeler yüzünden sürekli yeniden okuyordu.
  - Gizli kanala uygulama mesajı gönderilebiliyordu.
- **Botlar:** Yeniden denemeler yetkiyi yeniden kontrol etmiyordu; DNS iş parçacığı havuzu tıkanabiliyordu.
- **Eklentiler:**
  - Resmî eklenti adlarıyla pazar yeri paketi kurulabiliyordu.
  - İnceleme onayı sürüme bağlı değildi.
  - Manifest okuma sınırı sonradan uygulanıyordu.
- **Kimlik doğrulama:** Google giriş durumu çerezi `__Host-` önekini almadı; profil adı kontrol karakterlerini kabul ediyordu.
- **Masaüstü:** Giriş devri `'*'` hedefine mesaj gönderiyordu.

## 3. İşlevsel hata: oturum bir saatte bitiyordu

Oturum çerezi bir saat geçerliydi ve geçerli bir çerezi hiçbir şey
yenilemiyordu. `POST /api/auth/guest` yalnızca çerez zaten yokken
çağrılıyordu.

Sonuç olarak giriş yapan kullanıcı, ne kadar etkin olursa olsun, bir saat
sonra oturumdan düşüyordu. Misafir de kimliğini kaybediyordu.

Düzeltme (#108): **kayan oturum.**

- Çerez istek gelmeden 7 gün geçerli.
- Her API isteği (iptal kontrolünden sonra) ve her sayfa yüklemesi,
  ömrünün yarısı geçmiş geçerli bir çerezi aynı oturum kimliği ve
  `auth_time` ile yeniden imzalıyor.
- 30 günlük kesin ömür ve sunucu tarafı oturum iptali değişmedi.

## 4. Bilerek bırakılanlar

- **Bilinçli davranış:**
  - **Bot token'ları veren kişinin yetki kaybından sonra da geçerli kalıyor.**
    Discord'da da böyle; belgelendi.
  - **`member_leave.reason` (atma/ban), üye okuma yetkisi olan botlara gidiyor.**
    Belgelendi.
- **Dağıtım ayarına bağlı:**
  - **`LOBBYFORGE_TRUSTED_PROXY=cloudflare`:** Cloudflare arkasında değilken
    istemci kendi hız sınırı anahtarını seçebiliyor. Doctor bunu anlatıyor
    (önceki AUTH-V-01).
  - **Resmi hub'ın üst alan adının güvenilmeyen kardeş alt alan adları varsa**
    `lf_guest` çerezine de `__Host-` öneki gerekir. Bu, herkesin oturumunu
    kapatan bir değişiklik olduğu için ayrı planlanacak.
  - **IPv6:** Varsayılan Docker'da IPv6 istemcileri köprü ağ geçidi adresiyle
    görünebilir ve hız sınırlarını paylaşır. Doctor uyarısı ve dağıtım belgesi
    eklendi (#112); kalıcı çözüm, uç ağda IPv6'yı açmak.
- **Önceki incelemeden açık kalanlar:**
  - plugin worker'ın aynı UID ile çalışması (ADR-001);
  - `style-src 'unsafe-inline'`;
  - `braces` güvenlik bildirimi. Yalnız ESLint zincirinde, production imajında
    yok ve yaması yok.

## 5. Kontrol edilen ve sağlam bulunanlar (özet)

Her inceleyicinin "sağlam" listesi ayrıntılıdır; öne çıkanlar:

- **Oturum çerezi ve CSRF:**
  - HMAC, sabit zamanlı karşılaştırma.
  - Her girişte yeni oturum kimliği.
  - İptal kontrolü API'de, sayfalarda ve gateway'de.
  - Her değiştirici istekte köken denetimi.
- **Şifreler, sıfırlama ve doğrulama:**
  - Şifreler scrypt ile saklanıyor.
  - Hesap kilidi atomik.
  - Sıfırlama ve doğrulama belirteçleri 256 bit; tüketme tek bir koşullu UPDATE ile yapılıyor.
  - OAuth yönlendirmesi temizleniyor.
- **Yetkilendirme:**
  - Rol yükseltme kuralları ve moderasyon hiyerarşisi uygulanıyor.
  - Sunucular arası IDOR yok.
  - İstemci sunucuya ait `metadata` anahtarlarını taklit edemiyor.
  - `dangerouslySetInnerHTML` kullanılmıyor.
- **Botlar:**
  - Token 256 bit, karma ile saklanıyor.
  - Kanal erişimi tek kuralda.
  - Gateway içeriği veritabanından yeniden yüklüyor.
  - SSRF engelleri (IP sabitleme, tüm özel aralıklar, yönlendirme yok) yerinde.
  - İmza HMAC; webhook token'ları karma ile saklanıyor.
- **Etkinlikler:**
  - İstemci sistem eylemi ve etki gönderemiyor.
  - Etkiler izin ve sınırla doğrulanıyor.
  - Depo anahtar alanı sunucu tarafından belirleniyor.
  - Gizli durum her yolda izleyici başına projekte ediliyor.
  - LiveKit token'ı en dar yetkiyle veriliyor.
- **Pazar yeri:**
  - Onay istenenle birebir eşleşmeli.
  - Tarayıcı çerçevesi kendi kökeni dışına çıkamıyor (kaçış yok).
  - Worker RPC'si sabit zamanlı token ve özet (digest) ile korunuyor.
  - Dış arayüzün kökeni uygulamanınkinden farklı olmak zorunda.
- **Altyapı:**
  - Production compose iç servisleri yayınlamıyor.
  - Güncelleme Ed25519 imzalı; sürüm düşürme engelli.
  - Yedekler 0600.
  - CI'da aksiyonlar SHA ile sabitli; enjeksiyon yok.
  - Tauri IPC uzak sayfalardan erişilemiyor.

## 6. Düzeltme durumu

Bulguların hepsi düzeltildi ve `main`'e birleşti. Her alanın düzeltmesi kendi
commit'inde; testleri ve ayrıntıları özgün PR'larda duruyor (#107, #109, #110,
#111 ve `fix/sec-infra`). Tek bir CI turundan geçmeleri için #112'de
birleştirildiler.

| PR | Kapsam | Durum |
|---|---|---|
| #106 | Bağımlılıklar: Next 16.4, ioredis 6, TypeScript 6; `middleware.ts` → `proxy.ts`. Next 16.4'ün katı rota denetimi gerçek bir hata buldu: `/admin` ve bilinmeyen alt adresler doğrudan açılınca 404 veriyordu. ioredis 6'nın üstel yeniden bağlanma beklemesi, Redis kapalıyken komutları ~70 sn bekletiyordu; eski bekleme geri kondu | birleşti |
| #108 | Kayan oturum (§3), Google giriş durum çerezi (`__Host-`), profil adında kontrol karakterleri, Hushle `set-explainer` niyet anahtarı, ses yeniden bağlanma sınırı | birleşti |
| #112 | Alan 2–6'nın düzeltmeleri: pazar yeri ve sandbox, etkinlikler ve eklenti etkileri, botlar ve webhook'lar, yetkilendirme ve gizlilik, yükleme, altyapı ve masaüstü | birleşti (20/20 CI) |

**Yükseltme notu:** Yayımlanmış bir yer tutucu oturum sırrıyla çalışan kurulum
artık başlamaz (`requireSessionSecret`). Gerçek bir sır gerekir; sırrı
değiştirmek herkesin oturumunu kapatır.