Inside iOS: Security, Vulnerabilities, and Jailbreaking

This is a guest post by iFans forum member tw23, as part of the Inside iOS series on iFans.

iOS is one of the most secure mobile operating systems. You could even argue that it is more secure than Mac OS X itself, because of code signing.

This article will provide you with the basics of iOS security, some places you can find vulnerabilities in the kernel — thanks to the iOS Hackers Handbook — and some minor disadvantages of jailbreaking that you probably didn’t know about.

The Bootchain

When an iOS device boots up, this is the process:

BootROM -> security check -> LLB (NOR) -> security check -> iBoot (NOR) -> security check -> Kernel (NAND) -> security check -> iOS Software (NAND)

When an iOS device is in DFU mode, this is the process:

BootROM -> security check -> iBSS (NOR) -> security check -> iBEC (NOR) -> Kernel (or Ramdisk)

When an iOS device is in Recovery Mode, this is the process:

BootROM -> security check -> LLB (NOR) -> security check -> iBoot (NOR) -> Kernel (or Ramdisk)

As you can see, there are a lot of security checks to make sure that the file being loaded is not corrupted. Each file being loaded — iBSS or LLB, for example — is signed with Apple’s secret key, and the security checks make sure that it is Apple’s files that are being loaded.

Vulnerabilities

There are some places you can attack the Bootchain: the BootROM (cannot be fixed), iBoot (can be fixed) and Kernel (can be fixed). Assuming you found a vulernability in one of these, and exploited it. What is next? Well, there are two things you can do, with one being mandatory and the other optional. The mandatory step is patching the security checks and userland checks, such as sandbox and code signing. The optional thing you can do is install Cydia and other applications.

iOS Security Features

iOS is probably the most secure mobile software out on the market right now, and here are the reasons why.

Memory Protections

  • W^X/DEP/NX

Apple implants W^X on the iOS similar to Data Execution Prevention (DEP) that says a page can only be writable or executable. This brings up difficulties for security researchers and hackers. If a hacker, let’s say, exploits a WebKit vulnerability to gain control of your device, he can’t do much because of W^X, sandboxing — more on that later — and code signing.

On a number of operating systems which implant DEP or W^X, a hacker that gains control of your system can use Return Oriented Programming (ROP) to make a page executable; this is not the case on iOS thanks to code signing. Thus, exploit payloads have to be implanted in 100-percent ROP.

The only other way around W^X is a new thing Apple introduced in 4.3.3 — as far I know — which is “Just in Time” (JIT). This allows a Java page to be executable, but I really don’t know much about this. Instead, I recommend searching for and reading some of iOS hacker Charlie Miller’s content. Miller exploited a vulnerability in JIT which allowed a page to be both writable and executable. Apple patched this in iOS 4.3.5.

  • ROP

This is a very brief covering of ROP, which stands for Returned-Oriented Programming. I won’t go into any of the history — you can search for this at your avail — because it’s not important for this article, but I will tell you how it works. Basically how ROP works is you use the instructions from the libraries in which your application you are trying to exploit has loaded. For more information, just Google it, since we’re not really looking at how to exploit an app, just the security and vulnerability.

  • ASLR (Address Space Library Randomization)

This could be its own topic by itself, but it goes hand-in-hand with W^X. So let’s say you find a vulnerability and exploit it in 100% ROP, there is still ASLR to get by. ASLR stands for Address Space Layout Randomization. Basically what it does is when the libraries are loaded — in this case the dyld for iOS — it is always mapped at a different address. So sometimes it is mapped at 0×4000, for example, or sometimes at 0×4200. The good thing about iOS is that only the dyld is randomized and not any of the libraries.

What this means is that if you can read a pointer, you can basically find out where the base address is of the dyld, and map your stuff from there. But, say we can’t read a function pointer, what do we do? Well, we could get the base address, but the success of that could be as low as 1 in 1000. That’s not good. We can’t really do anything if we do not know the address of a pointer, which leads to the base address, because ROP depends on the address of instructions in the library.

  • Sandboxing

I am not too familiar with sandboxing, but I’ll try to explain it as best as I can. User applications are sandboxed to a certain directory. For example, a game you downloaded from the App Store cannot access anything else in iOS — neither read nor write — because it is sandboxed. Well, this arises a problem for jailbreak developers. They need to be able to write to files when they get code execution, which is what a jailbreak does. So they need to find a vulnerability in the way an app gets sandboxed, which I don’t really know about, and haven’t learned about it.

Also, one of the things a jailbreak does is patch out the security features of the kernel. So of course, jailbreak developers need to patch out sandboxing. Well, when a sandbox profile is ignored it says, “Sandbox: ignoring builtin profile for platform app.” We want that to happen, so we find the string and patch out the check for it. So we patch out that compare so it will always branch to what we want. That’s all I can really explain about sandboxing, since I don’t know much about it.

Encryption

I really hate encryption, so beg my pardon if this makes completely no sense to you. I will try to make this as short and sweet as possible, and if you want more information, you can Google it.

  • What is a UID?

A UID is a 16 digit key that is unique to that device and is embedded into the onboard cryptographic accelerator. The key itself is not accessible through software, but the accelerator can use this key to encrypt or decrypt specified data.

  • Passcode

When you lock your device with a passcode, your device encrypts it with a certain method. iOS encrypts your passcode with your UID with a special modified PBKDF2 algorithm to generate your passcode key. This key is preserved in memory until your device is locked. So when you try to unlock it, iOS tries to decrypt your passcode key with the same modified PBKDF2, which was used to encrypt your key, with the inputted key. If it matches, it will open up.

  • Device Key

The device key is used to encrypt all of the file protection class keys. To generate the device key, iOS uses the UID key to encrypt a static byte string.

  • Developers

Apple introduced the Data Protection API in iOS 4, and it is still is used in iOS 5. Basically, what it does is lets developers encrypt sensitive data into a keychain file, which is encrypted using one of these classes:

  1. NSFileProtectionComplete – protected and can be accessed only when the device is unlocked
  2. NSFileProtectionCompleteUnlessOpen – protected; must be open when the device is unlocked; can be written to after opened, even when locked
  3. NSFileProtectionCompleteUntilFirstUserAuthentication – protected until device is booted and the user enters a passcode for the first time
  4. NSFileProtectionNone – not protected, and can be accessed at any time

Each of these classes uses your device key to make another key — the file key — of that file that the developer wants to encrypt, and it gets encrypted.

Finding Vulnerabilities in the Kernel

Thanks to the iOS Hackers Handbook as a reference for this information. This will only cover kernel extensions, not the IOKit. There are only 4 places where userland can interact with the kernel:

  1. Userspace Code
  2. Network
  3. Hardware
  4. Filesystem

We will cover the IOCTL’s (input output controls) of the network, hardware, and filesystem. Note: there are many more IOCTL’s than the ones I list here and show you.

  • Userspace Code

When you attack through userspace code, you attack through the system calls. To list them, you can do it manually — not going to say it here since it’s not necessary — or using the iOSToolKit by iOS hacker Stefan Esser (i0n1c). Just run it, and you will see the system calls like this:

If you want to find a vulnerability in a syscall just audit every single syscall. Finding a vulnerability will lead to direct kernel code execution.

  • Network

The function “net_add_proto()” adds a network protocol taking a structure of “protosw” or “domain” as a parameter. The protosw structure looks like this (taken from the XNU source code in protosw.h):

struct protosw {
    short    pr_type;        /* socket type used for */
    struct    domain *pr_domain;    /* domain protocol a member of */
    short    pr_protocol;        /* protocol number */
    unsigned int pr_flags;        /* see below */
/* protocol-protocol hooks */
    void    (*pr_input)(struct mbuf *, int len);
                    /* input to protocol (from below) */
    int    (*pr_output)(struct mbuf *m, struct socket *so);
                    /* output to protocol (from above) */
    void    (*pr_ctlinput)(int, struct sockaddr *, void *);
                    /* control input (from below) */
    int    (*pr_ctloutput)(struct socket *, struct sockopt *);
                    /* control output (from above) */
/* user-protocol hook */
    void    *pr_ousrreq;
/* utility hooks */
    void    (*pr_init)(void);    /* initialization hook */
    void    (*pr_fasttimo)(void);
                    /* fast timeout (200ms) */
    void    (*pr_slowtimo)(void);
                    /* slow timeout (500ms) */
    void    (*pr_drain)(void);
                    /* flush any excess space possible */
#if __APPLE__
    int    (*pr_sysctl)(int *, u_int, void *, size_t *, void *, size_t);
                    /* sysctl for protocol */
#endif
    struct    pr_usrreqs *pr_usrreqs;    /* supersedes pr_usrreq() */
#if __APPLE__
    int    (*pr_lock)    (struct socket *so, int locktype, void *debug);
    int    (*pr_unlock)    (struct socket *so, int locktype, void *debug);
#ifdef _KERN_LOCKS_H_
    lck_mtx_t *    (*pr_getlock)    (struct socket *so, int locktype);
#else
    void *    (*pr_getlock)    (struct socket *so, int locktype);
#endif
#endif
#if __APPLE__
/* Implant hooks */
    TAILQ_HEAD(, socket_filter) pr_filter_head;
    struct protosw *pr_next;    /* Chain for domain */
    u_int32_t    reserved[1];        /* Padding for future use */
#endif
};

The stuff interesting for security researchers and hackers is the pointer to function called “pr_input” and “pr_cloutput”. The pr_input function is when you input data into the network protocl, and pr_cloutput is the setsockopt function. A vulnerability was found in iOS 4.3.1 – 4.3.2 by Stefan Esser (i0n1c) which let him get untethered.

  • Hardware/Devices

The functions “bdevsw_add”, “cdevsw_add”, “cdevsw_add_with_bdev” all adds devices with either a structure of type bdevsw or cdevsw which is defined in the XNU source code in conf.h.

cdevsw:

struct cdevsw {
open_close_fcn_t *d_open;
open_close_fcn_t *d_close;
read_write_fcn_t *d_read;
read_write_fcn_t *d_write;
ioctl_fcn_t *d_ioctl;
stop_fcn_t *d_stop;
reset_fcn_t *d_reset;
struct tty **d_ttys;
select_fcn_t *d_select;
mmap_fcn_t *d_mmap;
strategy_fcn_t *d_strategy;
void *d_reserved_1;
void *d_reserved_2;
int d_type;
};

bdevsw:

struct bdevsw {
open_close_fcn_t *d_open;
open_close_fcn_t *d_close;
strategy_fcn_t *d_strategy;
ioctl_fcn_t *d_ioctl;
dump_fcn_t *d_dump;
psize_fcn_t *d_psize;
int d_type;
};

The interesting things for us is the pointer to a function called “d_ioctl” which is the IOCTL handler for these structures. One of the parameters of the functions (eg. cdevsw_add) will add one of those structures (eg. cdevsw). Just use IDA to find the structure and then the ioctl — fifth one down from the top for cdevsw, and fourth one down for bdevsw. Here is an example:

Click on that, and it will bring you to the cdevsw structure

Click on it, and that will bring you to the ioctl handler for the particular structure of cdevsw. There are many others. You can audit manually or with an IOCTL fuzzer. I recommend you do both.

  • Filesystem

Auditing the filesystem would be like fuzzing the HFS parser stuff and looking at how it reads HFS/HFS+ files. Then look at the IOCTLs for it also. That’s really much all. Not that complex.

  • Last Thoughts

There are way more IOCTLs then the ones I have already mentioned. Just look for them in the source code and the kernelcache binary. Good luck.

Disadvantage of Jailbreaking

There is one major reason why you shouldn’t jailbreak, and that is the lack of security. Since jailbreaking disables a lot of security features, it will turn your device into an Android-based smartphone. And in my opinion, Android has basically no security. Jailbreaking will disable sandbox and a whole bunch of other security features and add more ways in which hackers can steal your data and do other malicious stuff with your device. Anyone remember the Ikee worm for iPhone? So just a caution for those of you who are paranoid about the security of your data.

Conclusion

I really hope you guys liked this article, and I hope it gave you some insight on how secure iOS is, some ways to find vulnerabilities in the kernel, and a disadvantage of jailbreaking. You do need to know a little programming, especially C and ARM, for finding vulnerabilities in the kernel and userland. Thank you for reading this long article, if you survived this long.

This is a guest post by iFans forum member tw23, as part of the Inside iOS series on iFans.

Post a response / What do you think?