Introduction:
Mobile technology has come a long way in a relatively short space of time. In less than 30 years we’ve moved away from big, brick-like cellular phones and a nascent internet to a world of super-slim and powerful smartphones, tablets and convertible laptops that are able to transmit and store data, as well as hook up the internet, with a simple tap.
While these devices offer us increased internet connectivity and day-to-day convenience, they also carry considerable security risks.
Shown below is OWASP’s top 10 list for security threats faced by mobile apps today:
Imagine you are an app developer and you write an app that you are proud of and are certain will be productive for people. You push that application into production and what’s more, It does become successful and loads of people start using it.
Then one day you get the news that a 1000 users of your application reported that sensitive data belonging to them that they accessed through your app is publicly doing the rounds of the internet. What if that happened just because of a simple line of code that checked the authenticity of a password and returned a boolean had been tampered with? A piece of code written by you. Scary thought isn’t it?
My intention with this blog is to simply highlight that such things can and do happen from time to time, and as developers we should be aware of them and come up with ways to prevent them from happening.
Some of the methods employed by hackers to bypass security protocols and gain access to your file system or modify sensitive code in order to retrieve critical data from your application are:
Repackaging:
iOS apps downloaded from Apple’s App Store are encrypted and signed by Apple. They can only run on devices that are able to decrypt them and validate their signatures. To pirate such an app, adversaries must create a cracked (decrypted and unsigned) version of the app and republish it on third-party sites. Victims can then use approved (non-jailbroken) iDevices to download and execute these apps from these third-party sites.
To decrypt the app, adversaries use tools such as clutch. An adversary uses clutch to decrypt the application and store it locally in a state that can be analyzed further by a decompiler. To execute this application, the adversary must run the tool and the corresponding application in a jailbroken environment.
Mitigation:
- Insert security controls at the appropriate code entry points that the application will invoke as early as possible within the app’s lifecycle. These controls should adequately detect if the device is running in a jailbroken environment. In the event that the app is running in said environment, the code should force the application to react, such as provide server notification, fail in a subtle way or even terminate for high risk, critical applications
- Jailbreak detection controls should inspect the environment for particular indicators such as the presence of particular files, file permissions, and running processes.
Swizzling:
The Objective-C runtime lets an application modify its mapping from a selector (method name) to an implementation. In doing so, an application can patch a method and execute additional code each time the original method is invoked by the runtime engine. This is typically done when an organization cannot inspect or modify the original method.
An attacker can take advantage of this feature by inspecting the metadata of an iOS app and identify methods that are performing sensitive operations. Then the attacker can inject a malicious dynamic library onto the device to intercept API calls made to the sensitive method and redirect them to the dynamic library.
E.g:
Consider the following method:
//Transaction-request delegate -(IBAction) performTransaction: (id) sender { if ([self loginUserWithUsername: username incomingPassword: password] != true) { UIAlertView * alert = [ [UIAlertView alloc] initWithTitle: @ "Invalid User" message: @ "Authentication Failure" delegate: self cancelButtonTitle: @ "OK" otherButtonTitles: nil ]; [alert show]; return; } // Perform sensitive operation here }
An attacker can use a tool like Mobile Substrate to intercept the method call to loginUserWithUserName:incomingPassword: to always return true, in doing so tricking the application into performing sensitive code in the perform Transaction method.
Mitigation:
- If the application is intentionally performing a swizzle, an adversary will exploit this design decision and swizzle this particular method as it will be a reliable entry point into the application. Strongly consider redesigning and eliminating this design feature.
Security Control Bypass:
Security controls are methods or pieces of code that are responsible for enforcing business policies within software. Examples of security controls include the following:
- Authentication
- Authorization
- Data Validation
- Session Management
- Exception Handling
- Logging and Auditing
- Code Signing
- Licensing
Attacks on security controls are very common. For example, attackers alter control flows to bypass authentication checks or licensing requirements.
Mitigation:
- Perform a checksum of code that contains critical instruction-branch code. Checksum validation of this code should occur immediately before the application executes this code.
- Add additional checksums that check the original checksum to ensure that an adversary is unable to modify the original checksum.
- Additional checksum validations of the code and other checksums should occur in other random parts of the application to ensure redundant validation that is unpredictable to the adversary
- Ensure that the checksum code does not have a binary signature that is easily identifiable by the adversary. Otherwise, the adversary will be able to identify all checksum instances and bypass them.
Automated Jailbreak Detection:
Many security-sensitive iOS apps such as mobile banking and peer-to-peer payment apps require a secure environment in order to execute. These apps have capabilities to detect whether their host is sound. They may choose to not execute in jailbroken environments due to valid security concerns. The jailbreak-detection mechanisms implemented within many apps are exposed in the clear, without protection, and can be defeated easily.
There are tools like xCon that can circumvent jailbreak-detection checks implemented in a number of iOS apps. It has succeeded in attacking many apps.
Mitigation:
- Follow the risk mitigation strategy of method swizzling prevention to prevent an adversary from weakening a jailbreak detection control already implemented.
- Follow the risk mitigation strategy of branch-failure prevention in order to prevent an adversary from making unauthorized changes to control-flow related to Jailbreak detection.
- Implement all of the appropriate jailbreak detection algorithms disclosed through various jailbreaking communities such as xCon.
Data storage (Don’t store or store securely):
If possible, try not to store any passwords in your application.
When storage is necessary for small data fragments, use the iOS keychain. In addition store all strings in encrypted format, even in the keychain. Never use plists for data storage (NSUserDefaults).
For larger data-sets, files, and databases (coredata or sqlite), utilize Apple’s Data Protection API with a minimum of the designation NSFIleProtectIonCompleteUnlessOpen.
Mitigation:
- Use iOS data protection classes and encryption to hide data that is sensitive.
- If you need to have passwords stored on your device, try to come up with techniques to make it that much more difficult for someone who has access to your file system to be able to just “Strings” out your sensitive information. E.g. you could try to break your password into different parts and encrypt them using different keys.
- Keep updating your passwords as frequently as possible.
- Use encrypted core data.
- If you are using sqlite database in your application, you could go for sqlcipher. It has a small footprint and great performance so it’s ideal for protecting embedded databases and well suited for mobile development. It encrypts the whole database and uses the latest encryption techniques to do so.
Conclusion:
In conclusion I would like to say that protecting your application from attacks is a never-ending process. No matter how well you try to protect your application, attackers will keep coming up with new and innovative ways to bypass your guard.
What we need to ensure as developers is:
- Identify security risks and attack vectors.
- Make the process of actually obtaining the data for the attacker as difficult and time consuming as possible.
- Make sure that you keep updating your techniques and APIs to the latest industry standards.