http://adl.tw/~jeremy/slides/presentation2.pptx
Attached detailed Analysis of CVE-2013-2094 (&on x86-32).
Exploit the CVE-2013-2094 with animation
There have been more vulnerabilities in the Linux Kernel in 2013 than there had been in the previous decade. In this paper, the research was focused on defending against arbitrary memory overwrites in Privilege Escalation.
To avoid malicious users getting root authority. The easiest way is to set the sensitive data structure to read-only. But we are not sure the sensitive data structure will never be modified by legal behavior from a normal device driver; thus, we posed a compatible solution between read-only solutions and writable solutions to enhance compatibility.
The main idea that we posed not only solves the above problem, but also the general problem which is ensuring that important memory values can only be changed within a safe range.
It is not just set to read-only.
Key Word : Linux Kernel Vulnerabilities、exploit、Privilege Escalation
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.
6
Normal 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.
7
addr2
Normal function
Function pointer(addr2)
addr1
8. Attack Principle
3. 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-2094
2. CVE-2013-2094 on x86-32
8
commit_creds(prepare_kernel_cred(NULL));
addr2
Normal function
Function pointer(addr2)
addr1
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.
10
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 WHAT
xue pts/0 61.66.243.96 Mon16 17:24m 0.21s 0.04s ssh
bbs@ptt.cc
jeremy pts/1 36-231-101-220.d 10:27 0.00s 0.19s 0.01s w
11
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
13
14. Ways to Find Addresses of Related
Kernel Data Structures
14
• Use the assembly instruction - sidt
• Search
– system.map
– /proc/kallsyms
15. Example
15
• 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
16
18. Proposed Solution
18
Important value : x Let 1 ≤ 𝐱 ≤ 5
If x=1, it is ok.
If x=6, it will fail.
Read-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
19
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
20
21. 21
Flowchart of Linux Page fault handler
Access to
kernel space
Access in
Kernel Mode
Noncontiguous
memory area
address
Address is a wrong
System call
parameter
Compatible
solution
22. Flowchart of Libra for IDT Table
22
Invalid 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()
23. Flowchart of Libra for IDT Table
23
Is the new value in
Kernel space?
Close the Read-only attribute of IDT table
Modify the value
Open the Read-only attribute of IDT table
Update the program counter
Page fault handler returns to the
program that
needs to change IDT table
24. Flowchart of Libra for ptmx_fops
24
kallsyms_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()
25. 25
Close the read-only attribute of ptmx_fops
Modify the value
Open the read-only attribute of ptmx_fops
Update 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.
26
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.
27
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
28
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
29
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
30
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
32
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 :
33
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/
36
37. Evaluation:
Stability testing
• Total Tests: 1424
37
Original
Ubuntu
Libra
Ubuntu
Total Skipped Tests
117 138
Total Failures
59 80
Kernel Version
3.8.0-19-generic 3.10.15
42. Appendix A
• A Case Study : CVE-2013-2094
• A Case Study : CVE-2013-2094 on x86-32
42
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.
43
44. A case study : CVE-2013-2094
• /kernel/events/core.c
1.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 == 9
11. /* ... */
12.
13. atomic_inc(&perf_swevent_enabled[event_id]
);
44
47. Linux 64-bit memory layout
0000000000000000 - 00007fffffffffff (=47 bits) user space, different per mm
hole caused by [48:63] sign extension
ffff800000000000 - ffff80ffffffffff (=40 bits) guard hole
ffff880000000000 - ffffc7ffffffffff (=64 TB) direct mapping of all phys. memory
ffffc80000000000 - ffffc8ffffffffff (=40 bits) hole
ffffc90000000000 - ffffe8ffffffffff (=45 bits) vmalloc/ioremap space
ffffe90000000000 - ffffe9ffffffffff (=40 bits) hole
ffffea0000000000 - ffffeaffffffffff (=40 bits) virtual memory map (1TB)
... unused hole ...
ffffffff80000000 - ffffffffa0000000 (=512 MB) kernel text mapping, from phys 0
ffffffffa0000000 - ffffffffff5fffff (=1525 MB) module mapping space
ffffffffff600000 - ffffffffffdfffff (=8 MB) vsyscalls
ffffffffffe00000 - ffffffffffffffff (=2 MB) unused hole
• From (Documentation/x86/x86_64/mm.txt)
47
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_enabled
ffffffff81f360c0 B perf_swevent_enabled
P.S : signed extension because of int type
int 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
48
49. Integer issues - Sign conversion issues
In 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.
49
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 Hijacked
idt.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 measuring
perf_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()
50
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 offset2÷4 offset3÷4
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
51
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
52
Payload
Null
3.Offset=
(Perf_swevent_enabled -
fsync)/4;
56
12
2. Find perf_swevent_enabled
& ptmx_fops by system.map
3…65536(0x10000)
而有vulnerability未必有相對應的exploit
這裡統計2009至2013的一些exploit
This statistics of Linux Kernel exploits is collected by exploit-db [21], packetstorm [22] from 2009 to 2013. Therefore, we know the exploits of Linux Kernel are in the majority.
Privilege Escalation 16
DoS 6 Buffer Overflow 1
Memory Disclosure 2
Total(弱點總數) 25
These kernel functions will create a new credit structure with root privileges, and then commit that credit structure to the current process. After returning to user-space, a root shell can be spawned.
4-bit Linux allows up to 128 TB of virtual address space for individual processes, and can address approximately 64 TB of physical memory
Ref. http://en.wikipedia.org/wiki/X86-64
http://code.woboq.org/linux/linux/arch/x86/include/asm/page_64_types.h.html