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:

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:

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:

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

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.

M10 - Extraneous Functionality

References