Libra : A Compatible Method for Defending Against Arbitrary Memory Overwrite
-
Upload
jeremy-huang -
Category
Software
-
view
710 -
download
3
description
Transcript of Libra : A Compatible Method for Defending Against Arbitrary Memory Overwrite
Libra: A Compatible Method for Defending Against Arbitrary Memory Overwrite
2
Outline• Chapter1 Introduction
– Statistics of Vulnerabilities and Exploits– Attack Principle
• Chapter2 Mechanism of Attack and Example– At the Second Step …– Kernel Data Structures to Overwrite
• Chapter3 Proposed Solution– Background Knowledge– Compatible Solution– Characteristics
• Chapter4 Implementation• Chapter5 Evaluation
– Compatible Comparison– Performance– Stability Testing– False Positive & Negative Positive
• Appendix– A Case Study : CVE-2013-2094
3
Statistics of Linux Kernel Vulnerabilities
From : www.cvedetails.com
4
Statistics of Vulnerabilities in 2013
From : www.cvedetails.com
5
Statistics of Exploits
6
Attack Principle• A typical exploit for arbitrary memory
overwrite of Privilege Escalation is described as following:1. Triggering the vulnerabilities for arbitrary
memory overwrite.
User spaceUser space
Kernel spaceNormal function
Function pointer(addr1)
addr1
7
Attack Principle
2. Overwriting any kernel function pointer, to make the pointer pointing to the payload address in user space.
Payload addr2
Kernel space
User space
Normal function
Function pointer(addr2)
addr1
8
Attack Principle3. Because the overwritten kernel function can be easily used when serving user requests, an unauthorized attacker can get the root access when the modified kernel function was used.
1. A Case Study : CVE-2013-20942. CVE-2013-2094 on x86-32
commit_creds(prepare_kernel_cred(NULL));
Payload addr2
Kernel space
User space
Normal function
Function pointer(addr2)
addr1
9
Kernel Data Structures Can Be Overwritten
• IDT table• ptmx_fops• …
10
Proposed Solution :Background knowledge
The interrupt handler address fields in an IDT table entry are composed of low_offset field, middle_offset field, and high_offset field.
11
ptmx_fops ?
pty (pseudo-teletype) is a pair of virtual character devices that provide a bidirectional communication channel. Pty consists of ptmx and pts.
For example:
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHATxue pts/0 61.66.243.96 Mon16 17:24m 0.21s 0.04s ssh [email protected] pts/1 36-231-101-220.d 10:27 0.00s 0.19s 0.01s w
12
Linux Device Driver Architecture
13
ptmx_fops ?
• static struct file_operations ptmx_fops;• file_operations – defined in <include/linux/fs.h>– contain a set of function pointers
• int (*fsync) (struct file *,loff_t,loff_t,int datasync);
– used by Kernel to access device driver’s functions
14
Ways to Find Addresses of Related Kernel Data Structures
• Use the assembly instruction - sidt• Search– system.map – /proc/kallsyms
15
Example
• grep ptmx_fops /boot/System.map-$(uname -r)
• grep ptmx_fops /proc/kallsyms• /* 56 is offset of fsync in struct file_operations on x86-32 */
int target = pmtx_ops + 56 //target is a kernel pointer
16
Hiding the Kernel Function Addresses
• #chmod o-r /boot/System.map-3.0.42-0.7-default
• #sysctl -w kernel.kptr_restrict=1
17
Kees Cook’s patch (Linux official patch)
__set_fixmap(FIX_RO_IDT,_pa_symbol(idt_table),PAGE_KERNEL_RO);
idt_descr.address = fix_to_virt(FIX_RO_IDT);
Compatibility: We are not sure that IDT table will be modified.
18
Proposed Solution
memoryImportant value : x Let 15
5 If x=1, it is ok.
If x=6, it will fail.
1Read-only
Page fault handler helps us to modify value (x=1)
19
Page fault error code bits
• The CPU pushes an error code on the stack before firing a page fault exception.
• The error code must be analyzed by the exception handler to determine how to handle the exception. http://wiki.osdev.org/Paging
20
Meaning of “error code = 3”
– bit 0 == 0: no page found 1: protection fault– bit 1 == 0: read access 1: write access– bit 2 == 0: kernel-mode access 1: user-mode access
21
Flowchart of Linux Page fault handlerAccess to
kernel space
Access in Kernel Mode
Noncontiguous memory area
address
Address is a wrongSystem call parameter
Compatiblesolution
22
Flowchart of Libra for IDT TableInvalid address= read_cr2
Page fault handler executes no_context()
Does the invalid address fall into the IDT table address
range?
Is the error_code equal to 3?
Continuing to execute no_context() YES
No
NoYES
23
Flowchart of Libra for IDT Table
Is the new value in Kernel space?
Close the Read-only attribute of IDT tableModify the value
Open the Read-only attribute of IDT tableUpdate the program counter
Page fault handler returns to the program that
needs to change IDT table
YESNo
24
Flowchart of Libra for ptmx_fopskallsyms_lookup_name("ptmx_fops")
;Invalid address = read_cr2();
Is the invalid address in the ptmx_fops
structure ?
Error code == 3 ? &&Modified value >
0xffffffff80000000
Continuing to execute
no_context() Yes
NO
25
Close the read-only attribute of ptmx_fopsModify the value
Open the read-only attribute of ptmx_fopsUpdate the program counter
Page fault returns to the program that needs
change ptmx_fops
26
Characteristics of Libra
– It is a software solution that does not require any extra hardware cost.
– It is a compromised solution between read-only solutions and writable solutions to enhance compatibility.
– It is a response-oriented security solution to avoid spending CPU resource for monitoring.
27
Implementation
• On Ubuntu 13.04 (Kernel version: 3.10.15) • On x86-64 architecture. • Intel(R) Pentium(R) D CPU 3.00GHz, 1GB RAM• [patch]x86: Use a read-only IDT alias on all
CPUs, by Kees Cook.
28
Evaluation:Compatible Comparison
• Adding a system call for compatible comparison idt_table2 = ((gate_desc *) idtr.address); idt_table2[i].offset_low = 0xbeef; idt_table2[i].offset_middle = 0xdead; idt_table2[i].offset_high = 0x12345678;
• Original zeroth entry of IDT table :*0xffffffffff57a008 (high_offset)= ffffffff*0xffffffffff57a000 (low_offset)=4df0*0xffffffffff57a004 (middle_offset)=816a
29
Evaluation:Compatible Comparison
• Kees cook’s solution led to this result that is as follow:• [131360.581351] pte_write(8000000001e22161):0• [131360.581355] *0xffffffffff57a008 (offset_high)= ffffffff• [131360.581358] *0xffffffffff57a000 (offset_low)=4df0• [131360.581360] *0xffffffffff57a004 (offset_middle)=816a
30
Evaluation:Compatible Comparison
• Libra solution led to this result that is as follow:• [11679.083463] pte_write(8000000001e22161):0• [11679.083466] *0xffffffffff57a008 (offset_high)= ffffffff
• [11679.083469] *0xffffffffff57a000 (offset_low)=beef
• [11679.083472] *0xffffffffff57a004 (offset_middle)=dead
31
Evaluation:Compatible Comparison
Kees Cook’s solution
LibraSolution
offset_low Read-only Writable
offset_middle Read-only Writable
offset_high Read-only Read-only
32
Evaluation:Compatible Comparison
•[ 146.215132] flush: (null)
• [ 146.215132] release value:ffffffff813e5880• [ 146.215132] fsync value: (null)• [ 146.215132] aio_fsync value: (null)• [ 146.215132] fasync value:ffffffff813e4430• [ 146.215132] Jeremy, cr2 = ffffffffff577060• [ 146.215132] Jeremy, page fault handler in kernel space is trigger!!!• [ 146.215132] address 0xffffffffff577060 in CR2• [ 146.215132] error_code = 3• [ 146.215132] page fault run to line 1068• [ 146.215132] page fault run to line 772• [ 146.215132] Jeremy, *kallsyms_lookup_name(ptmx_fops) : ffffffffff577000 in fault.c• [ 146.215132] The modified value at ptmx_fops : ffffffff8100beef• [ 146.215132] address : ffffffffff577060
•[ 146.236822] flush:ffffffff8100beef
Before modifing
After modifing
33
Evaluation:Performance
• We do performance testing through perf that is in Linux Kernel source code.
• “perf stat –r 100000 ./test_modify_idt 0”• The performance of Kees Cook’s solution :
34
Evaluation:Performance
• The performance of compatible solution :
35
Evaluation:Performance
Kees Cook solution Compatible solution0.058
0.0585
0.059
0.0595
0.06
0.0605
0.061
0.0615
Seconds
seconds
(+- 0.02%)
36
Evaluation:Stability testing
• “The Linux™ Test Project (LTP)is a joint project started by SGI™ and maintained by IBM®, that has a goal to deliver test suites to the open source community that validate the reliability, robustness, and stability of Linux.” -http://linux-test-project.github.io/
37
Evaluation:Stability testing
• Total Tests: 1424
Original Ubuntu
LibraUbuntu
Total Skipped Tests 117 138Total Failures 59 80Kernel Version 3.8.0-19-generic 3.10.15
38
Evaluation:False Positives & False Negatives
• False Positives : – Run four months.– Firefox, LibreOffice, OpenSSH, LXR website,
MSMBuilder.
39
Evaluation:False Positives & False Negatives
• False Negatives :– Linux PERF_EVENTS - Local Root Exploit • Sd, wzt, Vitaly Nikolenko, sorbo
– FreeBSD 9.0 Intel SYSRET Kernel Privilege Escalation exploit
– Nvidia Linux driver Privileges Escalation– CVE-2010-3081 & CVE-2010-3301: Linux kernel
COMPAT Privilege Escalation
40
Related Work• RGBDroid: A Novel Response-based Approach to Android Privilege Escalation Attacks.• Kees Cook’s patch: x86: Use a read-only IDT alias on all CPUs
• 2014-05-31, Vitaly Nikolenko’s exploit * Supported targets: * [0] Ubuntu 12.04.0 - 3.2.0-23-generic * [1] Ubuntu 12.04.1 - 3.2.0-29-generic * [2] Ubuntu 12.04.2 - 3.5.0-23-generic• uint64_t targets[3][3] = {{0xffffffff81ef67e0, // perf_swevent_enabled 0xffffffff81091630, // commit_creds 0xffffffff810918e0}, // prepare_kernel_cred {0xffffffff81ef67a0, 0xffffffff81091220, 0xffffffff810914d0}, {0xffffffff81ef5940, 0xffffffff8107ee30, 0xffffffff8107f0c0} };• Kernel address space layout randomization, Kees Cook, October 9, 2013, Linux Security Summit
41
Any Questions?
Thank you~
42
Appendix A
• A Case Study : CVE-2013-2094• A Case Study : CVE-2013-2094 on x86-32
43
Integer issues - Sign conversion issues (CVE-2013-2094)
• int fd = syscall(__NR_perf_event_open, ,…)
• After executing perf_swevent_init, an attacker can increase the content of any kernel address by 1.
after close(fd)
• After executing sw_perf_event_destroy, an attacker can decrease the content of any user address by 1.
44
A case study : CVE-2013-2094• /kernel/events/core.c1.static int perf_swevent_init(2. )3.{4. int event_id = event->attr.config;5. 6. /* ... */7. 8. if (event_id >= PERF_COUNT_SW_MAX)9. return -ENOENT;10. // PERF_COUNT_SW_MAX == 911. /* ... */12. 13. atomic_inc(&perf_swevent_enabled[event_id]);
45
A case study : CVE-2013-2094
/kernel/events/core.c1.static void sw_perf_event_destroy(2. )3.{4. u64 event_id = event->attr.config;5. 6. /* ... */7. 8.atomic_dec(&perf_swevent_enabled[event_id]);9. 10. /* ... */
46
Physical memoryUserSpace
0x00000000 00000000
0x00007fff ffffffff
Virtual memory
128 TB
64 TB
0xffff8000 00000000guard hole
0xffff8800 00000000__PAGE_OFFSET
0xffffffff 80000000__START_KERNEL_map
Kernel text 512MB
8MBVSYSCALL
4KB (a page size)FIXADDR_TOPFIXADDR_START
47
Linux 64-bit memory layout
0000000000000000 - 00007fffffffffff (=47 bits) user space, different per mmhole caused by [48:63] sign extension
ffff800000000000 - ffff80ffffffffff (=40 bits) guard holeffff880000000000 - ffffc7ffffffffff (=64 TB) direct mapping of all phys. memoryffffc80000000000 - ffffc8ffffffffff (=40 bits) holeffffc90000000000 - ffffe8ffffffffff (=45 bits) vmalloc/ioremap spaceffffe90000000000 - ffffe9ffffffffff (=40 bits) holeffffea0000000000 - ffffeaffffffffff (=40 bits) virtual memory map (1TB)... unused hole ...ffffffff80000000 - ffffffffa0000000 (=512 MB) kernel text mapping, from phys 0ffffffffa0000000 - ffffffffff5fffff (=1525 MB) module mapping spaceffffffffff600000 - ffffffffffdfffff (=8 MB) vsyscallsffffffffffe00000 - ffffffffffffffff (=2 MB) unused hole• From (Documentation/x86/x86_64/mm.txt)
48
Integer issues - Sign conversion issues(CVE-2013-2094)
In perf_swevent_init$ cat /boot/System.map-2.6.32-358.el6.x86_64 | grep perf_swevent_enabledffffffff81f360c0 B perf_swevent_enabled
P.S : signed extension because of int typeint event_id == 0xffffffff == -1 == 0xffffffffffffffff (x86-64)
perf_swevent_enabled[-1] ==0xffffffffffffffff * 4 + 0xffffffff81f360c0 == 0xFFFFFFFF81F360BC
int event_id == 0xfffffffe == -2 -->perf_swevent_enabled[-2] ==0xfffffffffffffffe * 4 + 0xffffffff81f360c0 == 0xFFFFFFFF81F360B8
49
Integer issues - Sign conversion issuesIn sw_perf_event_destroy()
Let's assume again event->attr.config == 0xffffffff --> P.S. No signed extension
0xffffffff [32bit] => 0x00000000ffffffff [64bit]
• perf_swevent_enabled[-1] address in sw_perf_event_destroy:– 0x00000000ffffffff * 4 + 0xffffffff81f360c0 == 0x00000003 81f360bc
• perf_swevent_enabled[-1] address in perf_swevent_init:– 0xffffffffffffffff * 4 + 0xffffffff81f360c0 == 0xffffffff 81f360bc
Even though the addresses of perf_swevent_enabled[-1] in sw_perf_event_destroy() and perf_swevent_init() are different, the 6 MSBs of their last 8 hex digitals are the same.
50
Perf_swevent_enabled[0]
0xffff ffff +1
Perf_swevent_enabled[-2]Perf_swevent_enabled[-1]
user
Kernel
NOP + Shellcode<-0x00000000 81000000
<- 0xffffffff 81734000
<-0x00000003 80000000
<- 0xffffffff 81734048 Hijackedidt.addr
Offset1----------->
idt.addr + 0x48
0000….
-1 by destroy(-2)
<-0x00000003 90000000
-1 by destroy(-1)
1.Allocate red region & green region.
2. Trigger vulnerability for measuringperf_event_open(-1)perf_event_open(-2)
<- 0xffffffff 817e1340
<-0x00000003 817e1338 <-0x00000003 817e133c
4.asm(“int $0x4”); root got!
<- 0xffffffff 80000008
sw_perf_event_destroy()a.k.a destroy()
offset2
offset3(0x48)
offset1
+=1 by init(-2)+=1 by init(-1)
idt table
perf_swevent_init() a.k.a init()
Offst1----------->
0x0000 0000
3. perf_event_open(- i + (((idt.addr&0xffff ffff)-0x80000000)/4)+16)
offset1 offset24 offset34
51
Modify the ptmx_fops In exploit// 56 is offset of fsync in struct file_operations int target = pmtx_ops + 56; int payload = -((perf_swevent_enabled - target)/4); perf_swevent_enabled + (payload*4) Trigger int ptmx = open("/dev/ptmx", O_RDWR);fsync(ptmx);
Source code : cve-2013-2094 port to x86-32
52
4. Trigger vulnerability . fsync(ptmx); root got!
4. Create a lot of child process. Each process executes Perf_event_open(Offset) 256 times. Total 256 processes.( 256*256= 65536)
1. Allocate 0x10000 for payload
<-0xC0000000
<-fsync
Payload
Null
<-ptmx_fops
Perf_swevent_enabled->
3.Offset=(Perf_swevent_enabled -fsync)/4;
56
<-0x00010000
12
2. Find perf_swevent_enabled & ptmx_fops by system.map
3…65536(0x10000)