Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Connect Token Sniffing #84

Closed
RandyGaul opened this issue Apr 3, 2019 · 11 comments
Closed

Connect Token Sniffing #84

RandyGaul opened this issue Apr 3, 2019 · 11 comments

Comments

@RandyGaul
Copy link

Say a valid, but malicious, client records their own list of valid dedicated server IP addresses. They then want to DoS another player, or steal another player's session. They sniff the other player's packets and get access to the opaque connect token. They then make an attempt to connect to a dedicated server by using their own personal IP address collection, and send the token to each server to try and connect before the sniffed client.

This causes two problems:

  1. The sniffed player can have their identity stolen, as another player has connected with their token before they do.
  2. The sniffed player might have to retrieve a new token and try to connect to other servers. In the case where no other servers are available, they are in a DoS scenario.

What is the idea for netcode regarding this strategy?

@ghost
Copy link

ghost commented Apr 3, 2019

Say a valid, but malicious, client records their own list of valid dedicated server IP addresses. They then want to DoS another player, or steal another player's session. They sniff the other player's packets and get access to the opaque connect token. They then make an attempt to connect to a dedicated server by using their own personal IP address collection, and send the token to each server to try and connect before the sniffed client.

This causes two problems:

  1. The sniffed player can have their identity stolen, as another player has connected with their token before they do.
  2. The sniffed player might have to retrieve a new token and try to connect to other servers. In the case where no other servers are available, they are in a DoS scenario.

What is the idea for netcode regarding this strategy?

You test it ?

@RandyGaul
Copy link
Author

It would require a whole lot of work to hack a client to do packet sniffing. But it's trivial to write a test to simulate sniffing: https://gist.github.com/RandyGaul/9387c766ff9279f8fe6a8372795d7f53. The test should be identical to sniffing, since the private section of the connect token is just memcpy'd around in any case.

I'm unable to see how netcode distinguishes between a user attempting to connect with a token twice, between the DoS/identity stealing scenario.

@ghost
Copy link

ghost commented Apr 3, 2019

It would require a whole lot of work to hack a client to do packet sniffing. But it's trivial to write a test to simulate sniffing: https://gist.github.com/RandyGaul/9387c766ff9279f8fe6a8372795d7f53. The test should be identical to sniffing, since the private section of the connect token is just memcpy'd around in any case.

I'm unable to see how netcode distinguishes between a user attempting to connect with a token twice, between the DoS/identity stealing scenario.

Do you have a solution to this problem?

Do I understand correctly that if one user hacks the client of a game of another user, he can connect use other token, but this is not terrible, given that he does not know the second user’s login and password for auth in game.
By the way, what do you think about this library in general? Should it be used in the MMORPG?

@RandyGaul
Copy link
Author

I actually don’t know if this is really a problem. That’s why I’m posting, to find out if it’s really a problem at all.

I’ve never made an MMORPG before, so I’m not really sure if it’s suitable or not.

I’m sure it’s possible to do username and password auth after the connection is established... But I thought the whole idea was to offload this part to the webserver over HTTPS.

@ghost
Copy link

ghost commented Apr 3, 2019

From my understanding, the initial communication of a connect token is outside the spec of netcode.io- that being said it's recommended to transfer the connect token over HTTPS with properly implemented TLS.

I believe the challenge token sequence is responsible for ensuring that spoofed IPs can't pass the connection sequence. From my understanding, the challenge token utilizes both a sequence number and data present only in the entire connect token. An attacker who is sniffing the UDP packet stream would not be able to create packets that could pass the challenge sequence.

If an attacker has your full connect token, chances are either that your initial webserver is not properly configured for TLS, or the attacker has access to the client itself, which in that case you have much bigger problems that netcode would not be able to approach.

@RandyGaul
Copy link
Author

Thanks you’re right! The nonce part was that piece I missed :)

@RandyGaul
Copy link
Author

RandyGaul commented Apr 3, 2019

Actually if we look here: https://github.com/networkprotocol/netcode.io/blob/master/netcode.c#L4293-L4304

The challenge token sequence is just an incrementing number. It does not use a shared-secret between in the initial connect token from the webserver. @stellarLuminant So your response does sound like it would work - if the sequence number was a shared secret like you explained, then I can see how the challenge-response secret would not work for a packet sniffer. However the strategy netcode actually uses is the challenge-response secret is covered using the shared keyset. A sniffer would not have access to the shared keyset and would be unable to respond during the challenge response sequence.

So the best the sniffer could do is to try and DoS the server by filling up encryption mappings by initiating the challenge-response sequence. But they should be unable to connect. So this must be why netcode by default reserves 4x encryption mappings as opposed to client slots, as a way to mitigate this DoS strategy.

@ghost
Copy link

ghost commented Apr 3, 2019

Actually if we look here: https://github.com/networkprotocol/netcode.io/blob/master/netcode.c#L4293-L4304

The challenge token sequence is just an incrementing number. It does not use a shared-secret between in the initial connect token from the webserver. @stellarLuminant So your response does sound like it would work - if the sequence number was a shared secret like you explained, then I can see how the challenge-response secret would not work for a packet sniffer. However the strategy netcode actually uses is the challenge-response secret is covered using the shared keyset. A sniffer would not have access to the shared keyset and would be unable to respond during the challenge response sequence.

So the best the sniffer could do is to try and DoS the server by filling up encryption mappings by initiating the challenge-response sequence. But they should be unable to connect.

As far as I know, the client cannot spoof the sequence value to deceive the server.

The sequence number is used as the nonce for packet encryption, so any modification to the sequence number fails the encryption signature check.

But i have other ask about "#define NETCODE_PACKET_SEND_RATE 10.0"
I did an analysis of how many packets the client / server sends over a specific time. As it turned out, they send each other about 100 packets per second and about 5000 per minute. This is normal?
If you change the value of NETCODE_PACKET_SEND_RATE down, that increase the delay before sending keep-alive packets.
I’m wondering why the author set the NETCODE_PACKET_SEND_RATE = 10.0 version and whether I need to change the fact that the client and the server send a lot of packets to each other, even when it is just send keep-alive (more time)

@RandyGaul
Copy link
Author

RandyGaul commented Apr 3, 2019

That’s normal yes. Glenn has said he wrote netcode with support for FPS games especially in mind, or games like agar.io. By rapidly sending keepalives, libyojimbo is able to piggy-back the keepalives to send reliable messages in the event the game is not currently sending any other unreliable data. I haven’t looked at the yojimbo source in-depth since 2017, but I imagine it still does the same thing.

@ghost
Copy link

ghost commented Apr 3, 2019

That’s normal yes. Glenn has said he wrote netcode with support for FPS games especially in mind. By rapidly sending keepalives, libyojimbo is able to piggy-back the keepalives to send reliable messages in the event the game is not currently sending any other unreliable data. I haven’t looked at the yojimbo source in-depth since 2017, but I imagine it still does the same thing.

So, me need use yojimbo or netcode ??

@RandyGaul
Copy link
Author

You probably want to use yojimbo. It uses netcode inside, but had reliability features, and other features too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant