Facepunch / garrysmod-issues

Garry's Mod issue tracker
147 stars 56 forks source link

Serverside net messages can be overflowed. #1797

Closed FPtje closed 9 years ago

FPtje commented 9 years ago

When there's any net message listener on the server, any client can spam messages to it and essentially DoS the server. Reproduction is really simple:

serverside:

util.AddNetworkString("somecrap")
net.Receive("somecrap", function() end) -- empty function is enough

clientside:

hook.Add("Think", "a", function() for i = 1, 100000 do net.Start("somecrap") net.SendToServer() end end)

If the number of messages is high enough you'll get this in your client console:

<something>:send reliable stream overflow

The number needs to be really high on a listen server (10k worked on my dedi server, but not on my listen server. 100k did the trick on a listen server).

What I can do

There is very little I can do to solve this problem. I could kick people that send messages with length 0, but that's really easy to bypass. Besides, some net messages are supposed to be empty. The only other thing I can do is keep track of how many net messages people send per second. I would have to be careful not to kick people who genuinely send a load of messages, e.g. in a badly coded script that sends a load of data in a ton of net messages at once. I don't want to be the guy that causes these addons to kick people.

Why I expect a solution in GMod itself

This issue was originally reported here: https://github.com/FPtje/DarkRP/issues/1799

Tested in both stable and dev branch. Equally reproducable.

FPtje commented 9 years ago

It is worth mentioning that with 100k messages the player fully freezes, but there's a limbo state that I could only reproduce on a dedicated server (and not on a listen server). It's the exact same code as above, but instead with 10k messages per frame instead of 100k. I did not get the reliable stream overflow error, and I could still move (unlike 100k), but I could not spawn props and lua_run_cl stopped working.

Grocel commented 9 years ago

I guess the game (server or client) should just close the connection to the causing player throwing the "reliable stream overflow" error.

JayIsSoCool commented 9 years ago

This does crash it, It doesn't just flood your client.

willox commented 9 years ago

Can't confirm. All I get is a filled up client -> server buffer.

FPtje commented 9 years ago
net.Receive("DarkRP_spawnPocket", function(len, ply)
    local item = net.ReadFloat()
    if not ply.darkRPPocket or not ply.darkRPPocket[item] then return end
    ply:dropPocketItem(item)
end)

Like what? Spamming the message will end up in the return before the eleventh message by default. The report was about sending empty messages. Unless my way of reading a float and checking a table value can lag a server, there's nothing wrong with it.

FPtje commented 9 years ago

Ah, turns out the guy reporting it is most likely running an old version of DarkRP that threw an error with bad messages. That combined with the fact that overflowing only bothers the client is enough reason to close the issue.

Ethorbit commented 4 years ago

Bumping because this is still a very valid gmod exploit 5 (almost 6) years later... Based on what I've seen, this can boot everyone off a server with 'reliable channel overflowed' and freeze/lag games.

Step 1. Inject lua or a C++ dll cheat Step 2. Spam a network message as fast as possible (maybe send it 20x each tick) Result 1: Server will continuously lag, client's games may freeze temporarily and lag Result 2: Everybody will get disconnected

Why are people allowed to spam a single net message? Why is there nothing built-in to prevent this? Garry's Mod should stop sending a net message when it is spammed unreasonably fast, maybe with a server command for those who want this to still be possible.

thegrb93 commented 4 years ago

You can override net.Incoming to detect lua net message spam. The main issue is addon makers don't sanity check net messages enough.

Ethorbit commented 4 years ago

It's what I'm doing right now, but it would be nice to have built-in protection against this