Swift

Recommendations for OWASP Mobile TOP 10 2016

M1 - Improper Platform Usage

  • Implement proper keychain security to store sensitive data.

Keychain Security

  • Make sure application wipe out user’s data once user perform logout operation

  • By default keychain data associated with the application does not get wiped out after uninstallation. If user reinstall the app and try to login with different user/role then it may accidentally give access of previous user acount. To prevent this it is important to check & delete keychain data of associated appliation at the time of first launch after reinstallation. Following code can be use for wiping procedure:

    let userDefaults = UserDefaults.standard

    if userDefaults.bool(forKey: "hasRunBefore") == false {
        // Remove Keychain items here

        // Update the flag indicator
        userDefaults.set(true, forKey: "hasRunBefore")
        userDefaults.synchronize() // Forces the app to update UserDefaults
    }
  • keychain is often misconfigured. iOS provide following restrictive protection class as defined by kSecAttrAccessible attribute:
    - kSecAttrAccessibleAlwaysThisDeviceOnly: Keychain data can always be accessed, regardless of device is locked or not. These data won't be  included in an iCloud or local backup.
    - kSecAttrAccessibleAfterFirstUnlock: Keychain data can't be accessed after a restart until the device has been unlocked once by the user.
    - kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly: Keychain data can't be accessed after a restart until the device has been unlocked once by the user. Items with this attribute do not migrate to a new device. Thus, after restoring from a backup of a different device, these items will not be present.
    - kSecAttrAccessibleWhenUnlocked: Keychain data can be accessed only while the device is unlocked by the user.
    - kSecAttrAccessibleWhenUnlockedThisDeviceOnly: The data in the Keychain item can be accessed only while the device is unlocked by the user. The data won't be included in an iCloud or local backup.
    - kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly: Keychain data can be accessed only when the device is unlocked. This protection class is only available if a passcode is set on the device. The data won't be included in an iCloud or local backup.

Reference:

M2 - Insecure Data Storage

  • It is recommended to not store any sensitive data at the client side.

  • If an application uses oauth for the login then only refresh token can be saved locally on keychain.

  • Incase of offline authentication, Use Password-Based Key Derivation Function 2 (PBKDF2) to login.

Information Leakage via HTTPS response Cache

  • Remove all cached response after logout operation.
    URLCache.shared.removeAllCachedResponses()
  • Implement Empemeral configuration property of URLSession instead of cookie, which store session related data in RAM instead of local cache. .ephmeral
  • Cache can be also disabled by setting the cache poliy to .notAllowed. It prevent storing cache in memory or disk.

Reference:

Background Resume Screenshot Information Disclosure

  • Following code cane be use to blur sensitive data before being backgrounded.

Refer https://medium.com/@alexxjk_mar/blurring-app-screen-in-ios-multitasking-switcher-ea5bb3eedcd5 for the full implementation.

    func prepareForEnteringIntoBackgroundMode() {
        let imageView = UIImageView()
        imageView.frame = window!.frame
        imageView.tag = self.blurViewTag
        imageView.contentMode = .scaleToFill
        imageView.backgroundColor = UIColor.gray
        window?.addSubview(imageView)
        applyBlurEffect(toImage: &cover)
        imageView.image = cover
    }

    private func prepareForEnteringIntoActiveMode() {
	    self.window?.viewWithTag(self.blurViewTag)?.removeFromSuperview()
    }

Reference:

M3 - Insecure Communication

  • It is recommended to not use insecure protocols such as HTTP, FTP etc.

  • Avoid sending sensitive data over alternate channels (e.g, SMS, MMS, or notifications).

  • All communication should be done over secure channel that support following:

    • Do not support SSL versions of protocols.
    • Do not support ciphers whose size is less than 128 bits.
    • Disable NULL, MD5, SHA1, MD4, RC4, CBC ciphers suites.
    • SSL certificates should be valid and generated by CA.
  • By default, iOS 9 or above enable App Transport Security (ATS). Implement ATS Exceptions correctly.

  • Ensure all NSURL calls do not allow self signed or invalid certificates.

  • It is recommended best practices to support only TLSv1.2 and TLSv1.3.

  • Implement SSL pinning to prevent MiTM attack.

SSL Pinning

This can be achieved by writing it from scratch or by using any of the following frameworks.

  • TrustKit is an open source framework that makes it easy to implement SSL pinning on objective C and Swift both.

  • NSURLSession is an API provided by Apple for secure communication.

    func URLSession(session: NSURLSession,  didReceiveChallenge challenge: NSURLAuthenticationChallenge, completionHandler (NSURLSessionAuthChallengeDisposition, NSURLCredential?) -> Void) {
        let serverTrust = challenge.protectionSpace.serverTrust
        let certificate = SecTrustGetCertificateAtIndex(serverTrust!, 0)

        // Set SSL policies for domain name check
        let policies = NSMutableArray();
        policies.addObject(SecPolicyCreateSSL(true, (challenge.protectionSpace.host)))
        SecTrustSetPolicies(serverTrust!, policies);

        // Evaluate server certificate
        var result: SecTrustResultType = 0
        SecTrustEvaluate(serverTrust!, &result)
        let isServerTrusted:Bool = (Int(result) == kSecTrustResultUnspecified || Int(result) == kSecTrustResultProceed)

        // Get local and remote cert data
        let remoteCertificateData:NSData = SecCertificateCopyData(certificate!)
        let pathToCert = NSBundle.mainBundle().pathForResource(githubCert, ofType: "cer")
        let localCertificate:NSData = NSData(contentsOfFile: pathToCert!)!

        if (isServerTrusted && remoteCertificateData.isEqualToData(localCertificate)) {
            let credential:NSURLCredential = NSURLCredential(forTrust: serverTrust!)
            completionHandler(.UseCredential, credential)
        } else {
            completionHandler(.CancelAuthenticationChallenge, nil)
        }
    }

Reference:

M4 - Insecure Authentication

  • Implement session based on application business requirement:

    • For highly critical applications we recommend terminating the user’s session if the session is inactive for more than 5 minutes.
    • Re-Authenticate users if the application returns from a background state.
    • Terminate the user’s session properly at client and server both sides if the user clicked on the logout button.
    • Make sure that the user is forced to choose alphanumeric characters for passwords.
  • Perform authentication checks at the server side.

  • Make sure that the user is forced to choose alphanumeric characters for passwords.

  • Implement 2FA check in sensitive application.

  • Make sure to have authentication check on all post authenticated API.

M5 - Insufficient Cryptography

  • For symmetric encryption AES with a key that’s at least 128 bits and a secure mode should be used as the preferred algorithm.

  • For asymmetric encryption RSA with 2048 bit or ECC with secure curve should be secure.

  • Avoid using below listed cryptographic algorithms as these are known to be weak

    • DES, 3DES
    • RC2
    • RC4
    • BLOWFISH
    • MD4
    • MD5
    • SHA1
  • The following algorithms are recommended:

    • Confidentiality algorithms: AES-GCM-256 or ChaCha20-Poly1305
    • Integrity algorithms: SHA-256, SHA-384, SHA-512, Blake2, the SHA-3 family
    • Digital signature algorithms: RSA (3072 bits and higher), ECDSA with NIST P-384
    • Key establishment algorithms: RSA (3072 bits and higher), DH (3072 bits or higher), ECDH with NIST P-384

M6 - Insecure Authorization

  • Applications should avoid using guessable numbers as id reference.

  • Authorization checks should happen at the server sides.

  • Enforce authorization check on every request at the server side.

M7 - Client Code Quality

  • Maintain consistent coding patterns that everyone in the organization agrees upon.

  • Write code that is easy to read and well-documented.

  • Control flow statements such as “if”, “for”, “while”, “switch” and “try” should not be nested too deeply.

Reference:

M8 - Code Tampering

Reference:

M9 - Reverse Engineering

  • Do not hardcode any sensitive data in code.

  • Following are some commercial & open source tools available that can be used to obfuscate client code.

M10 - Extraneous Functionality

References