OpenBSD Remote Exploit Only two remote holes in the default install - - PowerPoint PPT Presentation
OpenBSD Remote Exploit Only two remote holes in the default install - - PowerPoint PPT Presentation
OpenBSD Remote Exploit Only two remote holes in the default install Alfredo A. Ortega June 30, 2007 Mbuf buffer overflow Buffer overflow Researching the OpenBSD 008: RELIABILITY FIX a new vulnerability was found: The m dup1()
Mbuf buffer overflow
Buffer overflow
Researching the “OpenBSD 008: RELIABILITY FIX” a new vulnerability was found: The m dup1() function causes an overflow on the mbuf structure, used by the kernel to store network packets.
mbuf1 mbuf2 mbuf3 mbuf4 End of overflow Copy direction
Figure: mbuf chain overflow direction
The function m freem() crashed...
Searching for a way to gain code execution
Searching for a way to gain code execution
C code equivalent
/ s y s /mbuf . h #d e f i n e MEXTREMOVE(m) do { \ i f (MCLISREFERENCED(m)) { \ MCLDEREFERENCE(m) ; \ } e l s e i f ((m )−>m f l a g s & M CLUSTER) { \ p o o l p u t (&mclpool , (m )−>m ext . e x t b u f ) ; \ } e l s e i f ((m )−>m ext . e x t f r e e ) { \ (∗((m )−>m ext . e x t f r e e ) ) ( (m )−>m ext . ext buf , \ (m )−>m ext . e x t s i z e , (m )−>m ext . e x t a r g ) ; \ } e l s e { \ f r e e ((m )−>m ext . ext buf , (m )−>m ext . e x t t y p e ) ; \ } \ (m )−>m f l a g s &= ˜(M CLUSTER|M EXT ) ; \ (m )−>m ext . e x t s i z e = 0; /∗ why ??? ∗/ \ } while (/∗ CONSTCOND ∗/ 0)
IcmpV6 packets
Attack vector
We use two IcmpV6 packets as the attack vector
Header
Fragmentation Header IPv6 Header
Mbuf chain Fragment 2
Icmpv6
Icmpv6 Header Trampoline ShellCode SyscallHook Payload
Header mbuf 2 mbuf 1 Header mbuf 3
Hop−by−Hop Header Fragmentation Header IPv6 Header
Fragment 1
Figure: Detail of IcmpV6 fragments
Where are we?
Code execution
We really don’t know where in kernel-land we are. But ESI is pointing to our code.
User process Hooked syscall ShellCode Kernel Ring 0 Ring 3 Kernel Int 0x80 ShellCode ? ? ? ? ? ? ? ? ? ? ?
Initial situation Final situation
iret Where we are? Ring 0 ESI
Figure: Initial and final situations
Now what?
Hook (remember DOS TSRs?)
We hook the system call (Int 0x80)
User process INT 0x80 Kernel return Hook Hooked syscall User process INT 0x80 Kernel Ring 3 Ring 0 return Normal syscall
Normal System Call Hooked System Call
Figure: System call hook
Note: If the OS uses SYSENTER for system calls, the operation is slightly different.
New syscall pseudo-code
- 1. Adjust segment selectors DS and ES (to use movsd
instructions)
New syscall pseudo-code
- 1. Adjust segment selectors DS and ES (to use movsd
instructions)
- 2. Get curproc variable (current process)
New syscall pseudo-code
- 1. Adjust segment selectors DS and ES (to use movsd
instructions)
- 2. Get curproc variable (current process)
- 3. Get user Id (curproc− >userID)
New syscall pseudo-code
- 1. Adjust segment selectors DS and ES (to use movsd
instructions)
- 2. Get curproc variable (current process)
- 3. Get user Id (curproc− >userID)
- 4. If userID == 0 :
4.1 Get LDT position 4.2 Extend DS and CS on the LDT (This disables WˆX!) 4.3 Copy the user-mode code to the the stack of the process 4.4 Modify return address for the syscall to point to our code
New syscall pseudo-code
- 1. Adjust segment selectors DS and ES (to use movsd
instructions)
- 2. Get curproc variable (current process)
- 3. Get user Id (curproc− >userID)
- 4. If userID == 0 :
4.1 Get LDT position 4.2 Extend DS and CS on the LDT (This disables WˆX!) 4.3 Copy the user-mode code to the the stack of the process 4.4 Modify return address for the syscall to point to our code
- 5. Restore the original Int 0x80 vector (remove the hook)
New syscall pseudo-code
- 1. Adjust segment selectors DS and ES (to use movsd
instructions)
- 2. Get curproc variable (current process)
- 3. Get user Id (curproc− >userID)
- 4. If userID == 0 :
4.1 Get LDT position 4.2 Extend DS and CS on the LDT (This disables WˆX!) 4.3 Copy the user-mode code to the the stack of the process 4.4 Modify return address for the syscall to point to our code
- 5. Restore the original Int 0x80 vector (remove the hook)
- 6. Continue with the original syscall
OpenBSD WˆX internals
WˆX: Writable memory is never executable
i386: uses CS selector to limit the execution. To disable WˆX, we extend CS from ring0.
Extension Extension User Code Segment (CS) User Data Segment (DS) 0x00000000 0xffffffff 4 GB 512 MB stack
.so .text stack heap .so
Figure: OpenBSD selector scheme and extension
Defeating WˆX from ring0
Our algorithm, independent of the Kernel: s l d t ax ; Store LDT index
- n EAX
sub esp , byte 0 x7f sgdt [ esp +4] ; Store g l o b a l d e s c r i p t o r t a b l e mov ebx , [ esp +6] add esp , byte 0 x7f push eax ; Save l o c a l d e s c r i p t o r t a b l e index mov edx , [ ebx+eax ] mov ecx , [ ebx+eax+0x4 ] shr edx ,16 ; base low− − >edx mov eax , ecx s h l eax ,24 ; base middle − − > edx shr eax ,8
- r
edx , eax mov eax , ecx ; b a s e h i g h − − > edx and eax ,0 xff000000
- r
edx , eax mov ebx , edx ; ldt− − > ebx ; Extend CS s e l e c t o r
- r
dword [ ebx+0x1c ] , 0 x000f0000 ; Extend DS s e l e c t o r
- r
dword [ ebx+0x24 ] , 0 x000f0000
Injected code
WˆX will be restored on the next context switch, so we have two choices to do safe execution from user-mode:
Ring 3 User Stack Ring 3 User Stack
- 1. fork()
2.mmap() 3.copy 4.jmp to mmaped mprotect() extends CS permanently
- 1. mprotect()
2.fork() From kernel... From kernel...
Turning off W^X (from usermode) Creating a W+X section
3.Standard
- 5. Standard
user−mode code user−mode code
Figure: Payload injection options
Questions before going on?
Now we are executing standard user-mode code, and the system has been compromised.
Proposed protection
Limit the Kernel CS selector
The same strategy than on user-space. Used on PaX (http://pax.grsecurity.net) for Linux. 0x00000000 0xffffffff 4 GB
kernel
0xD0000000 0xD1000000 Kernel Code Segment (CS) Kernel Data Segment (DS)
CS shrink
mbuf chains, etc
Figure: OpenBSD Kernel CS selector shrink
A third remote vulnerability?
IPv6 Routing Headers
Uninitialized variable on the processing of IPv6 headers.
- 1. DoS or Code Execution (depending who you ask!)
- 2. Present on CVS from January to March of 2007 (very few
systems affected)
Conclusions
In this article we presented:
- 1. Generic kernel execution code and strategy
- 2. Possible security improvement of the kernel
Conclusions
In this article we presented:
- 1. Generic kernel execution code and strategy
- 2. Possible security improvement of the kernel
- 3. A third bug - No software is perfect