Why is it necessary to detect a jailbroken device?
Sometimes it’s necessary to restrict iOS app to run only on non-jailbroken devices. For example, it might be useful for media applications to make content piracy more difficult or to protect against more general application piracy.
To make it clear, it’s not possible to detect jailbroken device in all cases, because with proper motivation every implemented jailbreak check can be fooled. However, making hacking of the application more difficult by introducing additional security checks is always welcome.
Here’s a couple of ways to check if application is currently running in jailbroken environment:
Existence of symbolic links
Jailbreaking process involves moving multiple important iOS file system folders between different locations. When Applications folder is moved, it’s important that the original path to Applications will still be valid. Therefore, symbolic links are created instead of the original folder. Existence of common symbolic links indicates that the device has been jailbroken.
Use lstat to get the symbolic link status on iOS:
Existence of files that are common for jailbroken devices
One of the most common and easiest way to detect a jailbroken device is to check for files that are common for jailbroken devices, like Cydia.app or MobileSubstrate.dylib. Example implementation is pretty easy, checking for a list of popular files:
Reading and writing in system directories (sandbox violation)
In a non-jailbroken environment applications can only read and write inside the application sandbox. If the application is able to access files outside of its sandbox, it’s probably running on the jailbroken device. Example implementation:
Without any obfuscation it’s relatively easy to find the jailbreak checks and remove them from the application code. Therefore, it’s really important to hide jailbreak checks.
Objective-C strings and methods are the first ones to be found in the application code. Therefore, it’s recommended to implement jailbreak checks as inline C functions and not use Objective-C strings directly. In the example implementations I have used relatively easy obfuscation, which is also easy to detect and break (See GIST). However, for an inexperienced attacker it might be a strong barrier and it’s better than using Objective-C strings directly.
The example project can be found here: