İlk ciddi mobil sızma testimde yaptığım o acemice hatayı hatırladıkça hala yüzüm kızarır. Müşterinin (hadi ona 'testCompany' diyelim) ana bankacılık uygulamasını kurcalıyordum. SSL Pinning'i aşmak için internetten bulduğum, ne idüğü belirsiz bir Frida script'ini biraz modifiye edip pat diye çalıştırdım. Script o kadar agresif bir hook atıyordu ki, uygulama sadece crash olmakla kalmadı; arka plandaki yük dengeleyici (load balancer) alışılmadık trafik paternleri yüzünden tüm ofis IP'mizi 'DoS saldırısı' sanıp blokladı. Üç gün boyunca tüm ekip cep telefonu internetiyle çalışmak zorunda kalmıştık. O gün öğrendiğim en büyük ders şuydu: Mobil dünya, web dünyasının sadece 'küçültülmüş' hali değil, bambaşka bir canavar.
Bugün sizinle o günden bu yana öğrendiğim, sahanın tozunu yutmuş birinin gözünden mobil güvenliğin karanlık ve bir o kadar da eğlenceli dehlizlerine dalacağız. Kahveler hazırsa, cebimizdeki o akıllı kutuların aslında nasıl birer potansiyel casusa dönüşebileceğini ve bunlara karşı nasıl set çekeceğimizi konuşalım.
1. Statik Analiz: Samanlıkta İğne Aramak mı, Mıknatıs Kullanmak mı?
Çoğu kişi mobil sızma testine hemen cihazı bağlayıp trafiği dinleyerek başlayacağını sanır. Ama durun, önce bir 'kodun ruhuna' dokunmamız lazım. Android için .apk, iOS için .ipa dosyası bizim ilk durağımız. Bir APK dosyasını jadx-gui ile açtığınızda karşınıza çıkan o Java kodları bazen o kadar çok şey anlatır ki, trafiği dinlemenize bile gerek kalmaz.
En sık gördüğüm hata ne biliyor musunuz? 'Hardcoded' sırlar. Geliştirici arkadaşım, o API anahtarını veya Firebase URL'ini kodun içine gömdüğünde onun güvende olduğunu sanıyor. Ama değil. Basit bir grep komutuyla bile neler çıkıyor neler:
# Zararsızlaştırılmış örnek: APK içindeki gizli anahtarları aramak
grep -ri "api_key" ./source_code
grep -ri "secret" ./source_code
Savunma Taktiği: Kodun içinde asla ama asla ham (plain-text) halde API anahtarı, şifre veya kritik URL tutmayın. Bunları güvenli build-time konfigürasyonları veya Android Keystore / iOS Keychain gibi donanımsal destekli güvenli depolama birimlerinde saklayın. Ayrıca Proguard veya DexGuard kullanarak kodunuzu karartın (obfuscation). Kodunuz okunabilirse, haritanız çalınmış demektir.
2. Dinamik Analiz ve Frida: Kuklacının İplerini Ele Geçirmek
Mobil güvenliğin kalbi dinamik analizde atar. Uygulama çalışırken ona müdahale etmek, fonksiyonların dönüş değerlerini değiştirmek... İşte burada sahneye Frida çıkıyor. Frida, mobil pentest yapanların İsviçre çakısıdır.
Mesela uygulama 'Cihazınız root'lu, bu yüzden açılmıyorum' mu diyor? Hemen bir hook atıp o kontrolü bypass edelim. İşte size defanged (zararsızlaştırılmış) bir örnek:
// root_check_bypass.js (Mock örnek)
Java.perform(function () {
var RootChecker = Java.use("com.testCompany.security.CheckManager");
// isRooted fonksiyonu her zaman 'false' dönsün
RootChecker.isDeviceRooted.implementation = function () {
console.log("[+] Root kontrolü yakalandı ve kandırıldı!");
return false;
};
});
Frida ile bu script'i frida -U -f com.testCompany.app -l root_check_bypass.js --no-pause komutuyla çalıştırdığınızda, uygulama kendini en güvenli cihazda sanmaya başlar.
Savunma Taktiği: Root/Jailbreak kontrollerini sadece basit bir 'if-else' ile yapmayın. Kontrol mekanizmasını native katmana (C/C++) taşıyın ve RASP (Runtime Application Self-Protection) çözümlerini tercih edin. Uygulama, çalışma zamanında kendi bütünlüğünü kontrol edebilmeli.
3. SSL Pinning: Güvenli Sandığınız Tünel Ne Kadar Sağlam?
HTTP trafiğini Burp Suite ile dinlemek istediğinizde karşınıza çıkan o meşhur SSL hatası... Çoğu uygulama artık SSL Pinning kullanarak sadece kendi sertifikasına güveniyor. Ama Red Team dünyasında bu sadece küçük bir hız tümseği.
SSL Pinning'i aşmak için sertifika kontrolü yapan kütüphaneleri (OkHttp3, TrustManager vb.) hook'luyoruz. Eğer uygulama bu kontrolleri düzgün yapmazsa, saldırgan aradaki tüm trafiği (kimlik bilgileri, session tokenları) kabak gibi okur.
Savunma Taktiği: Network Security Configuration (Android) kullanarak sertifika pinning yapın ama bunu yaparken 'Certificate Transparency' loglarını da kontrol eden daha modern yaklaşımları benimseyin. Ve en önemlisi, SSL Pinning'e %100 güvenmeyin; uygulama katmanında da veri şifrelemesi (Payload Encryption) kullanarak işleri zorlaştırın.
4. Intent'ler ve Exported Components: Arka Kapıyı Açık Unutmak
Android dünyasında AndroidManifest.xml dosyasını incelemek, evin planına bakmak gibidir. Eğer bir activity, service veya broadcast receiver android:exported="true" olarak işaretlenmişse, cihazdaki diğer herhangi bir uygulama (kötü amaçlı bir uygulama dahil) ona sinyal gönderebilir.
Senaryo şu: testCompany uygulaması, giriş yapıldıktan sonra InternalDataActivity'yi açıyor. Eğer bu activity dışarıya açıksa, ben başka bir uygulama yazıp direkt o ekranı, login'i bypass ederek çağırabilirim.
<!-- Tehlikeli bir örnek -->
<activity android:name=".InternalDataActivity" android:exported="true">
<!-- Dışarıdan herkes bana erişebilir diyor -->
</activity>
Savunma Taktiği: İhtiyacınız olmayan bileşenleri asla dışarıya açmayın (exported="false"). Eğer dışarıdan veri almanız gerekiyorsa, gelen Intent'in içeriğini çok sıkı bir validasyondan geçirin. Kendi uygulamalarınız arasındaki iletişim için Signature-based permissions kullanın.
5. Insecure Data Storage: Telefonu Kaybedince Her Şeyi Kaybetmek
Kullanıcıların en büyük kabusu telefonunu çaldırmaktır. Bir Red Teamer olarak bizim görevimiz, telefon çalınsa bile uygulama verilerinin güvende kalmasını sağlamaktır. Shared Preferences içine kaydedilen kullanıcı şifreleri, Cache klasöründe unutulan hassas JSON çıktıları... Bunlar altın değerinde bilgiler.
Bir cihazın yedeğini aldığınızda veya root yetkisiyle /data/data/com.testCompany.app/ altına girdiğinizde bulduğunuz SQLite veritabanları genellikle şifrelenmemiştir.
Savunma Taktiği: Hassas verileri asla ama asla ham halde saklamayın. SQLCipher gibi kütüphanelerle veritabanınızı şifreleyin. Anahtar yönetimini ise işletim sisteminin sunduğu Keystore (Android) veya Keychain (iOS) sistemlerine emanet edin. Uygulama arka plana geçtiğinde ekran görüntüsü alınmasını engellemek için FLAG_SECURE kullanmayı da unutmayın.
Bitirirken...
Mobil güvenlik, kedi-fare oyununun en yoğun yaşandığı alanlardan biri. Biz Red Team tarafında her zaman bir yol bulmaya çalışıyoruz, ancak savunma tarafındaki dostlarımızın işi daha zor; her deliği kapatmak zorundalar.
Unutmayın, mobil bir uygulama geliştirirken yazdığınız her satır kod, bir saldırgan için potansiyel bir giriş kapısıdır. 'Kimse benim uygulamamı decompile etmez' veya 'Cihaz zaten güvenli' yanılgısına düşmeyin. Cihazın kontrolünün tamamen saldırganda olduğu (root/jailbreak) bir senaryoyu baz alarak savunma kurgulayın.
Bir sonraki yazıda, belki biraz da iOS'in o 'kapalı kutu' dünyasındaki zafiyetlerden ve Objective-C runtime'ın cilvelerinden bahsederiz. O zamana kadar, kodunuz güvenli, shell'iniz uzak olsun!
