Objective C
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 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:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
//Clear keychain on first run in case of reinstallation
if (![[NSUserDefaults standardUserDefaults] objectForKey:@"FirstRun"]) {
// Delete values from keychain here
[[NSUserDefaults standardUserDefaults] setValue:@"1strun" forKey:@"FirstRun"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
}
- 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:
- https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide/0x06d-testing-data-storage#testing-local-data-storage-mstg-storage-1-and-mstg-storage-2
- https://developer.apple.com/documentation/security/keychain_services/…
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
- It is recommended to remove cached responses after logout.
[[NSURLCache sharedURLCache] 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.
Background Resume Screenshot Information Disclosure
- Overlay custom image when application move into background state.
@property (UIImageView *)backgroundImage;
- (void)applicationDidEnterBackground:(UIApplication *)application {
UIImageView *myBanner = [[UIImageView alloc] initWithImage:@"overlayImage.png"];
self.backgroundImage = myBanner;
[self.window addSubview:myBanner];
}
Reference:
- 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
- https://developer.apple.com/documentation/uikit/app_and_environment/…
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:
AFNetworking provides a complete network library solution.
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.
(void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler {
// Get remote certificate
SecTrustRef serverTrust = challenge.protectionSpace.serverTrust;
SecCertificateRef certificate = SecTrustGetCertificateAtIndex(serverTrust, 0);
// Set SSL policies for domain name check
NSMutableArray *policies = [NSMutableArray array];
[policies addObject:(__bridge_transfer id)SecPolicyCreateSSL(true, (__bridge CFStringRef)challenge.protectionSpace.host)];
SecTrustSetPolicies(serverTrust, (__bridge CFArrayRef)policies);
// Evaluate server certificate
SecTrustResultType result;
SecTrustEvaluate(serverTrust, &result);
BOOL certificateIsValid = (result == kSecTrustResultUnspecified || result == kSecTrustResultProceed);
// Get local and remote cert data
NSData *remoteCertificateData = CFBridgingRelease(SecCertificateCopyData(certificate));
NSString *pathToCert = [[NSBundle mainBundle]pathForResource:@"github.com" ofType:@"cer"];
NSData *localCertificate = [NSData dataWithContentsOfFile:pathToCert];
// The pinnning check
if ([remoteCertificateData isEqualToData:localCertificate] && certificateIsValid) {
NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrust];
completionHandler(NSURLSessionAuthChallengeUseCredential, credential);
} else {
completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, NULL);
}
}
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.
- Using ephemeral sessions is the best practise as it does not use persistent storage.
Reference:
https://developer.apple.com/documentation/foundation/urlsessionconfiguration/1410529-ephemeral
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.
Do not use arc4random() for random number generators as it is considered as an unsafe function in Objective C.
Use SecRandomCopyBytes for secure random number generation.
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
Reference:
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
Buffer Overflow:
- Do not use insecure function such as sprintf(), gets() and getpw()
- It is recommended to enforce a maximum size for
str
buffer gets_s(str, sizeof(str)); - Build application with following security flag to prevent overflow or underflow attack
- Enable Address Space Layout Randomization (ASLR) while building applications. From iOS 4.3 and macOS 10.7 it is enabled by default. Before this version you must explicitly enable it by adding -pie flag.
- Application should be compiled with a Non-Executable (NX) bit (-allow_stack_execute). This allows the OS to mark certain parts of memory as non-executable.
- Enable stack canaries to minimise the risk of corruption.
- -fstack-protector flag: It enables stack canaries only for functions that contain buffers over 8 bytes (a string on the stack, for example),and is enabled by default when compiling for macOS 10.6 and later.
- -fstack-protector-all flag: It enables stack canaries for all functions.
- D_FORTIFY_SOURCE : It add additional static and dynamic bounds checking to a number of functions that normally provide none (sprintf, vsprintf, snprintf, vsnprintf, memcpy, mempcpy, memmove, memset, strcpy, stpcpy, strncpy, strcat and strncat). If set to level 1 (-D_FORTIFY_SOURCE=1), only compile-time checking is performed. Level 1 is enabled by default when compiling for macOS 10.6 and later. At level 2, additional run-time checking is performed.
- MallocCorruptionAbort : An environment variable that tells 32-bit applications to abort if a malloc call would fail because of a corrupted heap structure. Aborting on heap corruption is automatically enabled for 64-bit applications.
Control flow statements such as “if”, “for”, “while”, “switch” and “try” should not be nested too deeply.
Implement proper error handling mechanism in case of exception:
void save() {
try {
saveDocument();
} catch (const std::exception& ex) {
log << "Exception while saving the document: " << ex.what();
}
}
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:
It is good practise to write critical portions of code in low-level C to avoid exposure and manipulation by the Objective-C runtime tools.
Reference:
M9 - Reverse Engineering
Do not hardcode any sensitive data in code.
Although objective C code cannot be obfuscated 100 % There are some commercial & open source tools available that can be used to obfuscate client code.
Commercial Tool: ixguard
Open Source Tool: iOS-Class-Guard, Objc-Obfuscator, PPiOS-Rename
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.
References
- https://mobile-security.gitbook.io/mobile-security-testing-guide/ios-testing-guide
- https://developer.apple.com/documentation
- https://rules.sonarsource.com/objective-c
- https://csrc.nist.gov/csrc/media/publications/sp/800-175b/archive/2016-03-11/documents/sp800-175b-draft.pdf
- https://stackoverflow.com/questions/4747404/delete-keychain-items-when-an-app-is-uninstalled/40732677
- [https://infinum.com/the-capsized-eight/how-to-make-your-ios-apps-more-secure-with-ssl-pinning] (https://infinum.com/the-capsized-eight/how-to-make-your-ios-apps-more-secure-with-ssl-pinning)