
Thank you very much. Good afternoon everyone. Uh thank you for being here and uh thank you to the organizers for giving me this stage. Um the topic uh we're going to look at today is iOS application penetration testing and uh more specifically how we can make it less painful than it usually is. So let's get started. A quick word about me before we get into the technical content. Uh my name is Faralev. Um I'm the founder of my pentesting uh boutique uh called Shaman Red Team. Um I am a penetration tester and an appseac engineer. uh which means I spend a lot of time um penetration testing uh applications and helping developers to make sure that I can't
bring break into their applications. Outside of that uh I am a PhD student and a lecturer. So I also spent some time teaching and the topics I care about most are uh web mobile app hacking uh and security design and software development and a bit of uh cryptography and internet of things security. So here is the agenda for today's talk. First I want to talk about the challenges that makes uh iOS pentesting difficult. Then we'll go through some uh iOS app basics. Uh after all we will talk about um jailbreaking what it is why we care about it. Then we will get to the security model of iOS the attack surface. Uh we focus on during audits
and the difference between static and dynamic analysis. and we will talk about how to sideloadad iOS apps onto our own iOS devices. We will see how to uh use dynamic instrumentation methods and we will have a short demo at the end. So let's get started. So let me begin with my story how I ended up uh diving into this research in the first place. Uh here is how it began. Um, I spent weeks hunting for a jailbreakable device that was actually in a good condition and useful for testing. And when I when I finally found one, it felt like a victory really. uh but until I realized that its iOS version was lower than uh what my target
app required as a minimum and simply the app uh simply refused to install and naturally I wasn't about to give up my jailbreak. So I made developers uh suffer a little bit by tweaking the application so that it works on the lower iOS version and surprisingly it worked uh for a couple of weeks and then uh things went wrong again. Uh I forgot the passcode on my device and the only solution was a full reset uh which means um updating to the latest iOS version and saying goodbye to the jailbreak. So there I was no jailbreak um a newer iOS version that had no jailbreak uh available public jailbreak and uh my target app I still needed to
test and uh my deadline and that's the time I um where I had two choices. I could either give up or figure out how to do this without um a jailbreak. So I chose the second one and this is basically how this talk was born. So uh why does this uh story matter? Uh because every single u thing I described is a uh common issue when it comes to iOS security audits. Uh for example, finding a jailbreakable devices is uh harder every year. Recent versions of uh iOS uh don't have a public jailbreak at all. And here is the cruel twist. Some apps require a higher minimum iOS version. So even if you have a jailbreak jailbroken
device, uh the app might still refuse to install. And uh on top of that, jailbreak is not free. It may disable some features uh like biometric uh authentication, face ID and touch ID which makes it uh impossible to test uh biometric authentication properly uh during a security audit. And finally uh sometimes you simply do not want to jailbreak your own personal device because uh you may use it for day-to-day life. So the challenge is real and the solution we are going to uh explore today is how do we do meaningful uh pen testing uh even when we uh don't have a jailbroken device and jailbreak is not an option. So uh before we go any deeper uh let's
make sure we all share the same foundation. Uh what's an iOS app? Technically uh iOS applications are usually written in one of two languages. Um the older language is um Objective C and the newer and more common language is Swift. Uh developers write these apps in Xcode which is uh Apple's uh development ecosystem and it only runs on Mac OS. Uh once uh an app is built, it gets distributed through uh the Apple App Store. Uh and before it can even be installed on a user's device, it must be signed with a valid uh Apple developer certificate. And the signing is Apple's way of saying that we know who made this app and we trust it and at least we
verified the developer. Now on the device itself uh each iOS app uh runs on an isolated process and operates within a strict sandbox uh limiting access to other apps and uh system resources. And one more thing uh that the app package is encrypted uh uh on disk. Uh it can only get decrypted uh when the app is actually uh being executed. So uh let's talk about jailbreaking. Uh what is it really? Why do we care about it? First of all, iOS is a uh is very different from Android in one key way. Uh it doesn't uh give us uh a shell by default. Uh and jailbreaking is the process of opening that door anyway. and uh it removes the restrictions that
iOS uh normally enforces and uh gives you uh deep system access essentially root level access to the device. But jailbreaking is not something you just click a button uh to do. It is achievable through a an actual security vulnerability uh on iOS devices. Uh once you have a jailbroken device uh you can install things like uh custom themes uh community apps uh and uh you may have you can have package managers like slow allow installing community uh software which wouldn't be allowed um on Apple store Apple app store. So which devices can actually be jailbroken? uh the best public resource uh for this is this website here and uh it shows us for any device and iOS
combination whether there's a jailbreak available the devices that are um currently jailbreakable across all their supported uh versions iOS versions are older models you can see them here and uh this is due to the hardware level vulnerability and that allows jailbreak on any iOS version they can run. And for iOS version 17 and newer, which is basically every modern uh iOS device sold, there is no jailbreak available, at least publicly. And uh we can look at this table here. Uh for my iPhone XS, uh we can uh look at the um jailbreak options. And uh we can see NA entries uh which means there is no jailbreak available for the um version ranges. And uh uh
some uh version ranges can be jailbroken uh with specific tools and uh when we have a jailbroken device what does it actually give us? Uh first it lets us install unsigned IPA files. Normally every app that runs on iOS must be signed by a trusted developer certificate on a jailbroken device. Um this rule is relaxed and uh so we can install apps from arbitrary sources without fighting the signing system. Uh second we get root level access to the file system. That means we can browse any apps directories, inspect their databases, uh look at their preference files, look at their log files. Uh so because we are simple root. Third, we can uh run dynamic analysis tools uh in
their most powerful forum which we will talk in detail later in the next slides. And finally, we can install all kinds of security testing tools directly on the device. This includes proxies, debuggers, file browsers, uh package uh packet capture tools, etc. All of them become installable through uh package managers. So, jailbreaking gives us enormous power. Okay, a little bit about uh iOS security model. What is iOS security model actually predicting? Uh if you take a look at the diagram on the left side uh at the bottom you see um the hardware level the device key the Apple root certificate the crypto engine and something called the secure enclave. The secure enclave is a separate chip
basically a tiny computer inside your phone that handles sensitive operations uh like fingerprint matching and face recognition. uh the main iOS kernel cannot directly read its data. Uh it can only ask uh to do some operations uh like uh if this uh fingerprint is correct or sign this challenge like this and that operation is a very strong security boundary. Uh above the hardware we have the kernel um the OS partition and the user uh partition which is encrypted and on top of all that each app runs inside its own sandbox as we mentioned and its data and resources are uh isolated. An app uh cannot without permission read files from other apps or access microphone or
other system resources. Uh now a bit uh detailed about um main security features of uh iOS system. App groups are uh a mechanism that lets multiple apps from the same developer share data in a controlled way. For example, a main app and its widget can share a common data container. Uh from a security standpoint, if an app is a member of an app group, sensitive data might live in a shared container. Entitlements uh are fine grained permissions uh enforced by the operating system and embedded into the app at signing time. Uh they define what the app is allowed to do, which hardware it can access, which capabilities it can use, which groups it belongs to. A face ID and
Touch ID uh provide biometric authentication which is powered by the secure enclave. uh our fingerprint and face model never leaves that chip. Uh what iOS uh gives the app is basically a yes or no answer. Did the biometric check uh pass or not? So then we have keychain. Keychain is iOS secure uh storage mechanism uh for small sensitive items like passwords, tokens, um encryption keys uh which we also talk uh later in the uh next slides. Uh as you see all of these together form a layered uh defense. Uh now faced with all that security where do we look for uh problems? Uh fortunately uh we don't need to invent this from scratch. Um the OAS foundation
maintains a guide of uh a guide called the mobile application security testing guide. Uh you can find it um in this link and the MASG um documents around 70 tests uh specifically for iOS and it they fall into these categories. storage, crypto authentication, network platform code resilience and privacy. Uh but main areas of interest during security audits uh iOS security audits are local storage of sensitive data uh local authentication uh including Face ID and Touch ID. uh platform APIs. Uh this includes uh things uh like um interprocess communications uh the way apps uh talk to each other or app uh communicates with its uh components. At network level, this is just back end uh the APIs
the app talks to. Now uh before we get into the tools uh let's review two famous approaches we have uh when auditing static analysis versus dynamic analysis. Static analysis means uh looking at the app without running it. Uh we take the IPA file we unpack it. We look at the binary. We examine the configuration files. We search for hard-coded secrets. And the dynamic analysis means running the app and watching how it behaves. What does what does it write to disk? what network request does it make uh what what's happening in the memory and etc. uh on iOS uh static analysis uh alone gives very limited coverage uh why because swift and objective C binaries after compilation and encryption are not
easy to read. You can sometimes pull out strings some function names some structure but the actual business logic is buried in a machine code. Uh so dynamic analysis is a must and dynamic analysis is where the real insights uh come from. Running the app, watching it, interacting with it and ideally hooking into it uh so you can see uh what it is actually doing or any uh point in time. That's where uh you find the interesting bugs. In a good audit, you do uh both. You start with static analysis to get a map of the app. Then you uh move on to dynamic analysis to actually test its uh behavior, its runtime behavior. Okay, let's continue with uh static
analysis. We'll talk about IPA structure in this slide. Uh an IPA is really a zip archive. Uh you can rename it from zip uh IPA to zip and uh you can unzip it and you will get a folder called payload and inside that you get an app bundle uh which is another folder. The app file itself itself is the main binary. That's the compiled uh signed machine code that actually runs when you launch the app on your iPhone device. Uh info.p list uh is the uh app's main configuration file. It's a structured XML document. Um technically it's in binary format but it can be converted to XML very easily. Uh that tells iOS everything about the app.
bundle identifier, minimum iOS version, supported devices, permissions, it requests, and as a pentester, info.p list is often the first place uh we uh is the first place uh we read uh because it gives us a map of uh what the app is designed to do. And then uh we have embedded mobile provision. It's a provisioning profile. Uh it's basically the contract between uh Apple the developer uh and the device saying this app signed with this certificate is allowed to run. It also contains the entitlement and the list of capabilities the app is allowed to use. U code signature directory is a folder that contains hash of all the files in the bundle along with the cryptographic
signature. That's what iOS uses to verify that the app hasn't been tampered with. Then we have frameworks folder and plugins. Frameworks is where any third party uh libraries the app depends on are stored. And plugins uh are app extensions. Uh things like widgets inside the app, share extensions, notification extensions. They are basically little sub apps uh that run inside their own processes and they have their own binaries. uh their own info.p list files and signatures. Okay. Uh now I mentioned earlier that the IPA you get from the Apple store has an encrypted binary. Uh if you want to do any serious static analysis, we need a decrypted copy. So how do we get one? The easiest path is to ask the
developers. Uh if you are doing an authorized audit, the development team can give you a debug build or an archive that's not encrypted. Uh if that's not possible and you have a jailbroken device by any chance, there is a tool called Fred the iOS dump. Uh it does exactly what the name says. It uses Freda to attach to a running app, grab the decrypted binary from memory after iOS has decrypted it for execution and dump it to disk. This is the classic technique to a to getting a decrypted IPA. And uh uh if these options don't work for you, uh there are online services sites like armconverter.com, decrypt. Um these maintain libraries of already decrypted IPA files for popular app
store apps. Okay, let's say you manage to get a decrypted IPA file. The next step is to run it through a cool a tool called uh mobilef um mobile application sec mobile security framework. Uh it it is free open source uh and gives you a lot of information about the uh IPA file you're uploading. You have two options to use this. Either self-hosted, you can uh clone the repository and uh install it and run it um on your computer and second option is to use the online version uh which may be convenient for uh quick tests but you uh at the end of the day upload the IPA to a third party. Uh so consider
that. Uh so what does Mobisf do? uh it analyzes the IPA and gives you a report with several things. It inspects the info.p list and flags suspicious configurations. It analyzes the binary and looks for weaknesses uh in how the code was compiled. Basically, binary protections. It extracts URLs and end points from the binary. Uh it scans for potential sensitive strings, uh private keys, API keys, tokens, etc. uh which may accidentally left in the binary. So we are moving on to the dynamic analysis. Um it's the other half. For this the app obviously has to be installed on your iOS device. We need to be able to observe how the app interacts with the system and with external
services. We want to see its data storage options operations when it writes to disk. What does it write? Uh we want to see its network communication. what requests uh does it send? What response what responses does it receive? Uh we want to see its interprocess communication. Does it talk to other apps or system services? And we want to see how it handles user input. Uh if we have a jail working device, dynamic analysis becomes straightforward. We can SSH into the device as a root. We can browse any apps data directory. We can install custom tweaks and scripts that instrument the system or specific apps. But even without a jailbreak, dynamic analysis is still feasible. Uh we can install uh we
can still analyze the app's sandbox. We can still trace uh file network operations and function calls within the app. So we came to the heart of the presentation uh dynamic instrumentation. This is the core technique that makes uh non jailbroken iOS pen testing possible. It's called dynamic instrumentation and the tool we use for it uh called Freda. What do we want from dynamic instrumentation? Uh two things basically. First we want to capture and uh log application behavior in real time. Uh when the app calls a function, say a function that reads a keychain item, we want to see that call happen, see the arguments and see the return value. We want visibility into the black
box. Second, we want to modify application logic during um execution. This lets us bypass client side security checks and test the apps uh as if those checks didn't exist. Freda is a very powerful tool for that. Uh the way it works is that Freda injects a JavaScript uh engine into the target applications process. Once that engine is uh running inside the app, we can send it uh JavaScript code that intercepts function calls, reads memory and modifies behavior. Now uh there are two ways to use Freda on iOS. Uh the first way is to uh run a Freda server uh on the device and from your laptop you connect to that server and tell it which app to attach to. um
that's beautiful and clean but it requires a jailbroken device and we have uh another option uh which is one we care most about uh today uh is injecting a free the gadget into the app. Frea gadget is a shared library um that we embed inside the IPA. Uh when the app launches the gadget loads along with it and it exposes an interface that we can connect it from outside because the gadget lives inside the app's own process and is signed together with the app. No jailbreak is used and this is the uh key trick we have. Okay, continuing. So how do we actually put free the gadget into an IPA? Let's walk through it. Uh first we need to
download free the gadget itself. You can find it in the free projects GitHub releases page. Uh the file you want is called something like Fred the gadget version iOS universal. Next we need to patch the IPA. Uh we unzip the IPA uh which gives us a payload folder and inside that the app bundle for example payload app.app directory uh and we copy Freda gadget.dial uh into that folder. Now uh just putting uh the dial in that folder is not enough. The app's main binary doesn't know about it. It will load and ignore it. We need to modify the main binary to actually load our dial at startup. And that is what the tool op tool does. The
command uh looks like this. Um what this command does is add a load command to the apps binary. Specifically, it adds an entry that tells the dynamic linker when you load this app. Uh also load fa gadget.dial from the same directory. The executable path uh part is a special variable. That means the directory of the main executable and that's exactly where we copied our dial. Once optool has done its work, the IPA is patched but it's not yet signed. So it cannot be installed on a non-Jailbroken device. So that's the next step. So sideloading is a term for installing an app uh on iOS device from a source other than the app store. On a
uh jailbroken device uh you do not need to sign the app at all. As we said, you just install the raw IPA. But on a non- jailbrokable device um every app has to be signed. And that's where things get interested. Uh to sign an IP iOS app yourself, you need a few things. uh you need an Apple developer certificate. There are two ways to get that certificate. The first way is to enroll in the Apple developer uh program which costs $99 a year and uh the second one uh is free alternative. Uh it gives you a proper uh developer certificate. Uh also any uh Apple ID you can use for that. Uh so with your Apple
ID you generate what's called a free provisioning profile which lets you sign apps for free. Uh but those apps are only valid for 7 days. After 7 days the certificate expires uh the app refuses to launch and you have to resign and reinstall. Uh for testing uh 7 days is often enough. Uh so we can get away with that. uh to actually do the signing uh you also need a provisioning profile which is a file with the extension mobile provision. The easiest way to get one is to open Xcode, create a new empty project with any um bundle identifier you want. Let Xcode generate and download the provisioning profile automatically and then grab uh that
profile for our purposes. Uh you may also need to modify uh info.p list inside the IPA. the bundle identifier might need to match your Apple developer certificate and if the app uses app groups you might need to update those as well. So fortunately there are tools that can automate all this stuff for us. One of them is called Sideloadly. Uh it's an all-in-one desktop application that runs on Mac OS and Windows and it does almost everything uh we just described in a single interface. What sideloaded does for you, it takes your uh IPA file, let you inject custom dials like our free gadget dial into it, takes your IO uh Apple ID, uh signs the modified IPA and
pushes it to your device over USB. Uh one thing Sideloadly does automatically is to change uh the bundle identifier. When you sign with a personal or team certificate, the bundle ID has to match your team prefix which is tied to your uh developer account. Uh as you see here, it will be something like this where the last part here um is your team identifier. This is done to make sure that apps you sign uh do not collide with legitimately signed apps on your uh iOS device. So sometimes sideloading apps um sideloadaded apps uh can crash on launch. Uh sometimes it crashes partway through and you have to debug why. The most common issues I see are the
following. Uh entitlements not defined properly. The app was originally signed with certain entitlements that your free Apple ID cannot grant. Uh the fix is often to strip those entitlements from the entitlements P list before signing and uh plug-in and framework files may not be signed properly. Uh an IPA can contain multiple binaries. The main app plus frameworks plus plugins like widgets and extensions. Every single one of those has to be signed with a valid signatures uh not just the main binary. If side load or uh any signing script miss one of them the whole app refuses to launch it may crash. The solution is to make sure all binaries inside this bundle um get resigned.
And also uh finally pist files may require manual updates. Um, and if you want to go deeper with this one, there's a great article uh by with secure labs. Um, and uh you may also uh finally um try try consider consider uh using alternative tools like alt store um and you may uh find out uh which one works for you and your application. So running repacked iOS app. Uh okay. Uh let's say you manage to sideloadad your free patched IPA successfully. Uh first you need to u enable developer mode on the device to run the app. And this is a setting under privacy and security and it requires a reboot before running the application. And you also need to go into settings um
general VPN and device management and trust your developer uh certificate. Um obviously the first time you install a sideloaded app it will not be launched um because iOS system doesn't um trust your developer certificate yet. So you have to uh trust it manually. Uh after that uh you need to launch the app in debug mode from the command line. You see the uh exact command here. Um we specify our device ID uh and bundle ID of the sideload app. Uh then we uh use lldb debugger. Uh we use um it to attach to the process by its uh p. Um then uh at this point the app is running under the uh debugger but execution is paused. Uh you give it the
continue command and the app starts running normally including uh loading your Freda gadget and that's the moment when you can finally connect Freda to the gadget and start doing dynamic analysis. Uh so if you want to get the detailed step-by-step guide you can check the link from um wasp mastg at the bottom. So attaching to freed gadget how to connect to the uh patched app. First command uh we use it to list available applications on the USB uh connected device uh free psua. uh in that list one of the entries will be our target app and Fredo will tell us that a gadget is active inside it or not. Uh when we see that gadget is
activated uh we type the second command uh fida un gadget. Um so this attached freed to uh the gadget and the U again means uh USB and N gadget uh says attached to the process name gadget which uh what our embedded gadget is called. Now we have a JavaScript ripple running inside the target app. We can write scripts that intercept function calls dump memory uh modify return values and so on. Uh for people who do uh not want to write Freda scripts from scratch, there is a tool called objection. It's built on top of Freda and provides a nice interactive shell with a lot of pre-built commands. You can run it like this. Objective objection g the name of
the um app and explorer and you get a prompt where you can type things like iOS keychain dump uh or SLP bypass etc. Finally, there's a tool called uh grapefruit which was previously known as passion fruit. This is a comprehensive web- based um analysis tool for iOS and Android apps. It gives you a graphical interface into the app. Uh a browser for the sandbox, a class dumper, runtime inspection, and more. It's built on Freda. So, it works the same way as Objection, but with a much prettier interface, and here is the GitLab link for this. So, here we go. Moving to the demo part where we will see this um uh main three attack vectors uh in action. Uh the
first one uh we will look at is data storage. Um on iOS apps there are um multiple uh data storage options. User defaults is the most basic one. Developers love it because it's very easy. It's just a keep value pairs uh and it's stored in library preferences uh bundle ID.p list file. it's um stored unencrypted so it's not protected. If we will find any sensitive items stored in user defaults that's um uh that's certainly a finding. Then P list file files uh apps can generate their own P list files other than info.p list. So they may consider uh they they may uh store um sensitive files there again and that's not recommended uh at all because
that's not encrypted. uh SQL databases the same way uh applications sometimes store structured um data inside it uh which is not recommended because they are not encrypted as well and keychain uh which is the uh storage mechanism u recommended for secrets um and uh this is also a SQL light database stored uh in the application sandbox in this path and uh uh but it's protected uh it's encrypted the database managed by iOS and recommended for uh storing small pieces of sensitive data. Uh so uh let's see the demo of um data storage. I will use grapefruit for that. Let's start the video. Uh as you see we are starting the grapefruit um tool. It's UI. Uh and we
are um starting the our target application which is DVIA which is a uh intentionally vulnerable application. Uh we start it in the debug mode and then um we wait for the grapefruit to connect to the uh application. Um we select our device in LLDB debugger. We list the processes. We find the uh uh we find our application. We attach to it with its P and continuing. Then we will see the our app listed here. Uh we also have gadget but we choose our main app which is the via as you see we see the uh connected at the bottom and the application also continues uh its um execution. As you see we can browse the application sandbox freely. This is
done in a non jailbroken device. Um
the first one is uh storing some data in P list. Um we consider this is some sensitive information username and password. And as you see um we can read this file from the sandbox.
The second one is user defaults. Uh now the application will store the value we typed in the user defaults secret 1 2 3 and we can access it in in the path we we talked about just a moment ago. Libraries preferences and pist file. As you see we found the value the application stored. So we can also analyze uh keychain um keychain storage of the application um with grapefruit. Uh then the second attack vector is uh authentication. Um with authentication uh on iOS uh we have um um LA context API mainly used for um biometric authentication and the common method is evaluate policy localized reason reply and this only returns true or false value. Uh and most
applications rely on the boolean uh success call back to allow access. Uh so it's possible to bypass authentication by hooking evaluate policy and force the call back to return true. And it's recommended to uh but it this is certainly not the um secure way and uh the recommended way is to protect sensitive data let's say authentication token on your mobile application in keychain uh with a specific access control biometric bound key access control biometric current set. So the OS itself enforces authentication via secure enclave not just uh app logic. So let's see this in action here. Authentication we can easily hook into uh the API and we can return true and the app will allow us.
It's done here in the hooks. We activate biometric bypass and on the vulnerable app we tap on the face ID button. As you see uh here I click cancel and you see it says authentication successful. Why? Because we hooked the u API and returned true.
That's it about um authentication and uh network. This is fairly simple because this is all about requests being made to the back end. Um it's common with uh a lot of applications. Uh so we can proxy this uh traffic. We can um analyze it uh requests and responses. Um so um some apps uh however implement something called certificate pinning. This make uh MITM attacks harder. Um but uh most of the time it can also be bypassed by hooking the pinning functions because we have uh standard functions uh to implement this and there are a lot of free scripts for this uh we can use um to hook into those functions and always return uh like this certificate is fine.
So uh the application will continue sending its request to the uh backend server. it. We can see it in action here if time allows. The first one uh will be um on grapefruit. Grapefruit uh grapefruit is great uh when it comes to analyzing network requests. We choose an S URL. Uh I'm clearing the old requests and I start the logger. It will log all the requests I sent from the application like HTTP and HTTPS all of them. uh grapefruit doesn't have um SSL pinning bypass internally but uh uh for this one we I use um free free the script I mentioned so I connected to the gadget and uh uh I run the script and I'm using uh burp suite as a proxy
Okay. Um, I switched the interception on.
Uh, we also need to configure the proxy configuration on our iOS device.
We do this here. We enter the uh IP address and the port of our proxy.
Okay. Okay. So, um we intercepted uh the request with SS opening here. That was all. Uh thank you for your attention. Yes, it was all for today. Thank you for your attention.