 Okay, here we go. Hello, everyone. I'm happy to be with you today. My name is Yueqicheng, a PhD student from Pennsylvania State University. In this talk, I'd like to share with you some outcomes of my recent research work with my lab mate, Zheng Ponglin. This talk is about an exploitation approach which can bypass many medications in Nina's kernel. This approach uses magic objects, which we name as elastic objects. At the beginning of the talk, I will introduce several kernel protections that we are going to bypass, as well as some kernel substantive data we want to leak. Then I will introduce the exploitation approach using an example. Followed by this, I will show how we track down elastic objects by extending flexible objects in the kernel code base. I will display the severity of this exploitation approach at a reading about why we needed to study the generality of this attack. After this, I will describe the way we use to study the generality and the outcome of the study. Finally, I will go through several kernel mitigations that seem to be able to circumvent the attack, but I don't think so. That's why I propose a mitigation, which is a follow way from being perfect and use some comments from you. This talk takes about 40 minutes for 28 pages. If you have any questions, feel free to ask via text chat. And also I paste my contract at the last page of the slide, in case you don't have chance to ask questions. I hope you can enjoy the talk and send me your comments so that we can further advance our research. As I mentioned, I will describe several kernel protections that we plan to bypass. The first protection is stack-nary, which has already been deployed in both kernel and user space program for decades. I'm pretty sure that you are familiar with this protection on stack, just in case I will brief this mitigation. The idea is quite simple. When having a stack buffer overflow, the adversary can override the return address in current stack frame. Later, when the function returns, the current execution is directed to the malicious address. To detect this override during the prologue, the kernel places the stack-nary, which is several bytes of random value right below the return address and old EPP. During the epilogue, the kernel tests the canary on stack against the one start to see if any corruptions happened. If stack buffer overflow is triggered, the stack-nary is tampered before the return address. Thus, when the kernel finds a mismatch between the canary on stack and the one start, this means stack corruption has happened and the return address is no longer trustworthy. The stack-nary is now by default a mitigation in almost all Linux distros, including Ubuntu and Dabian. It is also used in other operating system kernel like FreeBSD and XMU. To bypass this mitigation, the adversary either uses brute-force method or relies on information leaking. The brute-force method is to guess the canary byte by byte, which reduces the complexity from 64 over two to eight over two on the big O. Information leaking is another approach in which the adversary can leak the canary to user space. One of my previous works is to use IP control to perform stack leaking. In this talk, I will show how I use write primitive to obtain a leak primitive for exposing the stack-nary. The second mitigation on stack I want to introduce is config initial stack all and the config GCC plug-in stack leak. Both mitigations are responsible for poisoning the kernel stack at the end of system call. The kernel is buggy, as we all know. One type of the bug is uninitialized stack. The adversary can exploit this type of bug using stack spray. When the machine enters a kernel mode, the kernel stack is used to store local variables. Some of the local variables can be synodied, for example, keys for encryption. The adversary can use a system call to store these synodative data on kernel stack. And then he or she can use another system call to trigger the uninitialized stack bug. As part of the stack is uninitialized, the synodative data is not erased from the stack. Later on, when part of the stack is copied to user space, the synodative data is leaked. Several weeks ago, a stack-based information leak in A2MP of Bluetooth is discovered, basically practicing this idea. To circumvent the leaking, there has been proposed many mitigations. For example, randomized the base address of kernel stack so that the two system calls are not using the same memory region. The two mitigations I mentioned here follow another approach which is to poison the kernel stack at the end of system call. Since the synodative data is erased, the adversary cannot use the uninitialized stack bug in the second system call to leak data. The difference between the two mitigations are that the formal is implemented in GCC plugin and the latter is in kernel codebase. And also the formal poisons the whole stack and the latter only erases the stack region that has been used in this system call. No matter which mitigation is used, both have the limitation that it only works for multi-system call attack. Because poisoning happens at the end of a system call, if the adversary can read the data before returning back to user space, information leaking is still doable. In the exploitation approach I will describe in this talk, the limited write primitive on kernel heap can be used to leak the data on stack in one system call, not using uninitialized stack bug. On slab and slab, one of the mitigations are config slab free list hardened. This mitigation includes three patches and I show the diagram of one patch on the slide. The free slots in slab allocator are chained using a singly linked list. The head of the list is named the free list. When a slot is in free status, the free, the first eight bytes are used to start the address of the next slot in list. This is a situation before the patch is applied. After the patch is applied, the first eight bytes of the free slot starts the XOR result of, first, the address of the next slot which is the free slot three in the diagram. Second, address of the free list ahead and the third, a random number. Without the patch, the adversary can forge a fake address using the heap buffer overflow and mislead the kernel to return the memory region indicated by the fake address in the next allocation. This allows the adversary to be able to tempo the data stored in the fake address. However, with this patch, the kernel will calculate the address of the next free slot by reversing XORs data in the first eight bytes. Even if the adversary can forge the data using the heap buffer overflow, the calculated address is not or to the adversary once. This is because the random number is involved in the calculation. According to one study early this year, the entropy of the hardening is very low and thus forging the address is possible. As a compliment in the exploitation approach I will describe in this talk, the first eight bytes after XOR can be leaked with a limited write primitive on kernel heap. The leaked eight bytes can then be used for forging. I will call the eight bytes as a heap cookie in the following slides. Another mitigation on slab slab is a pair of config initial on alloc default on which is known as initial on alloc and config initial on free default on which is known as initial on free. These two mitigations show some similarities with the stack poisoning we've discussed in the previous slides. Like a kernel stack, the heap object encloses sensitive data like function pointer and keys for encryption. Without the mitigation, the content in the heap object is left unchanged after the object is freed. Later, when the slot holding the object is recycled for the following allocations, the adversary can use an uninitialized heap bug to leak the data. To this end, the two mitigations are responsible for zeroing out the heap object after a time of freeing and reallocation respectively. As such, the sensitive data is removed and leaked data is all zero. The two mitigations work for used after free exploitation and a double free exploitation because the two types of vulnerability need to reason about freeing and reallocation. However, when the heap object is in use, the sensitive data is stored on the heap, on the current heap. This gives us the chance to leak the sensitive data in the heap object using the leak primitive obtained from limited write primitive. I will elaborate on this later. The next generation I want to describe is KASLR, corner address space layout randomization. On the slide, I show part of the corner memory layout. With this mitigation, the loaded corner text image could be anywhere from 80 to say zero as long as it complies with alignment policy. The loaded corner modules could be anywhere from say zero to say zero for zero as long as it complies with alignment policy. This is a situation of X64 and other architectures are similar. This mitigation works because it's very hard for those exploitation approaches to reliably jump to the target code if they want to execute corner instructions for malicious goal. To defeat this mitigation, the commonly used approach is to leak address of a global variable or function. Then the adversary can calculate the base address of loaded corner image through offset. That's why I say in the previous slides, the return address and the function pointer is sensitive data because this starts the address or functions. Once they are well-usely kit, KASLR can be bypassed. This is the first shortcoming of KASLR. Another shortcoming is a low entropy because there are only so many allocations the corner can fit in. Someone thinks the tackle can get the base address without too much trouble. As such, FG KASLR was proposed which implements functional granularity KASLR. I cannot go into details of this mitigation today because it is still in development. The main idea is to randomize the address or functions when loading the corner image. The entropy is much higher in this granularity and one leaking is far away from being enough to defeat this fine granularity mitigation. Similar idea has already been used in OpenBSD and I'm very willing to see it to be merged in Linux because I believe it's very powerful. On this page, I list the two types of sensitive data that can be leaked from Kono according to Andrew Konovalov's exploit. The first is the content of the file, ETC Shadow in genome key ring demo. This file can store the harsh value of the user's passwords. The adversary can use harsh collision to reverse engineer the harsh value and obtain the password. The earner of this file is root and the group is shadow. With a leak primitive, the adversary can scan the physical memory to search for the pattern because the first entry of the file is always for root and loaded to the beginning of the page. The second is interrupt descriptor table. When interrupt happens, the kernel will jump to the interrupt procedure for further process. The offset to the procedure entry is stored in the table. If the adversary can leak the offset, he or she can calculate the base address of loaded Kono image and thus bypass KALCR. There are many other types of sensitive data in kernel. Due to the time limit, I cannot enumerate them and I'm very happy to learn more. The exploitation approach I want to describe today is not a new attack. It's used in Pantui-on 2017 for CVE 2017-7184. In exploitation of this vulnerability, the tackle uses a flexible structure named transform the play state ESM. As shown in the diagram on the slide, this structure has two fields. One field is a bitmap length, which is an integer and another is bitmap, which is a buffer. The length of bitmap is determined dynamically and indicated by bitmap length. When Kono uses a structure, it obtains the length of bitmap from bitmap length. To do the exploitation, the tackle performs heap feng shui and places transform the play state ESM right after the vulnerable object. Then the tackle triggers the heap buffer overflow to overwrite bitmap length. The bitmap length is enlarged and misleads the kernel to believe the size of bitmap is larger than actual size. Later on, when the received message system call comes, the content in the bitmap is copied to user space while net input function. Since the bitmap length is enlarged, the heap region after the bitmap is also copied out, causing an overread. The tackle places the file structure after the bitmap. The file structure has a function point of field named fop, which points to a static variable EXT4 file operations. By leaking the value of the EXT4 file operations, the tackle knows address of the static variable and then calculates the base address of loaded kernel image for bypassing KSLR. The flexible object has two advantages in exploitation. One, it is ability to leak data. Another is the size of the object is determined dynamically. So it can be allocated to several general caches to be paired with vulnerable object and the victim object. We've talked about standard flexible structure, yes, which has a length field and an adjustable buffer after the end of the structure. Elastic object is extended from flexible object. On the right side of the slide, I just played three ways of extension. The first way is to have a large buffer defined in the middle of a data object. A length field within that object indicates the actual buffer size or more precisely speaking, the actual bytes used for storing data. At the time of defining the actual number of bytes, used for storing data, kernel typically examines a length field and ensures it doesn't go beyond the boundary of the large buffer. However, we discover that the kernel doesn't always enforce this essential check at the time of reading data from that buffer. As such, it eases an attacker's ability to manipulate the length field and thus construct a buffer over read. In the second and the third way, the two implementations do not enclose the length field and the adjustable buffer in the same kernel object. Instead, they place the length field and the adjustable buffer in two individual kernel objects. The difference between the second and third implementation is that one implementation contains an explicit reference to the adjustable buffer. In contrast, the third implementation references the adjustable buffer through a third intermediate kernel object. After the extension, let's see how we can perform exploitation using elastic object. The assumption of this attack is we've already obtained the right primitive on kernel heap, which tempos the length field as well as a pointer field if the elastic object is implemented in the second or third way. Later on, the value of length field is propagated to the size argument of copy to user function. Copy to user function has three arguments. The first argument is detonation indicating where the data is copied to. The second argument is source, which indicates where the data is copied from. The third argument is size, which represents how many bytes of data to copy. Now we've already controlled the size argument. On the right side of the slide, I show three situations of where the source could come from. The first situation is the source argument is the address of kernel stack. In this situation, if we enlarge the size value using the right primitive, we can overread the kernel stack and the leak stack nary and return address to user space. The second situation is the source argument is the address of a kernel heap. We can overread the kernel heap to disclose function pointer and the heap cookie. The third situation is a source argument is from the pointer field in the elastic object. And it is also tempoed by the adversary using the right primitive. In this situation, we can make the source argument to be any kernel address. As such, we can leak sensitive data like ETC shadow or interrupt descriptor table, which we mentioned in the previous slides. The severity of this attack is obvious. If the adversary has a right primitive on kernel heap by triggering vulnerabilities like slab autobahn right, use after free and double free, he or she can transfer this right primitive to obtain a leak primitive. This capability enables the adversary to leak stack nary, return address, encrypted heap cookie, function pointer, ETC shadow, interrupt descriptor table, and many other sensitive data. With these sensitive data in hand, it becomes easier for the tackles to perform following exploitation. Regarding the generality of this attack is unknown. First, we don't know what else channel functions in kernel except the use of, quality user can provide us with ability to communicate between kernel space and user space. Second, how many elastic structures and objects are there in the kernel code base? If we only have three or four, it's very hard to cover most stab caches, let alone to say powering them with vulnerability. The third question is, even if we have enough elastic structures and don't mean the length field and the point of field of them can be propagated to the channel functions. Without this guarantee, the adversary can hardly control the size argument as well as the source argument. The last question, giving a vulnerability, does it provide us with the right primitive to overwrite the length field and the point of field? It's possible that most vulnerabilities don't have that strong capability. However, generality problems are vital importance because it's related to the question that do we need to pay attention to this attack and do we need a mitigation? If the attack is very ad hoc, I don't see any necessity to build a medication. Probably a simple pattern is enough. As such, our research work mainly focus on studying the generality of this attack. First things first, we identify some channel functions in the kernel and lift them on the slide. We group them into three categories. The first category is memory copy API which is copy to user. The second one is specific to NetLink socket which is networking between color space and user space. To use this functionality requires the capability of network admin which is granted in the user's name space. Take NetLink code function as an example. Attribute learns which is highlighted with underline is a size argument and the data which is involved is a source argument. The third category is general networking. For example, SKB put data in which learn the size argument and data is a source argument. Some channel functions are the combination of two functions. For example, in NetLink, the return value of net economic data is a source argument which is later used in memory copy function. The size argument is currently memory copy. No matter what the function prototypes are, all of them have a source argument and a size argument. Our analysis begins from these channel functions. The first step in our static analysis is to identify the leaking ankle which is invoking to channel functions. I use that to represent source argument and a green for size argument in the channel function. The second step is to check where is this learns from In the diagram, the learns is from a structural variable named U payload. This type is user key payload. The third step is to check where is the source from. In the diagram, the source is a return value of K malloc. The type of the source is the user key payload two. We can clearly see the source and the learns are from the same structure type. Besides, we can learn that this structure variable is on the heap because it is generated through allocation. What's more, user key payload is a standard flexible structure because its size is a constant plus a variable. The offset of learns field and the adjustable buffer can also be tracked down. Through above analysis, we can learn which slab cache is responsible for holding the object. The last step of the analysis is to collect the constants along the path from the ankle retrieving lens to the ankle that leaks data. We do this examination because we want to see whether the kernel enforces the checking of learns field's legal value range. If the kernel says the learns cannot be too large, the leaking probably doesn't work. In the example on the slide, the kernel only ensures that the user controlled the parameter buff learns is larger than the data learns. Therefore, this checking doesn't influence the data leaking. Finally, we obtain a record for each identified elastic structure. We know the structure name, the cache holding the object, the offset of the learn field and pointer field, allocation sites, leaking sites, as well as all types of sensitive data can be leaked. In total, the static analysis tracks down 49 elastic structures in default configuration. We use kernel fuzzing and a manual analysis confirmed 38 of them. We list these structures here. In the table, the first column represents which cache the object can reside in. The second column is the structure's name. The third column is the offset of learns field and the pointer field. The fourth column is what sensitive data can be leaked. The fifth column is the privilege required to operate the object. The last column is the past constants. To sum up, most general caches are covered by identified structures. Note that the number of 36 and 38 are for structures, not objects. If we count the number in objects and the program sites that we use the objects, the statistics can be thousands. From this perspective, the elastic objects are pervasive in kernel code base. We use the 31 vulnerabilities to examine what we can do using elastic objects. The results show that 23 vulnerabilities is enabled with KASLR bypassing and the heap cookies leaking. 12 of them can leak stagnary and 5 of them can perform arbitrary read. Thus, I want to draw the conclusion that elastic object attack is general in Linux kernel. How about other operating system kernels? In XNU, the static analysis tracks down 16 structures and in 3BST, 20 structures. We used in total nine CVEs in 3BST and XNU. Five of them can bypass KASLR. Three of them can leak heap cookies because 3BST doesn't have heap cookie. Three of them can perform arbitrary read. It seems elastic object attack is an issue not only in Linux, but also in 3BST and XNU. To mitigate this elastic object attack, there are several mitigations in the Linux kernel that seems work, but I don't think so. Let me tell you why. The first potential mitigation is free list randomization. Without this mitigation, the freed slots are chained in the list linearly. This means the freed slots are physically continuous. With this feature, the adversary can predict the slab layout and perform stable heap function. With this mitigation, the freed slots are shuffled when kernel creates slab cache. Thus the other freed slots are randomized. In this way, the adversary can not predict the slab layout and it's harder for he or she to exploit slab auto bound write vulnerabilities. The limitations of this mitigation are first, it has no effects on use after free and double free exploitation. This is because the exploitation of these two bytes doesn't require to predict the slab layout. Second, there are many bypassing techniques against this mitigation. For example, heap groom, which is to first allocate the bounds of placehold objects and the victim object. The adversary frees the placehold objects and leaves holes on heap. After this, he or she can allocate the vulnerable object to the holes to perform heap function. Another technique is a freedist reversal. Due to the time limit, I will not elaborate on this because more details can be found online. The second potential mitigation is config GCC plotting random structure. This mitigation tries to randomize auto fields in the structure at the compilation phase. It prevents the tackles from predicting the offset of sensitive data within the structure. Take the structure on the slide as an example, the tackles want to override the function point of field initial to hijack control flow. Without the randomization, the offset of initial field is fixed and predictable. With the randomization, the initial field is shuffled to another order. Thus, the override doesn't always work. As such, this mitigation seems a threat to the tack. However, I want to say that this defense relies on random seed to perform randomization and the protection of this seed is not trivial. For example, Linux distros have to expose this random seed to their users for building third-party kernel modules. This is because the third-party kernel modules need to know how exactly the structure is defined after layout randomization for using these structures. The mitigation works well in house building kernel if the random seed can be protected appropriately. But for distros like Ubuntu and Debian, it's not very practical. The last potential mitigation is config hardenUserCopy, which is imparted from PaxUserCopy. This mitigation examines the size argument of copied user. If the source argument is a kernel stack address, this defense ensures that the size argument is smaller than the frame size. Only data in the current stack frame can be copied out. If the source argument is a kernel heap address, that defense ensures that the size argument is smaller than the slot size, class slot override is disallowed. The similar mechanism is also used in X and U kernel. While this technique can mitigate the threat of some of some elastic objects, it suffers from two problems. On the one hand, it only enforces the lens checking for copy to user. Other critical kernel functions for data transferring are not included. On the other hand, the legit lens range is not restricted enough. The sensitive data can reside in the cache slot or stack frame. It's still possible to leak them even after the mitigation is enforced. According to our discussion in the previous slides, there are now no mitigations in the kernel that can perfectly neutralize the threat of elastic objects. To this end, we propose a new defense mechanism. This mechanism isolates elastic objects that we identified into individual shadow caches. To be specific, we create an isolated shadow cache for each general cache during kernel boot up. Using shadow caches, we store elastic objects with the corresponding sizes. For example, the elastic object of object originally allocated in KMALOG96 will be assigned in KMALOG isolate 96 after the isolation mechanism is enabled. To support this isolation, we modify the kernel source code by adding one more flag at the allocation site. This flag specifies that the object should be allocated in the elastic object and it should be placed in the shadow caches. With the isolation mechanism, an adversary has little chance to leverage the vulnerability tied to other objects to manipulate the lens field and a point of field in elastic objects. Besides common hip spray objects and kernel objects with sensitive information like function pointers are also isolated from the elastic objects. They could not be used for hip feng shui and spraying. Several weeks after I submitted this presentation, I learned from GR Security that they have implemented more advanced isolation in their new defense named autoload. Autoload is much more aggressive in hip object isolation. Although I don't know more details about autoload, I'm pretty sure that its security improvements is very significant. We evaluated the performance overhead of our proposed mitigation. We used three sets of benchmarks. The first set is micro benchmarks. From LM bench, which tests the latency and the bandwidth of common system cost and the IO operations. The second set is macro benchmarks from Pharynx test suite, which runs five real world applications. To prevent the overhead from being hidden behind the sophisticated cone execution, we especially designed a third set benchmark to stress test the impact of our mitigation approach. This set of customized benchmarks uses the system core sequential to reach elastic object allocation and corresponding data leakage intensively. Overall, we could observe that the performance overhead is negligible with average performance drop less than 1%. We also evaluate the security of our proposed mitigation approach by the using third one vulnerabilities that we used to study the generality of the elastic object attack. For most vulnerabilities, we cannot find elastic objects that can be used for exploitation. This is because the elastic objects and the vulnerable objects are mostly different. They are isolated into two caches. There are no longer a possibility to use vulnerable objects to manipulate the length field of an elastic object. For vulnerable objects in CVE 2017, 7184 and CVE 2017, 17053, there are also elastic objects allocated in the shadow caches. Technically, they can be leveraged to override the data in the isolated caches and thus manipulate the length field of an elastic object for data disclosure. However, we argue that even if the situation exists, it will still raise the bar because the disclose the data is not likely to be useful for bypassing current mitigation. Taking the practice of circumventing KSR using CVE 2017, 17053, as an example, to use a vulnerable object to review a kernel-based address, in addition to leveraging the elastic object, an attacker usually has to identify a general object that encloses a function pointer. Then the attacker needs to place the object in the same isolated cache. However, due to the general and the elastic kernel object isolation, such an object is no longer available for this isolated cache. In addition to the defense we proposed, there are several alternative defense solutions we've ever considered. The first possible solution is to build shadow memory for each of the elastic objects allocated in the kernel. In that shadow memory, we can record the actual size of the corresponding object. When the kernel discloses data in an elastic buffer at an leaking angle, we could check whether the amount of the data migrating to the user space is within a legit range. Since the construction of shadow memory inevitably introduces memory and performance overhead, the key challenge of this solution is to develop a lightweight method to minimize overhead in a systematic method. Another possible solution is to design a mechanism to enable the integrity check for the data in the Lensfield. We introduce a checksum field. When the kernel allocates a corresponding object and initializes Lensfield, we could encrypt the Lens value and start it in the checksum field accordingly. With this design at a time of disclosing data in elastic buffer to the user land, the kernel could easily retrieve and scrutinize the checksum. The key challenge of implementing this idea is to ensure the addition of the checksum will not influence the usability of the kernel. Some elastic data structures are designed for protocols which have specific formats. After allocating objects in these types, the kernel references the data through corresponding offsets. If introducing additional field into such objects, one has to ensure that the newly added checksum field does not incur incorrect data reference. To sum up, first, we extend the flexible object to elastic to elastic object. Second, we design a systematic method demonstrating the generality of elastic object attack. We identify channel functions with track diagnostic structures in the kernel code base and use vulnerabilities to show the generality. Third, we investigate existing kernel mitigations and find none of them is perfect for mitigating this attack. Thus, we design a new defense. We evaluate the performance overhead and the security improvement of our proposed mitigation to show its cost and benefit. Thanks for listening and thank you very much for having me here. If you want to know more about me and my other projects or you don't have chance to ask questions in this session, feel free to follow me on Twitter. Contact me using email and check my personal page. Thank you all.