It is necessary for every iOS developer to take care of code security, data storage security, data communication security and so on. Even though iOS mobile apps are not as vulnerable as other mobile(and hybrid) platforms development, it still has its own set of security vulnerabilities. It becomes every organisation’s/developer’s responsibility to make sure that the code, logic, data and its communication is secured in the right way so as to prevent any intruders tampering and understanding the code.
What are the security challenges in iOS?
- Data Leaks
Storing sensitive data such as access token, secrets and API credentials in an unsecured way can lead to interception or stealing of the user data — which matters the most!
- Unsecured communication
By making our application communicate with a server using a non-secure connection, such as HTTP, will be risky can lead to potential and easy attacks.
- Man in the middle attack
By using known techniques of faking Certificate Authority (CA) on the device, the attacker could imitate the target, and decrypt traffic, i.e. a ‘Man-in-the-Middle attack’. This could lead to a leak of sensitive data which would expose other vulnerabilities.
Below are the some of the best practices that are following at Halodoc:
1. Local Data Storage:
We don't use NSUserDefaults or Plist files to store confidential information like passwords, authentication tokens, API keys, etc. This is because all the information saved by NSUserDefaults is present in an unencrypted format in a plist file that can be found in the location Library -> Preferences -> $AppBundleId.plist inside your application bundle.
The best option to store the confidential information in iOS is Keychain:
Keychain Services API helps you solve these problems by giving your app a way to store the small amount of user data in an encrypted database called the keychain. In the keychain, you are free to save passwords, access tokens, and other secrets that the user explicitly cares about, such as credit card information or even short sensitive notes.
There are multiple ways to save data to Keychain in iOS:
- Third-party wrappers
- Cocoa pod keys
At Halodoc, we decided to go with Cocoapod keys because third-party libraries increase the IPA and also we have to wait for the updates if any issues encountered.
Cocoa pod keys:
Cocoapods provides a plugin called cocoapods-keys, which can be used to manage your app secrets securely.
Not only does cocoapods-keys keep the secrets out of the project sources, it holds them securely in your system keychain. When pods are installed or updated, the developer is asked for each key that has no value already stored. A Swift class is generated that contains obfuscated versions of keys and their values. As this class is built by running Cocoapods, the Pods/CocoaPodsKeys directory can be added to the
The plugin has many advantages:
1) It asks for a value to be provided for each key, avoiding the need to document the required secrets. This makes it very easy for each developer to get their project environment configured.
2) The source file is generated, which allows it to be easily kept out of source control.
3) Secrets are scrambled within the generated sources, to protect against the keys being extracted from the app binary.
4) It can be used from both Swift and Objective-C sources.
Core Data or Realm files are also stored as unencrypted database files in your application bundle. These frameworks internally use SQL queries to store its data and hence all the files are stored as .db files. One can easily copy these files to their computer and use a tool like sqlite3 to examine all the content in these database files. So when storing confidential information through these frameworks, it’s always advised to encrypt the data and save it.
Setting a Protection Level for a Particular File
Looking at single files first, there are several APIs that accept a protection type as an option.
If you’re writing a new file from Data/NSData, use
2. Enabling Debug Logs
Developers log to the console for debugging purposes while writing code, but most developers ignore the fact that logs are actually by default public and everyone who attaches a phone to a mac can read the console logs. We should avoid logging sensitive information and use system features such as
os_log with placeholders to hide private information in debug messages.
print() to be strictly avoided.
3. Web Views
Web views embedded within apps are often sandboxed properly by the operating system and frameworks. This is, however, web code, so the same rules (XSS, CSRF) apply. A cross-site scripting attack will allow session hijacking and access to the rest of the app.
We moved on to
WKWebView a while back.
We have below settings for WKWebview:
4. HTTPS Request with SSL pinning
The attacker can inject a 301 HTTP redirection response with an attacker-controlled server.
HTTPS should be the standard for any communication between the app and server. HTTPS encrypts all messages sent between client and server and protects them against simple man-in-the-middle attacks. On the client-side, there is nothing to do for us as a developer, because the TLS/SSL protocol will be handled by the operating system.
In fact, iOS expect you to use HTTPS by default, so we should try to avoid HTTP connections as much as possible. We should make sure to use the newest TLS version to make use of the current state-of-the-art encryption mechanism.
App Transport Security(ATS), is the iOS feature that forces mobile apps to connect to back-end servers using HTTPS, instead of HTTP, to encrypt data in transit. ATS enforces a minimum security level for communications between a mobile app and web services that support its functionality. From iOS 9.0 or later, ATS is enabled by default, NSAllowsArbitraryLoads key will be added in the Info.plist to enable or disable.
SSL pinning can help to prevent the Man In Middle Attack. We can use SSL pinning to ensure that the app communicates only with the designated server itself (matching certificate or public key), and the app will not allow any requests to be sent out to any untrusted server.
When the communication starts, the client examines the server’s SSL certificate and checks if the received certificate is trusted by the Trusted Root CA store or other user-trusted certificates.
A potential drawback of this is you need to update the app as well if a server certificate expires or the server’s SSL key is changed. Since you hardcode the trusted certificates, the app needs to be updated too.
5. Avoid Caching HTTPS Request/Responses
In the iOS NSURLSession framework, the default session configuration has a cache policy enabled. Hence, it creates the Cache.DB file to persist the request/response information till it does not expire.
Developers should use the ephermeralSessionConfiguration which doesn’t have persistent storage for caches, cookies or credentials. (Private Browsing)
Remove shared cache as and when required.
Disable global cache
NOTE: Caching helps network performance by reducing the number of requests, turning it off for any data you think is highly sensitive can be a good idea.
6. Disable Auto-Correction
For the user, sensitive input fields such as password, credit card info, etc, make sure to disable the auto-correction for the keyboard.
As keyboards used in iOS cache data used for auto-correction.
Strictly no to third-party keyboards as there will be change that sensitive information can be leaked through these keyboards.
7. Third-Party Library Usage Check
Third-party SDKs or frameworks can be a huge security risk for our applications. Since they get compiled with our app and run in the same sandbox they have the same rights as our app. This means a malicious SDK can fetch our users’ location if you asked for this permission or even read from our application data storage or keychain. We should not simply trust every library that we find on the internet. Hence it's advisable to cross-check its repository links, license and try running through some code review/vulnerability check tools. We should never ever disable ATS for them, even if any third party library requests to do so.
Third-party libraries should be kept up-to-date so that we can get the advantage of any security improvements. We use dependency check tool and MobSF, which scans the third-party libraries and provides vulnerability details.
8. Clear the Pasteboard
Once the application enters the background, remove the pasteboard contents in AppDelegate. If you are using a custom Pasteboard, replace [UIPasteboard generalPasteboard] with your custom pasteboard.
9. Prevent system snapshots
The system takes a snapshot of the currently visible screen before moving an application to the background. It might be an invitation to a leak as the visible screen contains sensitive information. When an application is entering in the background state, a developer should take appropriate steps to secure sensitive information. Hide or obscure passwords including other sensitive information that might get captured as part of the snapshot. Cover the visible screen with a splash image, blur the current view or present the blank screen.
Use below method to hide or blur sensitive information
10. Detect Screenshot
Users can capture a screen with the combination of a device hardware keys at any point-in-time.
APIs are available which triggers the notification on the screenshot event.
However, APIs are not available to prevent a user from taking a screenshot. As a developer, we can capture these events to take an appropriate action based on the business requirement.
11. Detect Screen Recording
A screen can be recorded using the iOS platform feature. An application can’t stop screen recording. However, it can detect a recording status and take relevant action as per the business requirement.
1) Overlay with blur view.
2) Exit gracefully
This blog talks about the methods we implemented and constantly identifying and fix the security issues to make sure that we are not leaking users data, so to keep the app secure for our customers. We continually improve our guidelines with latest findings from across the industry.
We are always looking out for top engineering talent across all roles for our tech team. If challenging problems that drive big impact enthral you, do reach out to us at firstname.lastname@example.org
Halodoc is the number 1 all around Healthcare application in Indonesia. Our mission is to simplify and bring quality healthcare across Indonesia, from Sabang to Merauke.
We connect 20,000+ doctors with patients in need through our Tele-consultation service. We partner with 2500+ pharmacies in 100+ cities to bring medicine to your doorstep. We've also partnered with Indonesia's largest lab provider to provide lab home services, and to top it off we have recently launched a premium appointment service that partners with 500+ hospitals that allows patients to book a doctor appointment inside our application.
We are extremely fortunate to be trusted by our investors, such as the Bill & Melinda Gates foundation, Singtel, UOB Ventures, Allianz, Gojek and many more. We recently closed our Series B round and In total have raised USD$100million for our mission.
Our team work tirelessly to make sure that we create the best healthcare solution personalised for all of our patient's needs, and are continuously on a path to simplify healthcare for Indonesia.