OpenBSD Remote Exploit - Black Hat · OpenBSD Remote Exploit ”Only two remote holes in the...
Transcript of OpenBSD Remote Exploit - Black Hat · OpenBSD Remote Exploit ”Only two remote holes in the...
OpenBSD Remote Exploit
”Only two remote holes in the default install”
Alfredo A. Ortega
June 30, 2007
Mbuf buffer overflow
Buffer overflowResearching the “OpenBSD 008: RELIABILITY FIX” a new vulnerability was found: The m dup1() function causesan 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
#de 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) { \
poo l pu 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 . e x t bu f , \(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 . e x t bu f , (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 ??? ∗/ \
} wh i l e ( /∗ CONSTCOND ∗/ 0)
IcmpV6 packets
Attack vectorWe 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 executionWe 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 movsdinstructions)
2. Get curproc variable (current process)
3. Get user Id (curproc− >userID)
4. If userID == 0 :
4.1 Get LDT position4.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 process4.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
New syscall pseudo-code
1. Adjust segment selectors DS and ES (to use movsdinstructions)
2. Get curproc variable (current process)
3. Get user Id (curproc− >userID)
4. If userID == 0 :
4.1 Get LDT position4.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 process4.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
New syscall pseudo-code
1. Adjust segment selectors DS and ES (to use movsdinstructions)
2. Get curproc variable (current process)
3. Get user Id (curproc− >userID)
4. If userID == 0 :
4.1 Get LDT position4.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 process4.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
New syscall pseudo-code
1. Adjust segment selectors DS and ES (to use movsdinstructions)
2. Get curproc variable (current process)
3. Get user Id (curproc− >userID)
4. If userID == 0 :
4.1 Get LDT position4.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 process4.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
New syscall pseudo-code
1. Adjust segment selectors DS and ES (to use movsdinstructions)
2. Get curproc variable (current process)
3. Get user Id (curproc− >userID)
4. If userID == 0 :
4.1 Get LDT position4.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 process4.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
New syscall pseudo-code
1. Adjust segment selectors DS and ES (to use movsdinstructions)
2. Get curproc variable (current process)
3. Get user Id (curproc− >userID)
4. If userID == 0 :
4.1 Get LDT position4.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 process4.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 executablei386: 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 0xffffffff4 GB
512 MB
stack
.so.text stackheap.so
Figure: OpenBSD selector scheme and extension
Defeating WˆX from ring0
Our algorithm, independent of the Kernel:
s l d t ax ; S to r e LDT index on EAXsub esp , byte 0 x7 fsgdt [ esp+4] ; S to r e g l o b a l d e s c r i p t o r t a b l emov ebx , [ esp+6]add esp , byte 0 x7 fpush eax ; Save l o c a l d e s c r i p t o r t a b l e i ndexmov edx , [ ebx+eax ]mov ecx , [ ebx+eax+0x4 ]sh r edx , 16 ; base low−−>edxmov eax , ecxs h l eax , 24 ; b a s e m idd l e −−> edxsh r eax , 8or edx , eaxmov eax , ecx ; b a s e h i g h −−> edxand eax , 0 x f f 000000or edx , eaxmov ebx , edx ; l d t−−> ebx
; Extend CS s e l e c t o ror dword [ ebx+0x1c ] , 0 x000f0000
; Extend DS s e l e c t o ror dword [ ebx+0x24 ] , 0 x000f0000
Injected code
WˆX will be restored on the next context switch, so we have twochoices to do safe execution from user-mode:
Ring 3
UserStack
Ring 3
UserStack
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 systemhas been compromised.
Proposed protection
Limit the Kernel CS selectorThe same strategy than on user-space. Used on PaX (http://pax.grsecurity.net) for Linux.
0x00000000 0xffffffff4 GB
kern
el
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 fewsystems affected)
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
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
Final Questions?
Thanks to:Gerardo Richarte: Exploit ArchitectureMario Vilas and Nico Economou: Coding support