Insecure service configuration - Host verification - Swift

Insecure service configuration - Host verification - Swift

Need

Secure service configuration - Host verification

Context

  • Usage of Swift for iOS and macOS app development
  • Usage of Foundation for building responsive and accessible web interfaces
  • Usage of Alamofire for making HTTP requests in Swift

Description

Non compliant code

        import Foundation
import Alamofire

let url = "https://example.com"
Alamofire.request(url).validate().responseJSON { response in
    switch response.result {
    case .success:
        print("Validation Successful")
    case .failure(let error):
        print(error)
    }
}
        
        

This code is vulnerable to insecure service configuration due to lack of host verification. It is using Alamofire for networking in Swift. Alamofire is a very powerful framework and supports a wide variety of networking tasks. However, in this case, the developer is using it insecurely.

The request function is used to make a simple HTTP request to the given URL. The validate function is used to validate the request, which means it checks the response status code to be in the range 200...299, and that the Content-Type header of the response matches the Accept header of the request, if one is provided.

The problem here is, the code does not restrict incoming connections from unknown external hosts. It accepts all the incoming connections regardless of their origin. This can be a serious security issue as it can allow potential attackers to send requests to the application.

In this scenario, an attacker can intercept the request and manipulate the data or even redirect the request to a malicious server. As a result, sensitive user data can be exposed and the integrity of the application can be compromised.

In order to fix this vulnerability, we need to add host verification to ensure that the incoming connections are from the trusted hosts only. We can use ServerTrustPolicy to define the server trust evaluation criteria for a particular domain and subdomain.

Steps

  • Implement proper host verification by checking the server's SSL certificate.
  • Use a trusted certificate authority (CA) to issue the SSL certificate for the server.
  • Ensure that the server's SSL certificate is valid and not expired.
  • Verify that the server's SSL certificate matches the expected hostname.
  • Implement certificate pinning to further enhance security.
  • Regularly update the CA certificates on the client-side to include any new trusted CAs or revoke any compromised CAs.
  • Implement proper error handling and logging to detect and respond to any potential security issues.

Compliant code

        import Foundation
import Alamofire

let url = "https://example.com"

let serverTrustPolicies: [String: ServerTrustPolicy] = [
    "example.com": .pinCertificates(
        certificates: ServerTrustPolicy.certificates(),
        validateCertificateChain: true,
        validateHost: true
    )
]

let sessionManager = SessionManager(
    serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicies)
)

sessionManager.request(url).validate().responseJSON { response in
    switch response.result {
    case .success:
        print("Validation Successful")
    case .failure(let error):
        print(error)
    }
}
        
        

The above code fixes the vulnerability by implementing certificate pinning and host verification.

1. Certificate Pinning: This is done by using Alamofire's ServerTrustPolicy. We specify that for the host "example.com", we want to pin the certificates. This means that the app will only trust the specific certificates that we provide, and not any certificate in the trust chain. This is a strong defense against Man-in-the-Middle (MitM) attacks.

2. Host Verification: We set validateHost to true. This means that the app will verify that the certificate's common name or subject alternative name matches the host that we are connecting to.

3. Certificate Chain Validation: We set validateCertificateChain to true. This means that the app will verify that the certificate's chain of trust leads back to a trusted root certificate.

4. ServerTrustPolicyManager: We create a SessionManager with our serverTrustPolicyManager. This manager applies our trust policy to all requests made with this session manager.

5. Error Handling: If the request fails validation or if there is any other error, it will be caught and printed. This allows us to detect and respond to any potential security issues.

Remember to replace "example.com" with your actual host and to provide the correct certificates for pinning.

References