views:

72

answers:

4

Hi all,

I have a C\C++ code that receives a structure over the network, from this form:

struct DataStruct
{
int DataLen;
BYTE* Data;
}

The code I have runs over Data in a loop of DataLen times and processes the data.

...The problem:

After the code came to security experts for penetration tests, they prepared a fake application which sends this struct with DataLen bigger than the real length of Data. This causes, of course, an access violation exception.

So, the question is - how can I validate the real length of the received Data? Is it possible without changing the structure?

Thanks in advance.

+2  A: 

You know how much bytes you have received, so just compare it with DataLen.

Kirill V. Lyadvinsky
Maybe I wasn't clear - this is exactly my problem: I **don't** know how many bytes did I get...
rursw1
How's that? Almost any network IO function gives you this information.
Kirill V. Lyadvinsky
+4  A: 

Nice security experts! I wish my company had a department like that.

Whenever data is received from the network, the network IO reports the number of bytes actually written to the buffer, whether you used read(2), recv(2), or boost::asio::async_read or anything else I've seen. Typical use case when there's a "number of bytes to follow" field in the header of your data structure, is to repeatedly call read/recv/etc until that many bytes were received (or until error occurred), and only then it should construct and return your DataStruct (or report error).

Cubbi
+1  A: 

It is impossible without changing the structure. Data received from TCP/IP socket is plain stream. Logically, it is not divided into packets. Physical packet may contain one or more DataStruct instances, one DataStruct instance can be divided to two or more physical packets. Current information structure can be used only if there are no communication errors or invalid packets.

Alex Farber
A: 

Corruption is easy if you haven't any intrinsic limitation.

Some protection mechanisms would be:

  • Try to realloc() the buffer, within some acceptable size (if Data is dynamic)
  • Exceptions are friends: use SIGSEGV in signal(2), signal(7) and setjmp(2) to do some useful try/catch code structure. See Combining setjmp()/longjmp() and Signal Handling for a quick introduction on this topic. Use sigaction(2) to go deeper (by getting the faulty address;).
levif