M3: Insecure Communication
M3: Insecure Communication
This covers poor implementation of TLS, transmitting sensitive data over unencrypted channels, and weak network security configurations.
Implementation and Mitigation:
// iOS - Secure network communication
class SecureNetworkManager {
// VULNERABLE: Common insecure patterns
class InsecureCommunication {
func demonstrateVulnerabilities() {
// Bad: Allowing arbitrary loads
// In Info.plist: NSAllowsArbitraryLoads = true
// Bad: Disabling certificate validation
let session = URLSession(configuration: .default, delegate: self, delegateQueue: nil)
}
// Bad: Accepting any certificate
func urlSession(_ session: URLSession,
didReceive challenge: URLAuthenticationChallenge,
completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
// Never do this!
completionHandler(.useCredential, URLCredential(trust: challenge.protectionSpace.serverTrust!))
}
}
// SECURE: Proper network security
class SecureCommunication: NSObject, URLSessionDelegate {
private let pinnedCertificates: [String: SecCertificate] = [:]
func createSecureSession() -> URLSession {
let configuration = URLSessionConfiguration.default
// Enable TLS 1.2 minimum
configuration.tlsMinimumSupportedProtocolVersion = .TLSv12
configuration.tlsMaximumSupportedProtocolVersion = .TLSv13
// Disable caching for sensitive requests
configuration.requestCachePolicy = .reloadIgnoringLocalCacheData
configuration.urlCache = nil
// Set appropriate timeouts
configuration.timeoutIntervalForRequest = 30
configuration.timeoutIntervalForResource = 60
return URLSession(configuration: configuration, delegate: self, delegateQueue: nil)
}
// Implement certificate pinning
func urlSession(_ session: URLSession,
didReceive challenge: URLAuthenticationChallenge,
completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
guard challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust,
let serverTrust = challenge.protectionSpace.serverTrust,
let certificate = SecTrustGetCertificateAtIndex(serverTrust, 0) else {
completionHandler(.cancelAuthenticationChallenge, nil)
return
}
// Verify certificate pinning
let host = challenge.protectionSpace.host
if let pinnedCertificate = pinnedCertificates[host] {
let serverCertData = SecCertificateCopyData(certificate) as Data
let pinnedCertData = SecCertificateCopyData(pinnedCertificate) as Data
if serverCertData == pinnedCertData {
completionHandler(.useCredential, URLCredential(trust: serverTrust))
} else {
// Certificate mismatch - possible MITM
completionHandler(.cancelAuthenticationChallenge, nil)
}
} else {
// No pinning for this host - use default validation
completionHandler(.performDefaultHandling, nil)
}
}
// Secure API request with additional protections
func makeSecureRequest(to endpoint: String, body: Data?) async throws -> Data {
guard let url = URL(string: endpoint),
url.scheme == "https" else {
throw NetworkError.insecureURL
}
var request = URLRequest(url: url)
request.httpMethod = "POST"
// Add security headers
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue(generateRequestSignature(for: body), forHTTPHeaderField: "X-Signature")
request.setValue(UUID().uuidString, forHTTPHeaderField: "X-Request-ID")
if let body = body {
// Encrypt request body
request.httpBody = try encryptRequestBody(body)
}
let (data, response) = try await createSecureSession().data(for: request)
guard let httpResponse = response as? HTTPURLResponse,
(200...299).contains(httpResponse.statusCode) else {
throw NetworkError.invalidResponse
}
return data
}
}
}