Thanks to the mobile era we have mobile apps for everything these days. Every business from a barber shop to huge retailers has apps so that they can be closer to their customers. On one hand, we really leverage this convenience but on the other hand, there are risks of exposing a lot of confidential information while using these apps. And it becomes very vital when dealing with payments and other sensitive information.
As a developer of these apps, it is our responsibility to put checks to make sure privacy and security are not compromised. This article focuses on detecting if an iOS device is jailbroken.
JailBroken detections techniques basically fall under these categories
If a device is jailbroken, there are some files that exist in the system. One common file is Cydia. Let take a look at the code below how we would check for the existence of these files.
func isDeviceJailBroken() ->Bool {
if access("/Applications/Cydia.app", F_OK) != -1 || access("/Applications/blackra1n.app", F_OK) != -1 || access("/Applications/FakeCarrier.app", F_OK) != -1 || access("/Applications/Icy.app", F_OK) != -1 || access("/Applications/IntelliScreen.app", F_OK) != -1 || access("/Applications/MxTube.app", F_OK) != -1 || access("/Applications/RockApp.app", F_OK) != -1 || access("/Applications/SBSettings.app", F_OK) != -1 || access("/Applications/WinterBoard.app", F_OK) != -1 || access("/Library/MobileSubstrate/MobileSubstrate.dylib", F_OK) != -1 || access("/Library/MobileSubstrate/DynamicLibraries/LiveClock.plist", F_OK) != -1 || access("/Library/MobileSubstrate/DynamicLibraries/Veency.plist", F_OK) != -1 || access("/private/var/lib/apt", F_OK) != -1 || access("/private/var/lib/cydia", F_OK) != -1 || access("/private/var/mobile/Library/SBSettings/Themes", F_OK) != -1 || access("/private/var/stash", F_OK) != -1 || access("/private/var/tmp/cydia.log", F_OK) != -1 || access("/System/Library/LaunchDaemons/com.ikey.bbot.plist", F_OK) != -1 || access("/System/Library/LaunchDaemons/com.saurik.Cydia.Startup.plist", F_OK) != -1 || access("/usr/bin/sshd", F_OK) != -1 || access("/usr/libexec/sftp-server", F_OK) != -1 || access("/usr/sbin/sshd", F_OK) != -1 || access("/bin/bash", F_OK) != -1 || access("/etc/apt", F_OK) != -1 {
return true
}
return false
}
iOS App allows registering for different schemes that allow opening our app directly from a weblink. If a device is jailbroken we can check for the existence of cydia:// scheme. Below is code that checks for the existence for the URL scheme.
func isDeviceJailBroken() -> Bool {
if let url = URL(string: "cydia://package/com.example.package") {
if UIApplication.shared.canOpenURL(url) {
return true
}
return false
}
}
JailBroken device alters the sandbox behavior of the app. Basically, the app can access or affect things outside of its sandbox. So we check by writing a file outside our sandbox and if we succeed then the device is jailbroken. This is how it will look in code.
func isDeviceJailBroken() -> Bool {
let error: Error? = nil
let stringToBeWritten = "This is a JB test."
do {
try stringToBeWritten.write(toFile: "/private/jailbreak.txt", atomically: true, encoding: .utf8)
} catch {
}
if error == nil {
return true
} else {
let fileManager = FileManager.default
do {
try fileManager.removeItem(atPath: "/private/jailbreak.txt")
} catch {
}
}
return false
}
Dynamic Linking provides a way for executables to take advantage of code provided by other libraries without compiling and be able to ship that code in the executable file. This greatly helps executables to reuse code without including a copy of these different libraries. On the other hand, static linking will include all code the executable needs are shipped with it.
Usually Anti jailbroken detection tools are loaded as dynamic libraries. iOS dynamic linker dyld loads all the dynamic libraries. So we can check the presence of anti-jailbreak-detection tools by looking at the names and numbers of libraries loaded into the current process. If an anti-jailbreak-detection tool is running, we know the device is jailbroken.
JailBroke device detection definitely adds a layer of security to your app. But by no way or means, the list above is enough to do that. At the end of the day, as a good developer, we need to practice all the good security practices to secure our iOS app.