Personel Paneli Güvenliği: Giriş, Roller, CSRF ve Denetim Kaydı Pratikte Nasıl Çalıştı?
Bir otel personel takip panelinde parola saklama, oturum, CSRF koruması, rol ve bölüm yetkisi ile denetim kaydının nasıl kurulduğunu ve sahada hangi hataları yakaladığını anlatan proje notu.
Personel giriş-çıkış verisi hassas bir veridir: kim ne zaman işte, kim izinde, kim geç kaldı. Bu yüzden panelin güvenliğini sonradan eklenecek bir özellik olarak değil, baştan tasarım kararı olarak ele aldık. Bu not, bir otel için kurduğumuz Flask panelinde hangi katmanları kullandığımızı, her birinin hangi riske karşı olduğunu ve sahada bizi şaşırtan durumları anlatıyor. Genel kurulum adımları için Flask güvenli giriş rehberine bakabilirsiniz; burada o rehberdeki fikirlerin gerçek bir projede nasıl davrandığına odaklanıyoruz.
Katman 1: Ağ — panel internete açık değil
İlk savunma, saldırganın panele hiç ulaşamamasıdır. Pi'nin doğrudan internetten erişilebilir bir portu yok; dış erişim Cloudflare Tunnel üzerinden. Cihazın kendi güvenlik duvarı (UFW rehberi) yalnızca yerel ağdan SSH ve panel portuna izin veriyor; SSH tarafında parola girişi kapalı, anahtar zorunlu, tekrarlayan denemeler fail2ban ile engelleniyor. Tüneli kuranların sık düştüğü tuzak, tüneli tek başına yeterli sanmaktır; tünel yalnızca "kapıyı" saklar, içeri giren herkesin kim olduğunu ayrıca sormak gerekir.
Katman 2: Parola ve oturum
- Parolalar düz metin saklanmaz. Her kullanıcı için tuzlu ve yavaş bir özet (hash) tutulur; veritabanı sızsa bile parolalar doğrudan okunamaz.
- Başarısız girişler sınırlanır. Aynı kullanıcı adı ya da adresten kısa sürede çok sayıda hatalı deneme yapılırsa bir süre bekletilir. Bu, deneme-yanılmayı pratikte işe yaramaz kılar.
- Hata mesajı sızdırmaz. "Kullanıcı bulunamadı" ile "parola yanlış" ayrımı yapılmaz; ikisi de "kullanıcı adı veya parola hatalı" der. Böylece geçerli kullanıcı adları keşfedilemez.
- Oturum çerezi güvenli işaretlenir. Yalnızca HTTPS üzerinden gönderilir, JavaScript tarafından okunamaz ve başka sitelerden gelen isteklerde gönderilmez. Oturum süresi sınırlıdır; unutulan açık bir ekran sonsuza kadar açık kalmaz.
- Gizli anahtar koda gömülmez. Oturum imzalama anahtarı ortam değişkeninden gelir; kod depoya konsa bile anahtar sızmaz.
Katman 3: CSRF — "kullanıcı farkında olmadan" yapılan istekler
Müdür panele giriş yapmışken kötü niyetli bir sayfayı açarsa, o sayfa tarayıcıyı kullanarak panele "şu personeli sil" gibi bir istek gönderebilir; çerez otomatik eklendiği için istek meşru görünür. Buna CSRF denir. Önlem: durumu değiştiren her istek (POST) formda gizli, kullanıcıya özel, tahmin edilemez bir jeton taşımak zorundadır; sunucu jeton eşleşmezse isteği reddeder. Flask'te bunu her forma tek tek yazmak yerine uygulama genelinde zorunlu kıldık: jetonsuz hiçbir POST kabul edilmez. Bu, yeni eklenen bir formda geliştiricinin korumayı unutmasını imkânsız hale getirdi.
Sahada şaşırtıcı bir yan etkisi oldu: sayfa uzun süre açık kalıp jeton süresi dolunca kullanıcı "form çalışmıyor" diye bildirdi. Çözüm, hata mesajını "oturum süresi doldu, sayfayı yenileyin" diye anlaşılır hale getirmek oldu; güvenlik mesajları da kullanıcı deneyiminin parçasıdır.
Katman 4: Rol ve bölüm yetkisi
Üç rol, iki sınır: yönetici her şeyi yapar, insan kaynakları her bölümü görür ama ayar değiştiremez, bölüm müdürü yalnızca kendi bölümünü görür. Kritik karar, bu kuralın tek bir noktada uygulanması: müdür rolüyle yapılan her veritabanı sorgusuna bölüm koşulu otomatik eklenir. Böylece yeni bir rapor eklendiğinde geliştirici bölüm filtresini unutsa bile müdür başka bölümün verisini göremez. İkinci güvence bir izin listesi: müdürün açabileceği sayfalar açıkça listelenir, listede olmayan her sayfa kapalıdır. Yeni bir Excel indirmesi eklediğimizde listeye eklemeyi unuttuk ve müdürler "erişim yok" gördü; sinir bozucu ama doğru yönde bir hata. "Önce kapalı, sonra tek tek aç" yaklaşımının bedeli birkaç şikâyet, tersinin bedeli veri sızıntısıdır.
Bir de doğrudan nesne erişimi riski var: müdür adres satırındaki kişi numarasını değiştirip başka bölümün personelinin kartını açmayı deneyebilir. Bölüm filtresi sorgu seviyesinde çalıştığı için bu denemede kayıt "bulunamadı" döner; sayfa 404 verir, kayıt var mı yok mu bile belli etmez.
Katman 5: Denetim kaydı
Kim neyi ne zaman değiştirdi? Bu sorunun cevabı olmayan bir sistem, bir anlaşmazlıkta işe yaramaz. Bu yüzden her yönetsel işlem (personel ekleme, kart atama, izin girme, ayar değişikliği, rapor indirme) bir denetim kaydına yazılır: kullanıcı, zaman, işlem ve etkilenen kayıt. Denetim kaydı uygulama tarafından silinemez ve düzenlenemez, yalnızca eklenir. İlk haftalarda bu kayıt, "o kaydı kim değiştirdi" tartışmalarını tek bakışta kapattı ve ekibe sistemin adil olduğu hissini verdi; kayıtlar yalnızca suçlu aramak için değil, yanlış anlamaları çözmek için de değerlidir.
Denetim kaydında parola, jeton ya da kart numarasının tamamı gibi hassas veri tutulmaz. Kayıt, sızarsa yeni bir risk yaratmamalı.
Katman 6: Yedek ve geri dönüş
Güvenlik yalnızca saldırıyı engellemek değil, kötü bir gün sonrasında toparlanabilmektir. Veritabanı her gece yedeklenir ve başka bir makineye kopyalanır; 3-2-1 kuralı uyarınca en az bir kopya cihazdan ve binadan uzaktadır. Her kod güncellemesinden önce uygulama dosyalarının tarihli bir yedeği alınır ve bir şey ters giderse tek komutla eski sürüme dönülür. Bu alışkanlık, bir güncellemede şablon hatası yüzünden panelin açılmadığı gün birkaç dakikada telafi edildi.
Sahada gördüklerimiz
- En büyük risk teknik değil, insan. İlk iki ayda en sık rastlanan sorun parola paylaşımıydı: bir müdür parolasını yardımcısına verdi. Bunun üzerine her kişiye ayrı hesap açıp denetim kaydını gösterdik; parola paylaşımı kendiliğinden azaldı.
- Basit kurallar karmaşık olanlardan iyi. Çok sayıda ince yetki yerine üç net rol, anlaşılmayan bir matris yerine herkesin söyleyebildiği bir kural yarattı.
- Hatalar sessizce başarısız olmamalı. Yetkisiz bir erişim denemesi günlüğe yazılır; olağan dışı sayıda reddedilen istek varsa uyarı gelir.
- Güncellemeleri ertelemek riski büyütür. Sistem paketleri ve Python kütüphaneleri düzenli güncellenir; güncelleme öncesi yedek, sonrası kısa bir duman testi yapılır.
Kontrol listesi
- Panel internete doğrudan açık değil mi? Tünel ya da VPN arkasında mı?
- Parolalar yavaş bir özetle mi saklanıyor? Hatalı giriş sınırı var mı?
- Her POST jeton (CSRF) istiyor mu?
- Yetki kuralı sorgu seviyesinde mi, yoksa her sayfaya elle mi yazılmış?
- Yeni sayfalar varsayılan olarak kapalı mı?
- Yönetsel işlemler değiştirilemez bir denetim kaydına yazılıyor mu?
- Yedekten geri yükleme son üç ay içinde denendi mi?
Veri koruma boyutunu (aydınlatma metni, saklama süresi, erişim hakkı) ayrı bir yazıda ele aldık: personel giriş-çıkış verisi ve KVKK.