Tüm Yazılar
KategoriSecurity
Okuma Süresi
23 dk okuma
Yayın Tarihi
...
Kelime Sayısı
1.477kelime

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

Certificate pinning, mutual TLS, request signing, anti-tampering ve traffic analiz koruması ile iOS ağ güvenliğini en üst seviyeye taşıyın.

iOS Network Security Advanced: Sıfırdan Zırhlı İletişim

# iOS Network Security Advanced: Sıfırdan Zırhlı İletişim

Mobil uygulamanız ile sunucunuz arasındaki her byte, potansiyel bir saldırı yüzeyi. Man-in-the-Middle (MITM) saldırıları, certificate spoofing, request tampering ve traffic analysis — bunlar teorik tehditler değil, her gün gerçekleşen saldırılar. Bu rehberde, iOS uygulamanızın ağ katmanını askeri düzeyde koruma altına alacağız.

Uyarı: Bu rehberdeki teknikler savunma amaçlıdır. Güvenlik, katmanlı bir yaklaşım gerektirir; tek bir önlem yeterli değildir.

İçindekiler


1. HTTPS ve TLS Temelleri

App Transport Security (ATS), iOS 9'dan beri HTTPS'i zorunlu kılar. Ama varsayılan TLS yeterli mi?

TLS Handshake Süreci

  1. Client Hello: Desteklenen cipher suite'ler gönderilir
  2. Server Hello: Cipher suite ve sertifika seçilir
  3. Certificate Verification: Sertifika zinciri doğrulanır
  4. Key Exchange: Simetrik anahtar oluşturulur
  5. Encrypted Communication: Veri şifreli akar

ATS Konfigürasyonu

swift
1// Info.plist - En sıkı ATS ayarları
2// NSAppTransportSecurity:
3// NSAllowsArbitraryLoads: false (VARSAYILAN - degistirmeyin!)
4// NSExceptionDomains:
5// api.example.com:
6// NSExceptionMinimumTLSVersion: TLSv1.3
7// NSRequiresCertificateTransparency: true
8// NSExceptionRequiresForwardSecrecy: true
9 
10// Programmatic kontrol
11final class TLSConfiguration {
12 static func createSecureSession() -> URLSession {
13 let config = URLSessionConfiguration.default
14 config.tlsMinimumSupportedProtocolVersion = .TLSv13
15 config.urlCache = nil // Hassas veri cache'leme
16 config.requestCachePolicy = .reloadIgnoringLocalCacheData
17 
18 return URLSession(
19 configuration: config,
20 delegate: SecurityDelegate.shared,
21 delegateQueue: nil
22 )
23 }
24}

2. Certificate Pinning

Certificate Pinning, uygulamanızın sadece bildiği sertifikalara güvenmesini sağlar. Sistem trust store'u atlanarak MITM saldırıları önlenir.

Pinning Stratejileri

Strateji
Güvenlik
Esneklik
Bakım
Önerilen
**Certificate Pinning**
En yüksek
En düşük
Sertifika yenilemede update
Finans uygulamaları
**Public Key Pinning**
Yüksek
Orta
Key değişmezse update gerekmez
Genel kullanım
**CA Pinning**
Orta
Yüksek
Minimal
Kurumsal
**HPKP Header**
Orta
Orta
Server-side
Web uygulamaları

Public Key Pinning Implementasyonu

swift
1// MARK: - Certificate Pinner
2final class CertificatePinner: NSObject, URLSessionDelegate {
3 // Pin'lenmis public key hash'leri (SHA256, base64)
4 private let pinnedKeyHashes: Set<String> = [
5 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=", // Primary
6 "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB=", // Backup
7 ]
8 
9 func urlSession(
10 _ session: URLSession,
11 didReceive challenge: URLAuthenticationChallenge,
12 completionHandler: @escaping(URLSession.AuthChallengeDisposition, URLCredential?) -> Void
13 ) {
14 guard challenge.protectionSpace.authenticationMethod ==
15 NSURLAuthenticationMethodServerTrust,
16 let serverTrust = challenge.protectionSpace.serverTrust else {
17 completionHandler(.cancelAuthenticationChallenge, nil)
18 return
19 }
20 
21 // Sertifika zincirini dogrula
22 let policies = [SecPolicyCreateSSL(true, challenge.protectionSpace.host as CFString)]
23 SecTrustSetPolicies(serverTrust, policies as CFArray)
24 
25 var error: CFError?
26 guard SecTrustEvaluateWithError(serverTrust, &error) else {
27 completionHandler(.cancelAuthenticationChallenge, nil)
28 return
29 }
30 
31 // Public key pin kontrolu
32 let certificateCount = SecTrustGetCertificateCount(serverTrust)
33 var pinFound = false
34 
35 for index in 0..<certificateCount {
36 guard let certificate = SecTrustCopyCertificateChain(serverTrust)
37 .map({ ($0 as! [SecCertificate])[index] }),
38 let publicKey = SecCertificateCopyKey(certificate),
39 let publicKeyData = SecKeyCopyExternalRepresentation(publicKey, nil) as Data? else {
40 continue
41 }
42 
43 let keyHash = publicKeyData.sha256().base64EncodedString()
44 if pinnedKeyHashes.contains(keyHash) {
45 pinFound = true
46 break
47 }
48 }
49 
50 if pinFound {
51 completionHandler(.useCredential, URLCredential(trust: serverTrust))
52 } else {
53 // Pin eslesmedi - muhtemel MITM saldirisi!
54 SecurityLogger.log(.pinningFailure, host: challenge.protectionSpace.host)
55 completionHandler(.cancelAuthenticationChallenge, nil)
56 }
57 }
58}
59 
60extension Data {
61 func sha256() -> Data {
62 var hash = [UInt8](repeating: 0, count: Int(CC_SHA256_DIGEST_LENGTH))
63 withUnsafeBytes { buffer in
64 _ = CC_SHA256(buffer.baseAddress, CC_LONG(count), &hash)
65 }
66 return Data(hash)
67 }
68}

Easter Egg

Gizli bir bilgi buldun!

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


3. Mutual TLS (mTLS)

Normal TLS'de sadece sunucu kimliğini doğrular. mTLS'de hem sunucu hem istemci birbirini doğrular.

swift
1// MARK: - mTLS Client
2final class MutualTLSClient: NSObject, URLSessionDelegate {
3 private let clientIdentity: SecIdentity
4 
5 init(p12Data: Data, password: String) throws {
6 let options: [String: Any] = [kSecImportExportPassphrase as String: password]
7 var items: CFArray?
8 let status = SecPKCS12Import(p12Data as CFData, options as CFDictionary, &items)
9 
10 guard status == errSecSuccess,
11 let array = items as? [[String: Any]],
12 let first = array.first,
13 let identity = first[kSecImportItemIdentity as String] else {
14 throw SecurityError.invalidClientCertificate
15 }
16 
17 self.clientIdentity = identity as! SecIdentity
18 }
19 
20 func urlSession(
21 _ session: URLSession,
22 didReceive challenge: URLAuthenticationChallenge,
23 completionHandler: @escaping(URLSession.AuthChallengeDisposition, URLCredential?) -> Void
24 ) {
25 switch challenge.protectionSpace.authenticationMethod {
26 case NSURLAuthenticationMethodClientCertificate:
27 // Client sertifikasini sun
28 let credential = URLCredential(
29 identity: clientIdentity,
30 certificates: nil,
31 persistence: .forSession
32 )
33 completionHandler(.useCredential, credential)
34 
35 case NSURLAuthenticationMethodServerTrust:
36 // Normal server trust + pinning
37 guard let trust = challenge.protectionSpace.serverTrust else {
38 completionHandler(.cancelAuthenticationChallenge, nil)
39 return
40 }
41 completionHandler(.useCredential, URLCredential(trust: trust))
42 
43 default:
44 completionHandler(.performDefaultHandling, nil)
45 }
46 }
47}

4. Request Signing

Her API isteğinin imzalanması, request tampering'i önler.

swift
1// MARK: - HMAC Request Signer
2struct RequestSigner {
3 private let secretKey: Data
4 
5 init(secretKey: Data) {
6 self.secretKey = secretKey
7 }
8 
9 func sign(_ request: inout URLRequest) {
10 let timestamp = String(Int(Date().timeIntervalSince1970))
11 let nonce = UUID().uuidString
12 
13 // Imzalanacak veri olustur
14 let method = request.httpMethod ?? "GET"
15 let path = request.url?.path ?? "/"
16 let query = request.url?.query ?? ""
17 let bodyHash = (request.httpBody ?? Data()).sha256().base64EncodedString()
18 
19 let signatureInput = [method, path, query, timestamp, nonce, bodyHash]
20 .joined(separator: "\n")
21 
22 // HMAC-SHA256 imza
23 let signature = HMAC<SHA256>.authenticationCode(
24 for: Data(signatureInput.utf8),
25 using: SymmetricKey(data: secretKey)
26 )
27 let signatureString = Data(signature).base64EncodedString()
28 
29 // Header'lara ekle
30 request.setValue(timestamp, forHTTPHeaderField: "X-Timestamp")
31 request.setValue(nonce, forHTTPHeaderField: "X-Nonce")
32 request.setValue(signatureString, forHTTPHeaderField: "X-Signature")
33 }
34}

5. Proxy Detection

MITM proxy (Charles, mitmproxy vb.) kullanımını tespit edin:

swift
1// MARK: - Proxy Detector
2struct ProxyDetector {
3 static var isProxyConfigured: Bool {
4 guard let proxySettings = CFNetworkCopySystemProxySettings()?.takeRetainedValue()
5 as? [String: Any] else {
6 return false
7 }
8 
9 // HTTP Proxy kontrol
10 if let httpProxy = proxySettings["HTTPProxy"] as? String,
11 !httpProxy.isEmpty {
12 return true
13 }
14 
15 // HTTPS Proxy kontrol
16 if let httpsProxy = proxySettings["HTTPSProxy"] as? String,
17 !httpsProxy.isEmpty {
18 return true
19 }
20 
21 return false
22 }
23 
24 static func enforceNoProxy() {
25 if isProxyConfigured {
26 SecurityLogger.log(.proxyDetected)
27 // Hassas islemleri engelle veya uyar
28 }
29 }
30}

6. Network Security Katmanları

Katman
Koruma
Saldırı Türü
Zorluk
**TLS 1.3**
Transport şifreleme
Pasif dinleme
Kolay
**Certificate Pinning**
MITM koruması
Sahte sertifika
Orta
**mTLS**
Karşılıklı doğrulama
Yetkisiz istemci
Zor
**Request Signing**
Tampering koruması
İstek değiştirme
Orta
**Proxy Detection**
Analiz koruması
Traffic sniffing
Kolay
**Response Validation**
Veri bütünlüğü
Response injection
Orta

swift
1// MARK: - Remote Pin Rotation Manager
2final class PinRotationManager {
3 private let keychain = KeychainHelper.shared
4 private let remotePinURL = URL(string: "https://api.example.com/.well-known/pins.json")!
5 private let cacheKey = "certificate_pins_v1"
6 
7 func currentPins() -> Set<String> {
8 // 1. Keychain'deki guncel pin'leri oku
9 if let cached = keychain.getData(cacheKey),
10 let pins = try? JSONDecoder().decode(PinConfig.self, from: cached),
11 pins.expiresAt > Date() {
12 return Set(pins.hashes)
13 }
14 // 2. Fallback: bundle'daki hardcoded pin'ler
15 return Set(BundledPins.defaultHashes)
16 }
17 
18 func refreshPins() async {
19 guard let (data, _) = try? await URLSession.shared.data(from: remotePinURL),
20 let config = try? JSONDecoder().decode(PinConfig.self, from: data) else { return }
21 keychain.set(data, forKey: cacheKey)
22 }
23 
24 struct PinConfig: Codable {
25 let hashes: [String] // Primary + backup pin hash'leri
26 let expiresAt: Date // Cache suresi
27 let minAppVersion: String // Minimum desteklenen versiyon
28 }
29}

ALTIN İPUCU

Bu yazının en değerli bilgisi

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

Okuyucu Ödülü

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

Sonuç ve Öneriler

Network güvenliği, tek bir önlemle sağlanamaz. TLS ile başlayın, certificate pinning ekleyin, hassas endpoint'ler için request signing uygulayın ve proxy detection ile analiz koruması sağlayın. Güvenlik katmanlıdır; her katman bir saldırı vektörünü kapatır. Paranoyak olmayın ama hazırlıklı olun.

Etiketler

#Security#Networking#SSL#Certificate Pinning#iOS#Encryption
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