Author: Min(Spark) Zheng (SparkZheng@twitter)-Alibaba Mobile Security Group
Ian Beer@google released an exploit of CVE-2017-7047 Triple_Fetch  in the last week. Then, chenliang@keenlab wrote a Chinese article to analyze it . However, there are lots of highlights we could learn in the vulnerability and exp. Therefore, we plan to write this article to analyze Triple_Fetch and the sandbox escape technique on iOS 10.3.2.
0x01 CVE-2017-7047 Triple_Fetch Vulnerability
Chenliang and beer has a very detailed write up, so I only briefly summarize the vulnerability here.Because of the efficiency issue, for OS_xpc_data which is larger than 0x4000 in XPC translation, iOS system will use mach_vm_map to map the memory using physical pages. This means the sender and receiver shared same physical pages of memory. If the sender changes the shared memory, the receiver’s memory will be changed as well.
Therefore, using race condition, we could make the receiver get different data and the receiver may treat them as the same one. It’s will cause some serious problems. For example, the sender first sends @”ABCD” (includes @ and “) to the receiver, the receiver will allocate 7 bytes buffer for this string. However, the receiver will copy the string to the buffer until it meets ‘“’. If we change the string to @"ABCDOVERFLOW_OVERFLOW_OVERFLOW" after the allocation, it will cause a heap overflow in the process of the receiver.
The function Triple_Fetch chooses to attack is ___NSMS1() in the CoreFoundation frameowork.This function reads the shared string multi-time. If the sender changed the shared string during the process, it may cause a logic error of the function and then trigger the heap overflow. By using three groups of strings, it’s possible for the attacker to control the pc register of the receiver. That’s why this exploit is called Triple_Fetch. The picture shows three groups of strings which are used for the exploit:
The exploit chooses to attack the “com.apple.CoreAuthentication.daemon” service (/System/Library/Frameworks/LocalAuthentication.framework/Support/coreauthd), because this process has root privilege and can get other processes’ send right by using processor_set_tasks(). The picture shows the crash report of coreauthd:
0x02 Triple_Fetch JOP &ROP&Arbitrary Code Execution
Although you can control the pc register through Triple_Fetch vulnerability, you cannot control the stack. Therefore, we need to do stack pivot first.A good news is the X0 register which points to the xpc_uuid object is controlled by us:
Therefore, we can use the _longjmp function to do the stack pivot using JOP. Then we can control the stack:
The layout of xpc_uuid object and the JOP we used to do stack pivot are shown below:
It’s easier for us to write ROP when we control the stack.But the goal of beer is not only ROP, but arbitrary code execution as well. Therefore, beer’s exp used an exploit technique to get the task port of the receiver. Besides the fake xpc_uuid object, the exploit also send 0x1000 mach msgs with send right port to the target process:.
The content and location of these mach msgs (with 0x12344321 msgh_id) are shown below:
After that, the exp used ROP to traverse the Mach msgs and send them back to the attacker:
Then, the attacker will receive the Mach msg. If it receives the Mach msg with0x12344321 msgh_id, it means the attacker get the task port of the target process successfully:
After getting the task_port (in sploit()), the exploit moves to the next step - do_post_exploit(). do_post_exploit() also did a lot of things.Firstly, it uses the task port of coreauthd and processor_set_tasks() to get the task port list of all processes.
So how does it work? Because we have the task port of coreauthd, we could use mach_vm_* APIto modify the memory and register values of coreauthd.So, we can allocate a block of memory for the stack of function and then set the pc register to the function pointer we want to invoke. Therefore, we can let the target process to execute any function we wish to. The implementation can be found in call_remote() function:
Then, the exploit lets coreauthd executea serial of functions (e.g., task_get_special_port(), processor_set_default(), host_processor_set_priv() and processor_set_tasks()) to get the task port list of all processes and send it back to the attacker. Then, the exploit will search for the task ports of amfid,launchd,installd and springboard in the task port list. After that, it will patch amfid using the same trick in mach_portial. Last but not least, it starts debugserver.
In fact, the exploit not only can execute debugserver, but other binaries outside the sandbox as well. The only thing you should do is to swap the bin file in the pocs folder, recompile the app and then click exec bundle binary:
The magic is in the spawn_bundle_binary(). The function first executes “chmod 0777” for the third party bin and then invokes a serial of posix_spawn(like fork()) APIs to execute the third party bin.
Code execution outside the sandbox opens more interfaces to attack the kernel. In addition, we could read and modify lots of files on the iOS system through the SBE vulnerability. For example, the attacker can read personal files (e.g., SMS, chat logs and photos) and then send them to the hacker’s server:
In this article, we describe the Triple_Fetch NSXPC vulnerability found by Beer. Then we introduce a method to do stack pivot through JOP and gain arbitrary code execution through ROP.However, if we want to control the kernel, we still need one or two vulnerabilities in the XNU or IOKit. In addition, Apple fixed the kpp bypass technique which are used in the yalu 102. Therefore, even we have Triple_Fetch exploit, there is still a long way for jailbreakers to finish the jailbreak on iOS 10.3.2.