a bug in the server's packet receiving code...

a bug in the server's packet receiving code...

Postby Batlin on Wed Jan 12, 2011 2:17 pm

While preparing my next project I discovered a flaw in the server's code that could lead into the server dropping certain fragmented packets.

Let me first explain the server's loop per receive:
    - Read as many bytes as possible, which can fit into the buffer (64KB)
    - This buffer is initially filled with zeroes
    - Ensure we have enough bytes to start handling the first packet available
    - Start handling the packets

Handling the packets consist of two big parts:
    - Handling packets which do not require you to be logged on
    - Handling packets which require you to be logged on
    - At the end of handling a packet, copy the remainder of the buffer to the front

UO packets consist of two types of packets, packets with a fixed length and packets with a dynamic length. When handling packets with a fixed length both the server and the client must speak the same language. If one of them send a packet of different length other than the expected length, to other side will turn into an endless loop waiting for the remainder of the packet to be received. If you send too much data, then the other side will process the excess as if it were a new, seperate packet.

The bug is this: when the server checks for the packet to be valid, it requires a packet ID. Therefor the first check the server does is ensuring atleast one byte has been received. After obtaining the packet ID it will query its internal database to know if the packet is of fixed length or dynamic length. In case of fixed length, the server will not continue handling the packet until at least all data has been received for it. In case of dynamic length, the server will check the next 2 bytes in the packet as they contain the size of the dynamic data. However, the server code DOES NOT test that atleast 3 bytes have been received and that could be a problem.

The following python program demonstrates the potional problem:
Code: Select all
import socket
import time

s = socket.socket()
s.connect(("192.168.192.112", 10016))

packet = "\x03"
s.send(packet)
time.sleep(1)
packet = "\xA4".ljust(149,"\xFF")
s.send(packet)

time.sleep(3)

packet = "\x03"
s.send(packet)
time.sleep(1)
packet = "\x77"
s.send(packet)



First packet 0x03 is send, this is a dynamic packet.
The server's buffer will contain 0x03 00 00 00 00 and so-on.
Therefor the dynamic-length checked will be 0x0000.
The packet is discarded.

Next packet 0xA4 is send, this is a fixed packet that is ignored by the server.
Normally this packet contains system information about the client's PC. I filled it here with 0xFF.
Therefor the buffer now contains 0xA4 FF FF FF and so-on

Then packet 0x03 is send.
The buffer now contains 0x03 FF FF FF and so-on.
The dynamic-size is now 0xFFFF, and the server expects to receive 65535 more bytes and will wait.
Remember, there is only one valid client byte in the buffer.

We send 0x77.
The buffer now contains 0x03 0x77 FF FF and so-on.
There are 2 valid bytes from the client in buffer now, 0x03 and 0x077, the first FF is still garbage which the server is interpreting as it were client data.

I'm again gonna try to explain the effects of the bug:
If the packet arrives fragmented and in-case of a dynamic lengtht packet, less than 3 bytes are received, then the buffer will contain an invalid value. As the server fails to check that it has atleast 3 bytes, this will be a problem. The packet may be dropped, or may be parsed incorrectly or if you're lucky, the server keeps waiting up to the next byte. What will happen is up-to the packet being received, the new length and the data already in the buffer! In worst-case, the dynamic-length data is gonna be interpreted as if it were a seperate packet causing the client to hang.
Validate packet siz.png
Validate packet siz.png (24.46 KiB) Viewed 20 times
The red line is where the dynamic-length is obtained.
<Derrick> RunUO AI is kind of a functional prototype, which i have hacked into something resembling OSI behavior, but only by complitcating everything
Batlin
Site Admin
 
Posts: 306
Joined: Wed Apr 08, 2009 6:35 am


Return to UO Demo

Who is online

Users browsing this forum: No registered users and 1 guest