Skip to main content

Use of an insecure channel

Need

Secure transmission of sensitive information

Context

  • Usage of Swift for iOS and macOS app development
  • Usage of Foundation for building responsive and accessible web interfaces

Description

Non compliant code

import Foundation

let url = URL(string: "http://example.com")!
let task = URLSession.shared.dataTask(with: url) {(data, response, error) in
guard let data = data else { return }
print(String(data: data, encoding: .utf8)!)
}
task.resume()

In this Swift code, we are making a network call to a URL (http://example.com) using the URLSession.shared.dataTask method. The data received from the server is then printed in the console. This code is vulnerable because it uses HTTP, a non-secure protocol, to transmit data. HTTP does not encrypt the data being sent, therefore any sensitive information being transmitted can be intercepted and read by attackers. This is known as a 'man-in-the-middle' attack.

The URLSession.shared instance is a shared singleton session object that gives you a reasonable default behavior for creating tasks. In this case, we are using it to create a data task, which sends a HTTP request and calls a handler upon completion. The data returned by the server is then printed to the console.

The code does not check the scheme of the URL, it does not enforce HTTPS, and it does not validate the server's SSL certificate, all of which are necessary for secure transmission of data.

Steps

  • Replace the insecure HTTP protocol with a secure HTTPS protocol.
  • Ensure that the server you are connecting to supports HTTPS.
  • Obtain a valid SSL/TLS certificate for the server.
  • Update the URL to use the HTTPS protocol.
  • Use a secure URLSession configuration that enforces secure communication.
  • Verify the server's SSL/TLS certificate to prevent man-in-the-middle attacks.
  • Handle any errors that may occur during the secure connection process.

Compliant code

import Foundation

// Create a URLSession with a secure configuration
let session = URLSession(configuration: .ephemeral, delegate: nil, delegateQueue: .main)

// Update the URL to use the HTTPS protocol
let url = URL(string: "https://example.com")!

let task = session.dataTask(with: url) {(data, response, error) in
// Handle the error
if let error = error {
print("Error: \\(error)")
return
}

// Verify the server's SSL/TLS certificate
guard let httpResponse = response as? HTTPURLResponse,
let serverCertificate = httpResponse.serverTrust?.certificate(at: 0),
SecTrustEvaluateWithError(httpResponse.serverTrust!, nil),
SecCertificateCopyCommonName(serverCertificate, nil) == "example.com" else {
print("The server's SSL/TLS certificate is not valid.")
return
}

// Use the data
guard let data = data else { return }
print(String(data: data, encoding: .utf8)!)
}

task.resume()

The updated code now uses a secure HTTPS connection instead of an insecure HTTP connection. This is done by changing the URL to use the HTTPS protocol.

A URLSession with a secure configuration is created. The .ephemeral configuration is used, which does not cache any data to disk and stores all information in memory. This is more secure than the default configuration, which caches data to disk.

The server's SSL/TLS certificate is verified to prevent man-in-the-middle attacks. This is done by checking that the certificate's common name matches the expected server name. If the certificate is not valid, an error message is printed and the connection is aborted.

Finally, any errors that occur during the connection process are handled. If an error occurs, it is printed and the connection is aborted. If no errors occur, the data is used as before.

References