Slide 1

Slide 1 text

Xebia

Slide 2

Slide 2 text

About Xebia

Slide 3

Slide 3 text

Training • 6th November A Swift Kickstart: Introducing the Swift Programming Language • 7th November iOS 8 Quickstart: The fundamental pillars of iOS development

Slide 4

Slide 4 text

Welcome

Slide 5

Slide 5 text

Schedule • 17:00 - 18:00 entry • 18:00 - 19:00 Indian Diner • 19:00 Secure Coding practices on iOS • 20:00 Today widgets on iOS

Slide 6

Slide 6 text

Secure coding practices on iOS

Slide 7

Slide 7 text

Disclaimer These are my observations, I am not responsible for omissions on anything I present here or your own mistakes. This is not the end- all last word on iOS security.

Slide 8

Slide 8 text

Why need a secure iOS app?

Slide 9

Slide 9 text

SSL Concerns • Loads and loads of root CA's • Government interference • Not all CA's generate certificates with the proper algorithmic requirements • Man in the Middle attacks • Heartbleed

Slide 10

Slide 10 text

Who's ever used: #if DEBUG @interface NSURLRequest (DummyInterface) + (BOOL)allowsAnyHTTPSCertificateForHost:(NSString*)host; + (void)setAllowsAnyHTTPSCertificate:(BOOL)allow forHost:(NSString*)host; @end #endif Apple does not approve private API

Slide 11

Slide 11 text

Or: continueWithoutCredentialForAuth enticationChallenge

Slide 12

Slide 12 text

HTTP and HTTPS requests cached by default to disk

Slide 13

Slide 13 text

The docs of sharedURLCache say: Applications that do not have special caching requirements or constraints should find the default shared cache instance acceptable. An application with more specific needs can create a custom NSURLCache object and set it as the shared cache instance using setSharedURLCache:. The application should do so before any calls to this method.

Slide 14

Slide 14 text

URL Loading System Programming guide says: The example in Listing 7-1 prevents the on-disk caching of HTTPS responses. It also adds the current date to the user info dictionary for responses that are cached. Pre iOS 6 disk caching of HTTPS responses was not the default.

Slide 15

Slide 15 text

SSL Pinning

Slide 16

Slide 16 text

Why would you want to do SSL pinning? - Prevents MITM - Only allow one certificate or root CA - Some mitigation against crappy CA's - Requires a secure client

Slide 17

Slide 17 text

Here's a way First inform the system we want to do it ourselves: - (BOOL)connectionShouldUseCredentialStorage:(NSURLConnection *)connection { return NO; }

Slide 18

Slide 18 text

Then perform magic - (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge { BOOL isNotValid = NO; id sender = challenge.sender; NSURLProtectionSpace *protectionSpace = challenge.protectionSpace; if (protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust) { SecTrustRef serverTrustContext = protectionSpace.serverTrust; SecTrustResultType trustResult; NSError * error; // // Load certificate // // Prepare trust evaluation // SecTrustEvaluate(serverTrustContext, &trustResult); // // Decide what to do based on trust result // if (isNotValid){ #warning certificate is not valid, inform the end-user and cancel flow [sender cancelAuthenticationChallenge:challenge]; } } else { [sender continueWithoutCredentialForAuthenticationChallenge:challenge]; } }

Slide 19

Slide 19 text

Load certificate data, prepare trust evaluation if (nil == self.certificateData) { NSString * certificatePath = [[NSBundle mainBundle] pathForResource:@"rootca" ofType:@"crt"]; if (certificatePath != nil) { self.certificateData = [NSData dataWithContentsOfFile:certificatePath options:0 error:&error]; } else { isNotValid = YES; } } if (error == nil) { SecCertificateRef certificate = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)self.certificateData); if (nil == certificate) { isNotValid = YES; } else { CFMutableArrayRef certificatesArray = CFArrayCreateMutable(NULL, 1, &kCFTypeArrayCallBacks); CFArraySetValueAtIndex(certificatesArray, 0, (const void *)certificate); SecTrustSetAnchorCertificates(serverTrustContext, certificatesArray); SecTrustSetAnchorCertificatesOnly(serverTrustContext, true); CFRelease(certificatesArray); CFRelease(certificate); } }else { isNotValid = YES; }

Slide 20

Slide 20 text

Based on trust result decide what to do switch (trustResult) { case kSecTrustResultProceed: case kSecTrustResultUnspecified:{ NSURLCredential *credential = [NSURLCredential credentialForTrust:serverTrustContext]; [sender useCredential:credential forAuthenticationChallenge:challenge]; break; } // case kSecTrustResultRecoverableTrustFailure: Maybe try and recover from an acceptable cert failure here? default:{ isNotValid = YES; } }

Slide 21

Slide 21 text

The Simulator doesn't do SSL like a device, so you would need more magic: - (BOOL)connection:(NSURLConnection * const)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace * const)protectionSpace { NSString * const method = [protectionSpace authenticationMethod]; return [method isEqualToString:NSURLAuthenticationMethodServerTrust]; }

Slide 22

Slide 22 text

- (void)connection:(NSURLConnection * const)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge * const)challenge { id sender = [challenge sender]; NSURLProtectionSpace * const protectionSpace = [challenge protectionSpace]; if ([[protectionSpace authenticationMethod] isEqualToString:NSURLAuthenticationMethodServerTrust]) { SecTrustRef serverTrustContext = [protectionSpace serverTrust]; SecTrustSetAnchorCertificatesOnly(serverTrustContext, false); SecTrustResultType trustResult; SecTrustEvaluate(serverTrustContext, &trustResult); switch (trustResult) { case kSecTrustResultProceed: case kSecTrustResultUnspecified: // Certificate validated okay. break; default: { // Certificate didn't validate. Log, the first time, that the workaround is active. static BOOL userWarned = NO; if (!userWarned) { userWarned = YES; NSLog(@"**************** Server SSL certificate doesn't validate; disabling validation. **************"); } break; } } NSURLCredential * const credential = [NSURLCredential credentialForTrust:[protectionSpace serverTrust]]; [sender useCredential:credential forAuthenticationChallenge:challenge]; } else { [sender continueWithoutCredentialForAuthenticationChallenge:challenge]; } }

Slide 23

Slide 23 text

Switch between the two incantations by be #pragmatic during compile-time: #if TARGET_IPHONE_SIMULATOR //Do simulator stuff #else //Do device stuff #endif

Slide 24

Slide 24 text

A self generated Root CA certificate can be installed with Apple Configurator on your test devices. All certificate checks then behave as if the certificate is a regular CA.

Slide 25

Slide 25 text

It's an #if not an #ifdef Actual production bug. Oh shit, why did I not check that? — Not to be named developer's comment

Slide 26

Slide 26 text

He was not shot, cause normally he's a rockstar

Slide 27

Slide 27 text

Encryption • Use CommonCrypto • And/or RNCryptor • Use an IV!! It is important • Padding is a must

Slide 28

Slide 28 text

Keychain Developers storing secure items into NSUserDefaults will be taken out back, shot, dumped in a ditch, soaked with petrol and set on fire for good measure. Keychain SecItemAdd(…); SecItemUpdate(…); SecItemCopyMatching(…);

Slide 29

Slide 29 text

Do use the correct kSecAttrAccessible value CFTypeRef kSecAttrAccessibleWhenUnlocked; CFTypeRef kSecAttrAccessibleAfterFirstUnlock; CFTypeRef kSecAttrAccessibleAlways; CFTypeRef kSecAttrAccessibleWhenUnlockedThisDeviceOnly; CFTypeRef kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly; CFTypeRef kSecAttrAccessibleAlwaysThisDeviceOnly;

Slide 30

Slide 30 text

SQLite and SQL injection Don't do this: NSString *statement = [NSString stringWithFormat:@"SELECT username FROM users where uid = '%@'",uid]; Instead do this: objectivec const char *sql = "SELECT username FROM users where uid = ?"; sqlite3_prepare_v2(db, sql, -1, &selectUid, NULL); sqlite3_bind_int(selectUid, 1, uid); int status = sqlite3_step(selectUid);

Slide 31

Slide 31 text

Data protection Use the API's when applicable Same story reason you would want to use the keychain.

Slide 32

Slide 32 text

References -Apple Secure Coding Guide -ISEC PDF