Hardcoded Secrets

Hardcoded Secrets : Mobil uygulama geliştirme süreçlerinin hızı, bazen güvenliğin ihmal edilmesine neden olabilir. Geliştiricilerin test süreçlerini hızlandırmak veya “daha sonra düzeltirim” düşüncesiyle yaptıkları en kritik hatalardan biri, API anahtarlarını, veritabanı şifrelerini veya özel token’ları doğrudan kaynak kodun içine gömmektir. Siber güvenlik terminolojisinde “Hardcoded Secrets” olarak adlandırılan bu zafiyet, bir uygulamanın tamamen ele geçirilmesine neden olabilir.

Bu makalede, bu kritik zafiyetin neden oluştuğunu, saldırganların bunu nasıl tespit ettiğini ve Android NDK kullanarak nasıl daha güvenli hale getirileceğini teknik kod örnekleriyle inceleyeceğiz.

Hardcoded Secrets Nedir ve Neden Tehlikelidir?

Modern mobil uygulamalar; bulut sunucuları, ödeme sistemleri ve üçüncü parti servislerle (Google Maps, AWS, Firebase vb.) sürekli iletişim halindedir. Bu iletişim için kimlik doğrulama anahtarları (API Keys) gerekir. Eğer bir geliştirici, bu anahtarı String apiKey = "AIzaSy..." şeklinde kodun içine yazarsa, uygulamanın güvenliğini tersine mühendislik (reverse engineering) saldırılarına karşı savunmasız bırakmış olur.

OWASP Mobile Top 10 listesinde genellikle “Insecure Data Storage” veya “Extraneous Functionality” başlıkları altında değerlendirilen bu durum, saldırganın şunları yapmasına olanak tanır:

  • Şirketinizin bulut hesabını ele geçirip binlerce dolarlık sunucu faturası çıkarabilir.

  • Kullanıcı veritabanına erişip hassas verileri çalabilir (Data Breach).

  • Uygulamanızı klonlayıp içine zararlı yazılım enjekte edebilir.

Daha fazla bilgi için OWASP Mobile Top 10 projesini inceleyebilirsiniz.

Saldırı Senaryosu: Bir Hacker Kodunuzu Nasıl Görür?

Birçok geliştirici, uygulamanın .apk veya .ipa dosyasına dönüştürüldüğünde kodların gizlendiğini sanır. Oysa ki Java/Kotlin tabanlı Android uygulamaları, JADX veya APKTool gibi araçlarla saniyeler içinde kaynak koduna geri döndürülebilir.

Zafiyet İçeren Kod Örneği (Kotlin)

Aşağıdaki kod bloğu, tipik bir güvensiz geliştirme örneğidir:

Bir saldırgan, jadx-gui uygulamaniz.apk komutunu çalıştırdığında yukarıdaki kodu neredeyse birebir aynı şekilde görecektir. ProGuard veya R8 ile kodu karartmak (obfuscation) değişken isimlerini a, b gibi harflere dönüştürse de, “String” ifadeler (tırnak içindeki değerler) şifrelenmez ve açıkça okunabilir kalır.

Çözüm Yolları ve Güvenli Kod Mimarisi

Mobil uygulamalarda “istemci tarafında” (client-side) bir sırrı %100 gizlemek teorik olarak imkansızdır; çünkü anahtarın çalışma zamanında (runtime) çözülmesi gerekir. Ancak, saldırganın işini o kadar zorlaştırabilirsiniz ki, uğraşmaya değmez hale gelir. İşte katmanlı güvenlik yaklaşımı:

1. Seviye: Gradle ve BuildConfig Kullanımı (Temel Seviye)

Anahtarları koddan çıkarıp local.properties dosyasına koymak, kodu GitHub gibi versiyon kontrol sistemlerine (VCS) atarken anahtarların sızmasını engeller. Ancak unutmayın, bu yöntem APK’yı decompile eden birini durdurmaz.

Adım 1: local.properties dosyasına ekleyin:

API_KEY=”sk_live_guvenli_olmayan_yontem”

Adım 2: build.gradle (Module level) dosyasında tanımlayın:

defaultConfig {
buildConfigField “String”, “API_KEY”, properties[‘API_KEY’]
}

Bu yöntem sadece kaynak kod repozitorisini (Repo) temiz tutar, derlenmiş uygulamayı korumaz.

2. Seviye: Android NDK ile C++ Katmanında Saklama (Orta/İleri Seviye)

Java bytecode’unu tersine çevirmek çok kolaydır, ancak C++ ile yazılmış ve derlenmiş .so (Shared Object) kütüphanelerini analiz etmek (Disassembly) çok daha uzmanlık gerektirir. Saldırganın Hex Editor veya IDA Pro gibi araçlarla Assembly kodunu analiz etmesi gerekir.

Bu yöntemi uygulamak için projenize Android NDK (Native Development Kit) entegre etmelisiniz. Android NDK Kurulumu hakkında detaylı bilgiyi resmi dokümantasyonda bulabilirsiniz.

Adım 1: Native C++ Dosyası Oluşturma (native-lib.cpp)

Projenizin src/main/cpp dizininde C++ dosyanızı oluşturun ve anahtarı burada saklayın. Hatta anahtarı parçalayarak veya basit bir XOR işlemiyle saklamak güvenliği artırır.

Adım 2: Kotlin Tarafından Çağırma

Şimdi bu C++ fonksiyonunu Kotlin kodumuzdan güvenli bir şekilde çağırabiliriz.

Bu yöntem, “script kiddie” olarak adlandırılan ve sadece hazır araçlar kullanan saldırganların %90’ını durduracaktır.

İleri Düzey Güvenlik Önlemleri

Sadece anahtarı saklamak yetmez. Uygulamanızın bütünlüğünü korumak için ek katmanlar eklemelisiniz.

Sertifika Sabitleme (SSL Pinning)

Saldırgan anahtarı bulamasa bile, trafiği dinleyerek (Man-in-the-Middle) API isteği sırasında anahtarı yakalayabilir. Bunu önlemek için SSL Pinning kullanın. Bu işlem, uygulamanın sadece belirli bir sunucu sertifikasına güvenmesini sağlar. OkHttp Certificate Pinning kütüphanesi bu iş için endüstri standardıdır.

API Anahtarı Kısıtlamaları (Key Restrictions)

Google Cloud veya AWS konsolunda API anahtarlarınızı oluştururken, bu anahtarların sadece sizin uygulamanızın paket adı (com.sirket.uygulama) ve SHA-1 imza parmak izi ile çalışmasına izin verin. Böylece anahtar çalınsa bile, saldırgan kendi bilgisayarından bu anahtarı kullanamaz.

Sonuç: Güvenlik Bir Süreçtir

Mobil uygulama güvenliğinde “kırılamaz” diye bir kavram yoktur, sadece “kırılması maliyetli” kavramı vardır. Hardcoded secrets zafiyetini gidermek için API anahtarlarınızı Java kodlarından C++ (NDK) katmanına taşımak, kod karartma (obfuscation) kullanmak ve sunucu tarafında sıkı güvenlik politikaları uygulamak en etkili yöntemlerdir.

Bir güvenlik uzmanı olarak, uygulamanızı yayınlamadan önce mutlaka MobSF gibi otomatik tarama araçlarıyla veya manuel sızma testleriyle analiz etmenizi öneririm. Unutmayın, güvenliği sonradan ekleyemezsiniz, en baştan tasarlamalısınız.

Siber güvenlik ve güvenli kod geliştirme hakkında daha fazla teknik makale için CWE (Common Weakness Enumeration) veritabanını takip edebilirsiniz. Aynı zamanda güvenli kod geliştirme içinde : Android Uygulama Güvenliği ve Bileşenleri

About The Author

Reply