|
#######################################################################
Luigi Auriemma
Application: ENet library
http://enet.bespin.org
Versions: <= Jul 2005 (it's the current CVS version)
Platforms: Windows, *nix, *BSD and more
Bugs: A] invalid memory access (32 bit)
B] allocation abort with fragment
Exploitation: remote
Date: 12 Mar 2006
Author: Luigi Auriemma
e-mail: aluigi@autistici.org
web: http://aluigi.altervista.org
#######################################################################
1) Introduction
2) Bugs
3) The Code
4) Fix
#######################################################################
==============1) Introduction
==============
ENet is a powerful open source library for handling UDP connections (it
can be defined almost a sort of TCP over UDP).
It's very used in some games and engines like Cube, Sauerbraten,
Duke3d_w32 and others.
#######################################################################
======2) Bugs
======
---------------------------------
A] invalid memory access (32 bit)
---------------------------------
ENet uses 32 bit numbers for almost all the parameters in its packets,
like fragments offset, data size, timestamps, challenge numbers and so
on.
Each packet received by the library (enet_host_service) is handled by
the enet_protocol_handle_incoming_commands function.
This function uses a pointer (currentData) which points to the current
command, each packet can contain one or more commands which describe
operations like a connection request, an acknowledge, a fragment, a
message and more.
The instruction which checks this pointer to avoid that it points over
the received packet can be eluded through a big (negative on 32 bit
CPU) header.commandLength parameter.
After having bypassed the check currentData will point to an invalid
zone of the memory and when the cycle will continue on the subsequent
command (commandCount must be major than one) the application will
crash.
64 bit CPUs should be not vulnerable.
>From enet_protocol_handle_incoming_commands in protocol.c:
...
currentData = host -> receivedData + sizeof (ENetProtocolHeader);
while (commandCount > 0 &&
currentData < & host -> receivedData [host -> receivedDataLength])
{
command = (ENetProtocol *) currentData;
if (currentData + sizeof (ENetProtocolCommandHeader) > & host -> receivedData [host -> receivedDataLength])
return 0;
command -> header.commandLength = ENET_NET_TO_HOST_32 (command -> header.commandLength);
if (currentData + command -> header.commandLength > & host -> receivedData [host -> receivedDataLength])
return 0;
-- commandCount;
currentData += command -> header.commandLength;
...
---------------------------------
B] allocation abort with fragment
---------------------------------
ENet supports also the handling of fragments used to build the messages
bigger than the receiver's MTU.
When a fragment is received the library allocates the total message
size in memory so it can easily rebuild all the subsequent fragments in
this buffer.
If the total data size specified by the attacker cannot be allocated,
the library calls abort() and all the program terminates.
>From enet_protocol_handle_send_fragment in protocol.c:
...
startCommand = enet_peer_queue_incoming_command (peer,
& hostCommand,
enet_packet_create (NULL, totalLength, ENET_PACKET_FLAG_RELIABLE),
fragmentCount);
#######################################################################
==========3) The Code
==========
http://aluigi.altervista.org/poc/enetx.zip
#######################################################################
=====4) Fix
=====
No fix.
No reply from the developers.
#######################################################################
---
Luigi Auriemma
http://aluigi.altervista.org