Tüm Yazılar
KategoriSecurity
Okuma Süresi
26 dk
Yayın Tarihi
...
Kelime Sayısı
1.389kelime

Kahveni hazırla - bu içerikli bir makale!

Keychain kullanımı, biometric authentication, SSL pinning, jailbreak detection ve code obfuscation. Uygulamanızı güvenli hale getirin.

iOS Security Best Practices 2024

iOS güvenliği, kullanıcı verilerini ve uygulama bütünlüğünü korumak için kritik öneme sahiptir. Bu kapsamlı rehberde, modern iOS güvenlik best practice'lerini inceleyeceğiz.


İçindekiler


iOS Guvenlik Katmanlari Karsilastirma Tablosu

Guvenlik Katmani
Koruma Alani
Zorluk
Oncelik
Bypass Riski
**Keychain**
Token, sifre, credential
Kolay
Kritik
Dusuk
**Biometric Auth**
Kullanici dogrulama
Kolay
Yuksek
Dusuk
**SSL Pinning**
Network trafigi
Orta
Kritik
Orta
**Jailbreak Detection**
Cihaz butunlugu
Orta
Orta
Yuksek
**Code Obfuscation**
Kaynak kod
Zor
Orta
Orta
**Data Protection**
Dosya sifreleme
Kolay
Yuksek
Dusuk
**Runtime Protection**
Debugger engelleme
Zor
Orta
Yuksek
**Input Validation**
Enjeksiyon saldirilari
Kolay
Kritik
Dusuk
**Screen Capture Prevention**
Ekran goruntuleme
Kolay
Dusuk
Yuksek

Keychain Services

Hassas verileri güvenli şekilde saklamak için Keychain kullanımı:

swift
1import Security
2 
3class KeychainManager {
4 enum KeychainError: Error {
5 case duplicateEntry
6 case unknown(OSStatus)
7 case notFound
8 case unexpectedData
9 }
10
11 // Save
12 static func save(key: String, data: Data, biometricProtected: Bool = false) throws {
13 var query: [String: Any] = [
14 kSecClass as String: kSecClassGenericPassword,
15 kSecAttrAccount as String: key,
16 kSecValueData as String: data
17 ]
18
19 if biometricProtected {
20 let access = SecAccessControlCreateWithFlags(
21 nil,
22 kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly,
23 .biometryCurrentSet,
24 nil
25 )
26 query[kSecAttrAccessControl as String] = access
27 } else {
28 query[kSecAttrAccessible as String] = kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly
29 }
30
31 let status = SecItemAdd(query as CFDictionary, nil)
32
33 if status == errSecDuplicateItem {
34 // Update existing
35 let updateQuery = [kSecValueData as String: data]
36 SecItemUpdate(query as CFDictionary, updateQuery as CFDictionary)
37 } else if status != errSecSuccess {
38 throw KeychainError.unknown(status)
39 }
40 }
41
42 // Read
43 static func read(key: String) throws -> Data {
44 let query: [String: Any] = [
45 kSecClass as String: kSecClassGenericPassword,
46 kSecAttrAccount as String: key,
47 kSecReturnData as String: true,
48 kSecMatchLimit as String: kSecMatchLimitOne
49 ]
50
51 var result: AnyObject?
52 let status = SecItemCopyMatching(query as CFDictionary, &result)
53
54 guard status == errSecSuccess else {
55 throw KeychainError.notFound
56 }
57
58 guard let data = result as? Data else {
59 throw KeychainError.unexpectedData
60 }
61
62 return data
63 }
64
65 // Delete
66 static func delete(key: String) {
67 let query: [String: Any] = [
68 kSecClass as String: kSecClassGenericPassword,
69 kSecAttrAccount as String: key
70 ]
71 SecItemDelete(query as CFDictionary)
72 }
73}
74 
75// Usage
76struct Credentials: Codable {
77 let accessToken: String
78 let refreshToken: String
79 let expiresAt: Date
80}
81 
82class SecureStorage {
83 func saveCredentials(_ credentials: Credentials) throws {
84 let data = try JSONEncoder().encode(credentials)
85 try KeychainManager.save(key: "user_credentials", data: data, biometricProtected: true)
86 }
87
88 func loadCredentials() throws -> Credentials {
89 let data = try KeychainManager.read(key: "user_credentials")
90 return try JSONDecoder().decode(Credentials.self, from: data)
91 }
92}

Biometric Authentication

Face ID ve Touch ID entegrasyonu:

swift
1import LocalAuthentication
2 
3class BiometricAuthManager {
4 enum BiometricType {
5 case none
6 case touchID
7 case faceID
8 }
9
10 var biometricType: BiometricType {
11 let context = LAContext()
12 var error: NSError?
13
14 guard context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) else {
15 return .none
16 }
17
18 switch context.biometryType {
19 case .faceID: return .faceID
20 case .touchID: return .touchID
21 default: return .none
22 }
23 }
24
25 func authenticate(reason: String) async throws -> Bool {
26 let context = LAContext()
27 context.localizedCancelTitle = "İptal"
28 context.localizedFallbackTitle = "Şifre Kullan"
29
30 var error: NSError?
31 guard context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) else {
32 throw error ?? NSError(domain: "BiometricAuth", code: -1)
33 }
34
35 return try await context.evaluatePolicy(
36 .deviceOwnerAuthenticationWithBiometrics,
37 localizedReason: reason
38 )
39 }
40}
41 
42// SwiftUI Integration
43struct SecureView: View {
44 @State private var isAuthenticated = false
45 @State private var showError = false
46 private let biometricAuth = BiometricAuthManager()
47
48 var body: some View {
49 Group {
50 if isAuthenticated {
51 ProtectedContentView()
52 } else {
53 AuthenticationPromptView {
54 await authenticate()
55 }
56 }
57 }
58 .alert("Doğrulama Başarısız", isPresented: $showError) {
59 Button("Tamam", role: .cancel) {}
60 }
61 }
62
63 private func authenticate() async {
64 do {
65 isAuthenticated = try await biometricAuth.authenticate(
66 reason: "Güvenli içeriğe erişmek için doğrulayın"
67 )
68 } catch {
69 showError = true
70 }
71 }
72}

SSL Pinning

Man-in-the-middle saldırılarına karşı koruma:

swift
1import CryptoKit
2 
3class SSLPinningManager: NSObject, URLSessionDelegate {
4 // Public key hash'leri (base64)
5 private let pinnedHashes = [
6 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=", // Primary
7 "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB=" // Backup
8 ]
9
10 func urlSession(
11 _ session: URLSession,
12 didReceive challenge: URLAuthenticationChallenge,
13 completionHandler: @escaping(URLSession.AuthChallengeDisposition, URLCredential?) -> Void
14 ) {
15 guard challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust,
16 let serverTrust = challenge.protectionSpace.serverTrust else {
17 completionHandler(.cancelAuthenticationChallenge, nil)
18 return
19 }
20
21 // Sertifika zincirini doğrula
22 var error: CFError?
23 let isValid = SecTrustEvaluateWithError(serverTrust, &error)
24
25 guard isValid else {
26 completionHandler(.cancelAuthenticationChallenge, nil)
27 return
28 }
29
30 // Public key pinning
31 guard let certificate = SecTrustGetCertificateAtIndex(serverTrust, 0) else {
32 completionHandler(.cancelAuthenticationChallenge, nil)
33 return
34 }
35
36 let publicKey = SecCertificateCopyKey(certificate)
37 let publicKeyData = SecKeyCopyExternalRepresentation(publicKey!, nil)! as Data
38 let hash = SHA256.hash(data: publicKeyData)
39 let hashString = Data(hash).base64EncodedString()
40
41 if pinnedHashes.contains(hashString) {
42 completionHandler(.useCredential, URLCredential(trust: serverTrust))
43 } else {
44 completionHandler(.cancelAuthenticationChallenge, nil)
45 }
46 }
47}
48 
49// Alamofire ile SSL Pinning
50import Alamofire
51 
52class SecureNetworkManager {
53 static let shared = SecureNetworkManager()
54
55 private let session: Session
56
57 private init() {
58 let evaluators: [String: ServerTrustEvaluating] = [
59 "api.myapp.com": PublicKeysTrustEvaluator()
60 ]
61
62 let manager = ServerTrustManager(evaluators: evaluators)
63 session = Session(serverTrustManager: manager)
64 }
65
66 func request<T: Decodable>(_ endpoint: String) async throws -> T {
67 return try await session
68 .request("https://api.myapp.com" + endpoint)
69 .serializingDecodable(T.self)
70 .value
71 }
72}

Jailbreak Detection

swift
1class JailbreakDetector {
2 static func isJailbroken() -> Bool {
3 #if targetEnvironment(simulator)
4 return false
5 #else
6
7 // 1. Suspicious files check
8 let suspiciousFiles = [
9 "/Applications/Cydia.app",
10 "/Library/MobileSubstrate/MobileSubstrate.dylib",
11 "/bin/bash",
12 "/usr/sbin/sshd",
13 "/etc/apt",
14 "/private/var/lib/apt/"
15 ]
16
17 for path in suspiciousFiles {
18 if FileManager.default.fileExists(atPath: path) {
19 return true
20 }
21 }
22
23 // 2. Write test
24 let testPath = "/private/jailbreak_test.txt"
25 do {
26 try "test".write(toFile: testPath, atomically: true, encoding: .utf8)
27 try FileManager.default.removeItem(atPath: testPath)
28 return true
29 } catch {
30 // Expected on non-jailbroken devices
31 }
32
33 // 3. URL scheme check
34 if let url = URL(string: "cydia://package/com.example.package"),
35 UIApplication.shared.canOpenURL(url) {
36 return true
37 }
38
39 // 4. Dylib injection check
40 let count = _dyld_image_count()
41 for i in 0..<count {
42 if let name = _dyld_get_image_name(i) {
43 let imageName = String(cString: name)
44 if imageName.contains("MobileSubstrate") ||
45 imageName.contains("Substrate") ||
46 imageName.contains("cycript") {
47 return true
48 }
49 }
50 }
51
52 return false
53 #endif
54 }
55}

Data Protection

swift
1// File protection levels
2func saveSecureFile(data: Data, filename: String) throws {
3 let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
4 let fileURL = documentsURL.appendingPathComponent(filename)
5
6 try data.write(to: fileURL, options: .completeFileProtection)
7
8 // Verify protection
9 let attributes = try FileManager.default.attributesOfItem(atPath: fileURL.path)
10 let protection = attributes[.protectionKey] as? FileProtectionType
11 assert(protection == .complete)
12}

Security Checklist

  • Keychain için hassas veriler
  • Biometric authentication
  • SSL/TLS pinning
  • Jailbreak detection
  • File protection
  • Input validation
  • Code obfuscation
  • Debug detection
  • Screen capture prevention

Sonuç

iOS güvenliği çok katmanlı bir yaklaşım gerektirir. Keychain, biometric auth, SSL pinning ve jailbreak detection gibi teknikleri kombine ederek uygulamanızı güvenli hale getirebilirsiniz.

Easter Egg

Gizli bir bilgi buldun!

Bu bölümde gizli bir bilgi var. Keşfetmek ister misin?

Okuyucu Ödülü

Tebrikler! Bu yazıyı sonuna kadar okuduğun için sana özel bir hediyem var:

ALTIN İPUCU

Bu yazının en değerli bilgisi

Bu ipucu, yazının en önemli çıkarımını içeriyor.

Etiketler

#Security#iOS#Keychain#Encryption#OWASP#App Transport
Muhittin Çamdalı

Muhittin Çamdalı

Senior iOS Developer

12+ yıllık deneyime sahip iOS Developer. Swift, SwiftUI ve modern iOS mimarileri konusunda uzman. Apple platformlarında performanslı ve kullanıcı dostu uygulamalar geliştiriyorum.

iOS Geliştirme Haberleri

Haftalık Swift tips, SwiftUI tricks ve iOS best practices. Spam yok, sadece değerli içerik.

Gizliliğinize saygı duyuyoruz. İstediğiniz zaman abonelikten çıkabilirsiniz.

Paylaş

Bunu da begenebilirsiniz