İçeriğe geç
Sedat Özdemir
Yazılar

android-hacking

Cebimizdeki Truva Atları: Mobil Uygulama Güvenliğinde 'Ben Yapmam' Denilen Hatalar

Mobil uygulamaların derinliklerine, o decompile edilmiş kodların karanlık dehlizlerine iniyoruz. Root detection'dan SSL pinning'e kadar sahadaki acı gerçekleri ve savunma taktiklerini konuştuk.

Sedat Özdemir
· 4 dk okuma

Gençlik heyecanı işte... İlk mobil sızma testimde, daha yolun çok başındayken, bir bankacılık uygulamasının derinliklerine dalmıştım. Hedefimiz testCompany firmasının yeni çıkan cüzdan uygulamasıydı. O zamanlar her şeyi manuel yapmaya çalışıyorum, kendimi 'Matrix'teki Neo sanıyorum. Uygulamayı decompile ettim, saatlerce smali kodları arasında kayboldum. En sonunda bir API anahtarı bulduğumu sanıp tüm sisteme oradan sızabileceğimi iddia eden o meşhur 'Eureka!' anını yaşadım. Ekibe gidip 'Buldum beyler, sistem bizde!' dedim. Ama küçük bir detay vardı: Bulduğum anahtar aslında Google Maps'in herkese açık, kısıtlanmamış bir API key'iydi ve uygulamanın sadece harita göstermesine yarıyordu. O gün anladım ki, sadece bulmak yetmez; neyi, nerede ve neden bulduğunu bilmek ve bağlamı anlamak her şeydir. O günden beri her mobil projeye 'Hadi bakalım, bu sefer nerede patlayacağız?' diyerek girerim.

Decompile Etmek Mi? O İş Kolay!

Bir Red Teamer olarak işe başladığımızda genelde ilk yaptığımız şey APK veya IPA dosyasını alıp parçalarına ayırmak olur. Android dünyasında bu iş jadx-gui veya apktool ile çocuk oyuncağı. Ama mesele kodu okumak değil, geliştiricinin yorgun olduğu bir salı akşamı bıraktığı o küçük 'unutkanlığı' bulmak.

En sevdiğim hata tipi, strings.xml dosyasının içine veya doğrudan Java/Kotlin kodunun içine gömülmüş API anahtarlarıdır. Geliştirici dostum diyor ki: 'Zaten bu uygulama binary hale geliyor, kimse kodumu göremez.' Ah be güzel kardeşim, decompile dediğin şey sadece saniyeler alıyor.

Bakın mesela, şöyle bir şeyle karşılaşmak o kadar yaygın ki:

// Zararsızlaştırılmış (defanged) örnek
public class ApiConfig {
    private static final String API_KEY = "sk_test_51Mz9...THIS_IS_A_MOCK_KEY..."; // TEHLİKE!
    private static final String BASE_URL = "https://api.example.com/v1/";
}

Burada durup şunu düşünmek lazım: Bu anahtar bir Red Teamer'ın eline geçerse, backend tarafındaki hangi yetkilere sahip olur? Eğer bu bir ödeme sistemiyse ve o anahtar 'test' yerine 'live' ortamına bakıyorsa, geçmiş olsun.

Yerel Depolama: Güvenli Sandığımız O Kara Delik

Uygulamalar veri saklamayı sever. Kullanıcı tercihleri, session token'lar, bazen (maalesef) kullanıcı parolaları... Android'de SharedPreferences, iOS'te UserDefaults veya her iki platformda da SQLite veritabanları en sık kullanılan yerler.

Yıllardır değişmeyen bir hata vardır: Hassas veriyi düz metin (plain-text) olarak saklamak. Geliştirici 'Uygulamanın private alanında saklıyorum, diğer uygulamalar erişemez' diye düşünür. Rootlanmış bir cihazda veya fiziksel erişimi olan bir saldırgan karşısında o private alanın koruması sadece bir illüzyondur.

Mesela AndroidManifest.xml dosyasındaki şu masum görünen satıra dikkat edin:

<application
    android:allowBackup="true"
    ... >
</application>

Bu satır, bir saldırganın adb backup komutuyla telefonunuzdaki tüm uygulama verilerini bilgisayarına çekmesine olanak tanır. Telefonunuzun şifresi olsa bile, USB debugging açıksa verileriniz artık saldırganın bilgisayarındadır. Biz Red Team operasyonlarında, fiziksel erişim senaryolarında ilk buraya bakarız.

SSL Pinning: Güvenlik Mi, Yoksa Sahte Bir Huzur Mu?

Ağ trafiğini izlemek (Interception), mobil pentestin kalbidir. Burp Suite'i kurarsın, sertifikayı cihaza yüklersin ve trafiği akmaya başlar. Ama o da ne? Uygulama ağ hatası veriyor. İşte burada devreye SSL Pinning girer. Uygulama der ki: 'Ben sadece kendi bildiğim, içine gömülü sertifika ile konuşurum, senin Burp Suite sertifikanı tanımam.'

Çoğu kişi burada 'Tamam, uygulama güvenli' deyip bırakıyor. Ama bizim için eğlence yeni başlıyor. Frida diye bir harikamız var. Frida ile çalışma zamanında (runtime) uygulamanın içine sızıp, sertifika kontrolü yapan fonksiyonu 'bypass' edebiliriz.

Örnek bir Frida hook script'i (mantıksal akış):

// Frida ile SSL Pinning Bypass (Pseudo-code)
Java.perform(function() {
    var CertificatePinner = Java.use('okhttp3.CertificatePinner');
    CertificatePinner.check.implementation = function(hostname, certificates) {
        console.log("[+] Bypassing check for: " + hostname);
        return; // Kontrolü boş geç, hata fırlatma!
    };
});

Gördüğünüz gibi, SSL Pinning tek başına bir kurtuluş değil. Savunma tarafında sadece pinning'e güvenmek yerine, veriyi uygulama katmanında da şifrelemek (End-to-End Encryption - E2EE) gerçek bir koruma sağlar.

Root ve Jailbreak Tespiti: Kedi Fare Oyunu

Uygulamalarımız genellikle rootlanmış cihazlarda çalışmak istemez. Haklılar da; root demek, işletim sisteminin tüm koruma mekanizmalarının devre dışı kalması demek. Ancak geliştiricilerin yaptığı en büyük hata, root kontrolünü sadece basit bir dosya varlığı kontrolüne indirgemektir.

Saldırgan su binary'sinin adını değiştirir veya Magisk gibi araçlarla root varlığını gizlerse o kontroller patlar. Hatta daha da basiti, Frida ile root kontrol fonksiyonunun sonucunu her zaman false döndürecek şekilde değiştirebiliriz.

Peki Ne Yapmalı? (Defensive Taktikler)

Bir Red Teamer olarak canınızı yaktıktan sonra biraz da merhem sürelim. testCompany gibi şirketlerde bu işlerin nasıl daha iyi yapılabileceğine dair birkaç ipucum var:

  1. Obfuscation (Kod Karartma): ProGuard veya R8 gibi araçları sadece kodu küçültmek için değil, Red Teamer'ların işini zorlaştırmak için de kullanın. Kod okunabilirliği ne kadar düşükse, bizim işimiz o kadar uzar.
  2. Sensitive Data handling: Hassas verileri asla SharedPreferences gibi yerlerde plain-text saklamayın. Android'de EncryptedSharedPreferences veya iOS'te Keychain kullanın. Ama unutmayın, Keychain bile %100 aşılmaz değildir.
  3. Network Security Config: Android 7.0+ ile gelen network_security_config.xml dosyasını düzgün yapılandırın. Sadece güvenli CA'lere izin verin.
  4. Dynamic Check: Uygulamanın çalışma zamanındaki bütünlüğünü kontrol eden mekanizmalar ekleyin. Frida veya Xposed gibi framework'lerin varlığını tespit eden gelişmiş kütüphaneler kullanın.
  5. Hardcoded Secrets: API anahtarları veya gizli token'lar için asla kodu kullanmayın. Bunları çalışma zamanında güvenli bir vault sisteminden (HashiCorp Vault vb.) çekmek her zaman daha güvenlidir.

Günün sonunda, mobil güvenlik tek bir 'altın vuruş' ile sağlanmıyor. Bu bir katmanlı savunma meselesi. Biz Red Team ekipleri her zaman bir açık buluruz, ama amacımız o açığın gerçek hayatta birileri tarafından sömürülmesini engellemek için sizi erkenden uyarmaktır.

Stay secure, stay geek!

İlgili yazılar