Insecure functionality - Swift

Insecure functionality - Swift

Need

Secure functionality implementation

Context

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

Description

Non compliant code

        import UIKit
import Foundation

class ViewController: UIViewController {
    
    @IBOutlet weak var passwordField: UITextField!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }
    
    @IBAction func loginButtonTapped(_ sender: Any) {
        let password = passwordField.text
        validatePassword(password: password!)
    }
    
    func validatePassword(password: String) {
        if password == "123456" {
            // grant access
            print("Access granted")
        } else {
            // deny access
            print("Access denied")
        }
    }
}
        
        

In this Swift code for an iOS application, we have a ViewController with a password field. The password field is a UITextField where users input their password. The loginButtonTapped function is triggered when the login button is tapped.

The vulnerability lies in the validatePassword function. The function compares the input password with a hardcoded string "123456". If the input password matches this string, access is granted, otherwise, access is denied.

This is an insecure functionality because the password is hardcoded into the application and is the same for all users. An attacker can easily reverse engineer the application, discover the hardcoded password, and gain unauthorized access to the system.

Additionally, the password is a very weak one (a sequence of numbers), which can easily be guessed or brute-forced. This further increases the risk of unauthorized access.

Finally, the password is stored in plain text in the source code and is printed out in the console. This means that anyone with access to the console logs or the source code can see the password. This is a serious security issue as passwords should always be stored securely and never be logged or displayed in plain text.

Steps

  • Avoid hardcoding sensitive information, such as passwords, directly in the code.
  • Implement a secure authentication mechanism, such as using a secure hash function to store and compare passwords.
  • Consider using a secure authentication framework or library that provides built-in security features.
  • Implement proper input validation and sanitization to prevent any malicious input from being processed.
  • Implement secure communication protocols, such as HTTPS, to protect sensitive data during transmission.
  • Regularly update and patch the application to address any known security vulnerabilities.
  • Perform security testing, such as penetration testing, to identify and fix any potential vulnerabilities.
  • Follow secure coding practices and guidelines to minimize the risk of introducing vulnerabilities.

Compliant code

        import UIKit
import Foundation
import CryptoKit

class ViewController: UIViewController {
    
    @IBOutlet weak var passwordField: UITextField!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }
    
    @IBAction func loginButtonTapped(_ sender: Any) {
        guard let password = passwordField.text else { return }
        validatePassword(password: password)
    }
    
    func validatePassword(password: String) {
        let hashedPassword = hashPassword(password: password)
        // Compare the hashed password with the stored hashed password
        if hashedPassword == getStoredHashedPassword() {
            // grant access
            print("Access granted")
        } else {
            // deny access
            print("Access denied")
        }
    }
    
    func hashPassword(password: String) -> String {
        let inputData = Data(password.utf8)
        let hashed = SHA256.hash(data: inputData)
        return hashed.compactMap { String(format: "%02x", $0) }.joined()
    }
    
    func getStoredHashedPassword() -> String {
        // Fetch the stored hashed password from secure storage
        // This is just a placeholder. In a real application, you would fetch this from a secure place like Keychain.
        return "storedhashedpassword"
    }
}
        
        

The original code had a hardcoded password, which is a major security vulnerability. The updated code now uses the CryptoKit library to hash the password input by the user. This hashed password is then compared with a stored hashed password (which should be securely stored and retrieved, for example, using iOS Keychain).

This way, even if an attacker gains access to the system, they would only see the hashed password, which is useless without the original password.

The validatePassword function now takes the user's input, hashes it, and compares it to the stored hashed password. If they match, access is granted; otherwise, access is denied.

The hashPassword function takes a password, converts it to Data, hashes it using SHA256, and then converts the hashed data to a hexadecimal string.

The getStoredHashedPassword function is a placeholder for fetching the stored hashed password from a secure place. In a real application, you would fetch this from a secure place like Keychain.

The loginButtonTapped function now uses optional binding to safely unwrap the text from the password field. If the text is nil, the function simply returns without doing anything.

This code is more secure as it doesn't expose any sensitive information, uses secure hashing for password comparison, and safely handles user input.

References