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:
- https://medium.com/@alexxjk_mar/blurring-app-screen-in-ios-multitasking-switcher-ea5bb3eedcd5
- https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06d-testing-data-storage#testing-auto-generated-screenshots-for-sensitive-information-mstg-storage-9
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
Mobile Security Testing guide describe following ways that can make hard to debug the application:
ptrace: It is most common system call that is used by the app to inspect and manipulate process of other process.
Reference:
sysctl: sysctl helps to check if any application try to debug the mobile app.
Reference:
Other 3rd party library such as IOSSecuritySuite provide anti-Tampering security. It an detect emulator, jailbreak device, debugger and common reverse engineering tool.
Reference:
- https://github.com/securing/IOSSecuritySuite
- https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06j-testing-resiliency-against-reverse-engineering#testing-anti-debugging-detection-mstg-resilience-2
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.
Commercial Tool: ixguard
Open Source Tool: Sirius-Obfuscator
M10 - Extraneous Functionality
Remove hidden backdoor functionality or other internal development security controls that are not intended to be released into a production environment.
Ensure all security controls are enabled in the production environment.
Do not store any sensitive data in the log file in production environment.