Handling intentionlly malformed packets
I''ve read alot comments about prefixing gamepackets with the length when used in conjunction with TCP''s send and recieve calls.
What I''m curious about is how you would protect your server from maliciously malformed packets and ways to detect them. Since TCP is a stream based protocol, its common to prefix your packets with their length, or read in a predetermined amount of data so that you can determine the type and size of the packet.
Suppose that somebody crafts a packet that is 100 bytes in size but modifies the prefixed length to be 50,000 or something. Given a simple example of handling this, the reciever would read the prefixed length and then continue to read in 50,000 more bytes of data. If the sender is going to be sending more data, say if this case were to happen during gameplay, the packets that the client sent would have been garbled in with the previous calls to recieve due to the tampered packet.
What are the better ways to handle problems like this?
-=[ Megahertz ]=-
-=[Megahertz]=-
Well, if there aren''t 50,000 more bytes on that particular socket, nothing''s gonna happen You''ll just read data for that particular player and buffer it, meaning that player gets no benefit out of the game whereas other players are continuing as normal.
If you''d rather not have 50K buffers, then just work out the maximum packet length - this is probably deducible at compile time. If they try to give you a packet bigger than that, reject it.
But really, this isn''t a significant problem. They''re just sabotaging their own connection. Just as long as you have a check to ensure that you''re not gonna let them upload 1MB of arbitrary data to try and crash your game, there''s nothing you need to worry about really.
[ MSVC Fixes | STL Docs | SDL | Game AI | Sockets | C++ Faq Lite | Boost
Asking Questions | Organising code files | My stuff | Tiny XML | STLPort]
If you''d rather not have 50K buffers, then just work out the maximum packet length - this is probably deducible at compile time. If they try to give you a packet bigger than that, reject it.
But really, this isn''t a significant problem. They''re just sabotaging their own connection. Just as long as you have a check to ensure that you''re not gonna let them upload 1MB of arbitrary data to try and crash your game, there''s nothing you need to worry about really.
[ MSVC Fixes | STL Docs | SDL | Game AI | Sockets | C++ Faq Lite | Boost
Asking Questions | Organising code files | My stuff | Tiny XML | STLPort]
With TCP, you have the option of terminating a connection if you detect the packet contains ludicrous data.
> I''ve read alot comments about
> prefixing gamepackets with the
> length
You can send a packet ID, so that the receiving end can distinguish between fixed-length and variable-length packets. To avoid an overflow, I suggest you break packets into 1K-4K length max; the first packet contains info about and how many other packets will follow. You can also have a 4-bytes magic number at the head of every packet so that you can check if you are out-of-sync or not.
You want to guard your code against starvation; if a malicious user says the packet is 4K and sends 100 bytes then stops, you want to have the opportunity to provide a sufficient delay before terminating the connection. That means ... ouch ... working in non-blocking mode !
-cb
> I''ve read alot comments about
> prefixing gamepackets with the
> length
You can send a packet ID, so that the receiving end can distinguish between fixed-length and variable-length packets. To avoid an overflow, I suggest you break packets into 1K-4K length max; the first packet contains info about and how many other packets will follow. You can also have a 4-bytes magic number at the head of every packet so that you can check if you are out-of-sync or not.
You want to guard your code against starvation; if a malicious user says the packet is 4K and sends 100 bytes then stops, you want to have the opportunity to provide a sufficient delay before terminating the connection. That means ... ouch ... working in non-blocking mode !
-cb
The simpliest way is to avoid using a size parameter. This can be acomplished by either using only fixed-sized messages. Instead of variable sized messages, make sure that you do sanity checks on the data. Check data lenghts, for example does a 20000 byte string make sense? If not drop it.
However, I think that with a TCP connection it is impossible to reject data that is sent, so you will have to be able to detect and drop unwanted connections.
Actually, since I am working on a similar program, are there any ideas on a good way to do this? Other than timeouts and then dropping connections, I can''t think of a good way to handle malicious data like this.
However, I think that with a TCP connection it is impossible to reject data that is sent, so you will have to be able to detect and drop unwanted connections.
Actually, since I am working on a similar program, are there any ideas on a good way to do this? Other than timeouts and then dropping connections, I can''t think of a good way to handle malicious data like this.
Perhaps im just confused by what your wrote, or maybe I didnt explain the issue properly.
Sure, I could calcuate the max packet size and reject any packets not within that range, but that doesn't address the issue completely.
Suppose this is what my stream of data off the socket looks like:
32 32 00 06 45 43 23 23 54 53 32 34 00 05 42 54 34 25 24
The first 2 numbers are the packet type id. The second two are the length of the packets payload. The rest following that is the actual data for the payload.
In the above example there are 2 packets in that stream and everything is hunky dory.
Now I'll mess with the packets.
32 32 00 08 45 43 23 23 54 53 32 32 00 05 42 54 34 25 24
The first packet has a packet type of 3232 (just some arbitrary number) with a payload length of 8 bytes. This is incorrect. If I read in 8 bytes to fill out this packet I'll steal 2 bytes from the next packet. When then if try to process that packet, I end up with a packet type id of 0005, which is incorrect, and it just snowballs from there.
Am i just way off base on my implementation of this? I know this works, just as long as nobody screws with the stream.
-=[ Megahertz ]=-
[edited by - Megahertz on March 29, 2003 11:30:03 AM]
Sure, I could calcuate the max packet size and reject any packets not within that range, but that doesn't address the issue completely.
Suppose this is what my stream of data off the socket looks like:
32 32 00 06 45 43 23 23 54 53 32 34 00 05 42 54 34 25 24
The first 2 numbers are the packet type id. The second two are the length of the packets payload. The rest following that is the actual data for the payload.
In the above example there are 2 packets in that stream and everything is hunky dory.
Now I'll mess with the packets.
32 32 00 08 45 43 23 23 54 53 32 32 00 05 42 54 34 25 24
The first packet has a packet type of 3232 (just some arbitrary number) with a payload length of 8 bytes. This is incorrect. If I read in 8 bytes to fill out this packet I'll steal 2 bytes from the next packet. When then if try to process that packet, I end up with a packet type id of 0005, which is incorrect, and it just snowballs from there.
Am i just way off base on my implementation of this? I know this works, just as long as nobody screws with the stream.
-=[ Megahertz ]=-
[edited by - Megahertz on March 29, 2003 11:30:03 AM]
-=[Megahertz]=-
> I end up with a packet type id
> of 0005, which is incorrect, and
> it just snowballs from there
What prevents you from terminating the connection at this point since you''ve just detected that 0005 is an incorrect packet type? Either there is a bug in the communication code or there is a malicious user at the other end; either way you''re screwed and further stream processing is likely to lead to a crash.
-cb
> of 0005, which is incorrect, and
> it just snowballs from there
What prevents you from terminating the connection at this point since you''ve just detected that 0005 is an incorrect packet type? Either there is a bug in the communication code or there is a malicious user at the other end; either way you''re screwed and further stream processing is likely to lead to a crash.
-cb
Disconnection doesn''t seem like a viable option to me. What if you were in the middle of a game and your opponent was losing, so he fires up his hack which inserts a packet with erroneous length like that? If you disconnected, if would appear to the rest of the players like you hung up and the cheater would remain in the game. I guess you could report the error to other players and everyone could hang up on the cheater, but then it would be pretty easy to make another hack to disconnect someone that way, too.
> Disconnection doesn''t seem like
> a viable option to me.
Your connection is compromised and your input stream out-of-sync. Regardless how smart your mousetrap is, there will always be a smarter mouse to walk around the trap, especially so if the mouse controls the other end of your input stream. What else can you do, except cut your losses and disconnect?
> If you disconnected, if would
> appear to the rest of the players
> like you hung up and the cheater
> would remain in the game.
In a P2P model, yes. Which is why the client/server model has been an allround favorite in minimizing cheaters; servers are harder to compromise. Besides, would you enjoy a game where a player is know to cheat?
-cb
> a viable option to me.
Your connection is compromised and your input stream out-of-sync. Regardless how smart your mousetrap is, there will always be a smarter mouse to walk around the trap, especially so if the mouse controls the other end of your input stream. What else can you do, except cut your losses and disconnect?
> If you disconnected, if would
> appear to the rest of the players
> like you hung up and the cheater
> would remain in the game.
In a P2P model, yes. Which is why the client/server model has been an allround favorite in minimizing cheaters; servers are harder to compromise. Besides, would you enjoy a game where a player is know to cheat?
-cb
Disconnecting the player is a viable option and what''s probably going to happen. If a player is sending bad packets, then he prolly doesn''t deserve to be in the game.
One problem with going off the packet type id is the case where the stream is improperly parsed due to a tampered packet and the next packet type id is actually a valid one. That packet will get parsed and shoved into the appropriate data structure. However since the alignment is now off, the packet is going to contain garbage and that as well will need to be detected.
I suppose a simple comparison of the payload size with the structure size will catch most of those cases and give me a hint that something is amiss with the stream. At that point the user can be disconnected as well.
Im sure they''ll be some odd corner cases where stuff will slip by and cause problems for the server. I''ll just have to address those as they are discovered.
-=[ Megahertz ]=-
One problem with going off the packet type id is the case where the stream is improperly parsed due to a tampered packet and the next packet type id is actually a valid one. That packet will get parsed and shoved into the appropriate data structure. However since the alignment is now off, the packet is going to contain garbage and that as well will need to be detected.
I suppose a simple comparison of the payload size with the structure size will catch most of those cases and give me a hint that something is amiss with the stream. At that point the user can be disconnected as well.
Im sure they''ll be some odd corner cases where stuff will slip by and cause problems for the server. I''ll just have to address those as they are discovered.
-=[ Megahertz ]=-
-=[Megahertz]=-
Sorry if what I said was unclear. Basically I was saying that you should have your messages as strict as possible, so you can avoid the case you mention. One way to help is to not read large "chunks" of arbitrary size. Idealy your messages would be of fixed length. However, I was also trying to point out that I don''t think there is an easy solution to a intentionally misbehaving client.
About "misbehaving" clients:
Would you want to automatically disconnect the client?
Maybe the bad packet is caused by a bug, either in the client or server. In such a case would you want to automatically disconnect them? There could be some other problem resulting in lost or bad data being transmitted.
Perhaps you could have a "resync" message sent from the server when it receives a bad packet, inorder to tell the client that it is misbehaving. If the client continues to misbehave, then drop them. The "resync" message could cause the client to send a string of 0''s (say 16 or 100, or whatever), so it can pad against bad messages like in your example.
What about using some statisitcs to decide? Maybe if in say the last 10 messages a certain number (say 1-3) are bad, tell the client to resync their connection. If the number rises to 5+, disconnect. This could help avoid "hiccups" in the network. To help detect a consistently bad client, count bad packets over a longer period. Say 100 messages, and drop any client that has more than 5-10% bad messages in the long term.
Of course these methods don''t prevent bad clients, but they might help detect bad clients from network errors.
However the most important ability is to have a server stable and secure enough to withstand these attacks. If a misbehaving client is able to alter the game state in an improper way, you have a problem.
About "misbehaving" clients:
Would you want to automatically disconnect the client?
Maybe the bad packet is caused by a bug, either in the client or server. In such a case would you want to automatically disconnect them? There could be some other problem resulting in lost or bad data being transmitted.
Perhaps you could have a "resync" message sent from the server when it receives a bad packet, inorder to tell the client that it is misbehaving. If the client continues to misbehave, then drop them. The "resync" message could cause the client to send a string of 0''s (say 16 or 100, or whatever), so it can pad against bad messages like in your example.
What about using some statisitcs to decide? Maybe if in say the last 10 messages a certain number (say 1-3) are bad, tell the client to resync their connection. If the number rises to 5+, disconnect. This could help avoid "hiccups" in the network. To help detect a consistently bad client, count bad packets over a longer period. Say 100 messages, and drop any client that has more than 5-10% bad messages in the long term.
Of course these methods don''t prevent bad clients, but they might help detect bad clients from network errors.
However the most important ability is to have a server stable and secure enough to withstand these attacks. If a misbehaving client is able to alter the game state in an improper way, you have a problem.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement
Recommended Tutorials
Advertisement