Sitemap

Flutter’da Güvenliğin Altın Kuralı: Cliente Asla Güvenme

6 min readJun 27, 2025

--

Merhaba değerli geliştirici arkadaşlar. Bu yazımda Cliente Asla Güvenme ilkesinden bahsediyor olacağız. Bu konu sadece Flutter geliştiricilerini değil bir çok geliştiriciyi kapsıyor ancak benim alanım Flutter olduğu için Flutter özelinde bu konuyu ele alıyor olacağım.

Cliente Asla Güvenme (Never Trust the Client), yazılım ve özellikle mobil uygulama geliştirmenin en temel ve en kritik güvenlik prensiplerinden biridir. Bu prensibi anlamak ve uygulamak, basit bir uygulamayı sağlam ve güvenilir bir sisteme dönüştüren en önemli adımdır.

Modern uygulama geliştirme dünyasında, özellikle Flutter gibi platformlar arası çözümlerle harika kullanıcı arayüzleri ve deneyimleri yaratmaya odaklanıyoruz. Ancak bu süreçte, genellikle göz ardı edilen ama felaketle sonuçlanabilecek bir gerçek vardır: Kullanıcının cihazında çalışan kod (yani client), tamamen düşman bir bölgededir. “Cliente Asla Güvenme” ilkesi, bu gerçeği kabul ederek güvenli, sağlam ve manipülasyona kapalı sistemler inşa etmenin temel felsefesidir.

Bölüm 1: Client Nedir ve Neden Güvenilmez?

Öncelikle “client” kavramını netleştirelim. Bir Flutter uygulaması bağlamında client, kullanıcının cep telefonunda, tabletinde veya masaüstünde çalışan derlenmiş uygulama kodunun tamamıdır. Bu, yazdığınız Dart kodunu, kullandığınız paketleri, yerel veritabanını (SQLite, Hive), paylaşılan tercihleri (SharedPreferences) ve uygulamanın bellekteki durumunu içerir.

Peki, neden kendi yazdığımız bu koda güvenemeyiz?

Cevap basit: Kod sizin bilgisayarınızda değil, kullanıcının kontrolündeki bir cihazda çalışıyor. Bu cihaz üzerinde sizin hiçbir kontrolünüz yoktur. Bir saldırgan veya kötü niyetli bir kullanıcı, bu ortamı çeşitli şekillerde manipüle edebilir:

  1. Tersine Mühendislik (Reverse Engineering): Derlenmiş APK (Android) veya IPA (iOS) dosyaları, uzmanlar tarafından analiz edilebilir. flutter build — obfuscate gibi komutlar bunu zorlaştırsa da imkansız hale getirmez. Saldırgan, kodunuzun mantığını, API endpoint’lerinizi ve kullandığınız şifreleme anahtarları gibi gömülü sırları keşfedebilir.
  2. Ağ Trafiğini İzleme ve Değiştirme (Man-in-the-Middle — MitM): Kullanıcı, cihazının ağ trafiğini bir proxy aracı (örneğin Burp Suite veya Charles) üzerinden geçirerek uygulamanızın sunucuya gönderdiği ve sunucudan aldığı tüm istekleri görebilir, analiz edebilir ve hatta değiştirebilir. SSL/TLS şifrelemesi bunu engeller gibi görünse de, kullanıcı kendi cihazına özel bir sertifika yükleyerek bu trafiği de deşifre edebilir. Bu konuda yazdığım ilgili makaleye buraya tıklayarak erişebilirsiniz
  3. Root’lu veya Jailbreak’li Cihazlar: Bu tür cihazlarda kullanıcı, işletim sisteminin en derin katmanlarına kadar erişim hakkına sahiptir. Uygulamanızın korumalı alanını (sandbox) aşabilir, bellekteki verileri okuyup değiştirebilir ve yerel olarak depoladığınız her dosyaya erişebilirler.
  4. Uygulama Klonlama ve Modifikasyonu: Saldırgan, uygulamanızın paketini açıp, kodunu değiştirip (örneğin, premium özellikleri ücretsiz yapacak şekilde) yeniden paketleyerek dağıtabilir.

Bu dört temel tehdit, client tarafında alınan hiçbir kararın veya tutulan hiçbir verinin %100 güvenilir olamayacağını kanıtlar.

Bölüm 2: Yaygın Hatalar ve Gerçek Dünya Senaryoları

Teoriyi anladıktan sonra, bu ilkenin ihlal edildiği pratik senaryolara bakalım. Bu hatalar, birçok uygulamanın güvenlik açığına sebep olur.

Senaryo 1: Fiyat ve Satın Alma Mantığının Client’ta Olması

Bir e-ticaret uygulamasında, kullanıcı sepete bir ürün ekliyor. Ürünün fiyatı 100 TL.

  • Yanlış Yaklaşım (Cliente Güvenen): Flutter uygulaması, ödeme butonuna basıldığında sunucuya şöyle bir istek gönderir: POST /api/purchase ile birlikte {“user_id”: 123, “product_id”: “XYZ”, “price”: 100.00}.
  • Risk: Kötü niyetli bir kullanıcı, ağ trafiğini izleyerek bu isteği yakalar ve price değerini 1.00 olarak değiştirip sunucuya gönderir. Eğer sunucu bu fiyatı sorgulamadan kabul ederse, 100 TL’lik ürünü 1 TL’ye satmış olursunuz.
  • Doğru Yaklaşım (Cliente Güvenmeyen): Flutter uygulaması sunucuya sadece alınmak istenen ürünün ID’sini ve miktarını gönderir: POST /api/purchase ile {“user_id”: 123, “product_id”: “XYZ”, “quantity”: 1}. Sunucu, kendi veritabanından product_id’si “XYZ” olan ürünün fiyatını kontrol eder, ödemeyi bu fiyata göre başlatır ve tüm hesaplamayı kendisi yapar. Client’tan gelen fiyata asla itibar etmez.

Senaryo 2: Kullanıcı Yetkilendirmesinin Client’ta Yönetilmesi

Kullanıcı giriş yaptığında, sunucu kullanıcı bilgilerini döner.

  • Yanlış Yaklaşım: Sunucu, {“username”: “test”, “is_admin”: true} gibi bir yanıt döner. Flutter uygulaması bu is_admin değerini SharedPreferences’e kaydeder ve admin paneli butonunu bu değişkene göre gösterir/gizler.
  • Risk: Root’lu bir cihazda kullanıcı, SharedPreferences dosyasını düzenleyerek is_admin değerini true yapabilir ve admin paneline erişebilir. Daha da kötüsü, admin paneline giden API isteklerini keşfedip doğrudan bu istekleri gönderebilir.
  • Doğru Yaklaşım: Client’ta is_admin gibi bir bayrak tutmak sadece UI kolaylığı içindir, güvenlik için değildir. Asıl güvenlik, sunucu tarafındadır. Admin paneline erişim gerektiren her bir API isteği (/api/admin/deleteUser gibi), kullanıcının token’ını içermelidir. Sunucu, bu token’ı alır, veritabanından kullanıcının gerçekten admin olup olmadığını her istekte yeniden kontrol eder ve ancak yetkisi varsa işlemi gerçekleştirir. Client’ın “ben adminim” demesine asla inanmaz.

Senaryo 3: Client-Side Form Doğrulamasına Aşırı Güvenmek

Kayıt formunda e-posta formatı, şifre uzunluğu gibi doğrulamalar yapıyorsunuz.

  • Yanlış Yaklaşım: Sadece Flutter tarafında validator fonksiyonları ile kontrol yapmak ve sunucunun gelen veriyi olduğu gibi kabul ettiğini varsaymak.
  • Risk: Bir saldırgan, Postman gibi bir araçla uygulamanızın UI’ını tamamen atlayarak doğrudan kayıt API’nıza geçersiz verilerle (örneğin, SQL Injection saldırısı içeren bir kullanıcı adı ile) istek gönderebilir.
  • Doğru Yaklaşım: Client-side doğrulama, sadece kullanıcı deneyimini (UX) iyileştirmek için yapılır. Kullanıcıya anında geri bildirim vererek zaman kazandırır. Ancak asıl ve nihai doğrulama, her zaman sunucu tarafında yeniden yapılmalıdır. E-posta formatı, veri tipleri, uzunluk kısıtları ve diğer tüm iş kuralları sunucuda tekrar kontrol edilmelidir.

Bölüm 3: Flutter’da Savunmayı Güçlendirme Stratejileri (Defense in Depth)

“Cliente Asla Güvenme” ilkesinin temeli sunucuya dayansa da, bu Flutter tarafında hiçbir şey yapmayacağımız anlamına gelmez. Defense in Depth (Derinlemesine Savunma) prensibi, saldırganın işini zorlaştırmak için client tarafında da bir dizi önlem almayı gerektirir. Bunlar sunucu güvenliğinin yerini tutmaz ama caydırıcı bir katman oluşturur.

  1. Kod Gizleme (Obfuscation):
    Uygulamanızı flutter build apk — obfuscate — split-debug-info=/<project-name>/<directory> komutuyla derlemek, Dart kodunuzdaki sınıf, metot ve değişken adlarını anlamsız karakterlerle değiştirir. Bu, tersine mühendislik sürecini önemli ölçüde zorlaştırır.
  2. SSL Pinning (Sertifika Sabitleme):
    Saldırganların MitM saldırıları yapmasını engellemenin en etkili yollarından biridir. SSL Pinning ile uygulamanız, sadece sizin belirlediğiniz sunucunun SSL sertifikasına veya public key’ine güvenir. Saldırgan, kendi sahte sertifikasını cihaza yüklese bile, uygulamanız bu sertifikayı tanımayacağı için bağlantı kurmaz. http_certificate_pinning gibi paketler bu konuda yardımcı olabilir. Ayrıca bu konuyu ele aldığım makaleye buraya tıklayarak erişebilirsiniz
  3. Root ve Jailbreak Tespiti:
    flutter_jailbreak_detection gibi paketler kullanarak uygulamanızın root’lu veya jailbreak’li bir cihazda çalışıp çalışmadığını tespit edebilirsiniz. Tespit durumunda, uygulamayı kapatabilir veya kritik özellikleri devre dışı bırakabilirsiniz. Bu %100 garantili bir yöntem değildir çünkü bu tespit mekanizmaları da atlatılabilir, ancak yine de ek bir güvenlik katmanıdır.
  4. Güvenli Yerel Depolama:
    Kullanıcının token’ı gibi hassas verileri SharedPreferences içinde saklamak son derece tehlikelidir. Bu veriler düz metin olarak saklanır. Bunun yerine, iOS için Keychain ve Android için Keystore kullanan flutter_secure_storage paketini kullanmalısınız. Bu, verilerin donanım destekli şifrelenmiş bir alanda saklanmasını sağlar.
  5. API Anahtarları ve Sırlar:
    Kodunuzun içine asla hassas API anahtarları veya şifreler gömmeyin. Bunlar tersine mühendislikle kolayca bulunabilir.
  • Minimum Çözüm: .env dosyaları ve flutter_dotenv paketi kullanmak. Ancak bu sadece geliştirme sürecini kolaylaştırır, derlenmiş kodda anahtarlar yine görünür olacaktır.
  • Daha İyi Çözüm: Hassas anahtar gerektiren işlemleri (örneğin, bir ödeme sağlayıcısı ile iletişim) doğrudan client’tan yapmak yerine, bu işlemi sizin kontrolünüzdeki bir ara sunucu (proxy/backend) üzerinden yapın. Client sizin sunucunuza istek atar, sizin sunucunuz gizli anahtarı kullanarak asıl servise gider. Ancak her uygulamada proxy ya da backend kullanılmayabiliyor. Bu konuda env çözümünden çok daha iyi olduğunu düşündüğüm çözümü buraya tıklayarak okuyabilirsiniz

Değerli arkadaşlar biliyoruz ki Flutter, harika kullanıcı deneyimleri yaratmak için mükemmel bir araçtır. Client tarafı, kullanıcıya hızlı geri bildirimler vermek, verileri güzelce göstermek ve geçici durumları yönetmek için vardır. Ancak otorite, doğruluk ve güvenlik kaynağı her zaman ve istisnasız olarak sunucu olmalıdır. Bu altın kuralı benimsediğinizde, sadece güzel görünen değil, aynı zamanda sağlam, güvenilir ve saldırılara karşı dirençli uygulamalar inşa edersiniz.

Güvenlik kavramını internete açılmış, internet üzerinden alış veriş yapan uygulamalarınızda oturtmanız sadece sizin değil aynı zamanda uygulamanızı kullanan kişilerinde faydasına olacağından bu kavramada en az etkileyici arayüzler oluşturmak kadar önem vermenizi tavsiye ediyorum.

Bu yazımda elimden geldiğince sizlere Flutter’da Cliente Asla Güvenme ilkesini nasıl ele alabileceğimizi anlatmaya çalıştım. Umarım ilgilisi ve meraklısı için faydalı olur. Sonraki yazılarda görüşmek üzere..

Github: www.github.com/abdullah017
Linkedin: www.linkedin.com/in/abdullahtas
Stackoverflow:
https://stackoverflow.com/users/13807726/abdullah-t

--

--

AbdullahTaş
AbdullahTaş

Written by AbdullahTaş

FLUTTER DEVELOPER AT IWWOMI | HASURA-GRAPHQL & FIREBASE |

No responses yet