Insecure service configuration - Backup - Swift

Insecure service configuration - Backup - Swift

Need

Secure backup configuration

Context

  • Usage of Swift for iOS and macOS app development
  • Usage of UIKit for building modern and responsive user interfaces

Description

Non compliant code

        import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        
        let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
        let documentsDirectory = paths[0]
        let filePath = "\\(documentsDirectory)/SensitiveData.plist"
        
        let sensitiveData = ["username": "admin", "password": "password123"]
        let plistContent = NSDictionary(dictionary: sensitiveData)
        plistContent.write(toFile: filePath, atomically: true)
        
        return true
    }
}
        
        

The above Swift code is for an iOS application where the AppDelegate class is set as the entry point of the application. Here, the application is storing sensitive data (username and password) in a plist file in the application's Document directory.

This directory is backed up by default in iOS, which means that the sensitive data is also backed up and can be accessed if the backup is compromised. This is a security vulnerability as it can lead to information leakage. The plist file "SensitiveData.plist" is created and written into the Document directory of the application.

The NSSearchPathForDirectoriesInDomains function is used to get the path to the Document directory of the application. The sensitive data is then written to a plist file in this directory using the write(toFile:atomically:) function of NSDictionary.

This function writes the contents of the dictionary to a file at the specified path ( filePath), and if the atomically parameter is true (as it is in this case), the dictionary's contents are written to a temporary file, and then — assuming no errors occur — the temporary file is renamed to the path specified by filePath.

This means that the sensitive data (username and password) is stored in a file that is backed up and can be accessed if the backup is compromised.

Steps

  • Remove the code that writes sensitive data to a file.
  • Avoid storing sensitive data in plain text.
  • Implement secure storage mechanisms such as Keychain or encrypted databases to store sensitive data.
  • Ensure that the backup feature is disabled for sensitive data.
  • Regularly review and update the application's security configuration to address any potential vulnerabilities.

Compliant code

        import UIKit
import Security

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        
        // Removed the code that writes sensitive data to a file.
        // Instead, we are storing the sensitive data in Keychain.
        let username: String = "admin"
        let password: String = "password123"
        
        let usernameData = username.data(using: String.Encoding.utf8)!
        let passwordData = password.data(using: String.Encoding.utf8)!
        
        let usernameQuery: [String: Any] = [kSecClass as String: kSecClassGenericPassword,
                                            kSecAttrAccount as String: username,
                                            kSecValueData as String: usernameData]
        
        let passwordQuery: [String: Any] = [kSecClass as String: kSecClassGenericPassword,
                                            kSecAttrAccount as String: password,
                                            kSecValueData as String: passwordData]
        
        SecItemAdd(usernameQuery as CFDictionary, nil)
        SecItemAdd(passwordQuery as CFDictionary, nil)
        
        return true
    }
}
        
        

The updated code no longer writes sensitive data to a file. Instead, it stores the sensitive data in the Keychain, which is a secure storage mechanism provided by iOS. The Keychain stores the data in an encrypted format, which prevents it from being accessed without proper authentication.

The SecItemAdd function is used to add the sensitive data to the Keychain. The data is passed to this function as a dictionary, which includes the class of the item (in this case, a generic password), the account name, and the data itself.

By storing the sensitive data in the Keychain, we are ensuring that it is not included in backups, which addresses the original vulnerability. Furthermore, by encrypting the data, we are preventing it from being accessed in plain text, which provides an additional layer of security.

It is important to regularly review and update the application's security configuration to ensure that it remains secure as new vulnerabilities are discovered. This includes regularly reviewing the use of the Keychain and other secure storage mechanisms to ensure that they are being used correctly and effectively.

References