minetest icon indicating copy to clipboard operation
minetest copied to clipboard

Add network encryption into minetest

Open Emojigit opened this issue 5 years ago • 30 comments

Problem and Solutions

Currently, Minetest packets are unencrypted, which leads to several privacy problems. We should encrypt them, to avoid man-in-the-middle attack and eavesdrops.

Alternatives

Make a CSM, which works with the Server, to encrypt serious data like commands or chatroom messages.

Emojigit avatar Jul 18 '20 23:07 Emojigit

Passwords are encoded using SRP before they're sent over the network, requiring quite some efforts by the attacker. See also: #1943 -> PR #2620.

DTLS would be a possibility instead of pain UDP. However, the transferred packets are usually very small (< 1 KiB), with unreliable parts mixed into it (player movements). I don't see any need to encrypt the network - this is a game, not a nuclear reactor remote software (which shouldn't exist in the first place ;) ).

SmallJoker avatar Jul 19 '20 07:07 SmallJoker

Possible close, really? Chat and form traffic should be encrypted. Maybe meta as well. Anything that involves big blobs of text.

As it is, a MITM attack can be used to impersonate someone with privileges and send commands in their stead, including very dangerous ones like #10163, making this a vector for a server to get compromised. (We have enough botnets on the internet as it is.)

In addition, lots of kids play this game without knowing that their communications can be trivially overheard. By not encrypting the traffic, you are making it very easy for some creep to datamine them. (Researching the victim is usually the first step for kidnappers, traffickers, etc. If you think they wouldn't bother bugging someone's home connection, think again.)

Or maybe somebody lives in a country with a less than stellar human rights situation, and slips up in conversation. One word might be enough to land you in trouble, or put you on some list. Do you think an authoritarian government cares if it happened in a block game?

Finally, if a zero day is found in some more complicated portion of the client environment such as forms, malware can be spread without having to compromise the server itself. Any node along the way can do it. Yikes.

And if any of those things happen, the server owner might have to deal with some unpleasant fallout too, depending on the circumstances.

The question about encrypting communication and securing a public server in 2020 should never be "if" but "how". Don't wait until any of the above things happen, do it now.

hecktest avatar Jul 19 '20 14:07 hecktest

~~I consider this low priority at this time.~~ Passwords are protected using SRP, chat is not privileged, and connection hijacking is not trivial (you need to be on a node between the server and the client). Minetest is also not that big of a target.

This will probably be needed when server-sent client-side scripting is added, to ensure that any code is sent from the server and not a MiTM.

Now-a-days, encryption has good hardware support so performance shouldn't be a problem. We can also use the handshake to let the client and server agree on whether encryption should be used, allowing network compatibility to be kept. This would introduce a downgrade attack, but we could use the serverlist to make the client require encryption when connecting. Server-sent client-side mods could also require encryption.

Authentication of the server could be an issue, the best way to do that would be ~~two methods~~:

  • the server list could contain the public key of the server
  • ~~the public key of a server could be verified by its domain name, using standard internet CAs~~

I guess it depends on how secure you want it to be

rubenwardy avatar Jul 19 '20 14:07 rubenwardy

Minetest is not big but in my opinion we shouldn't wait with security until someone dies. It's not like encryption is hard either. Using the master server as a key authority should be good enough as a default. Third party CAs would require some extra steps to set up, like having a domain in the first place. That part need not be in the initial implementation. Plaintext connections would still be supported, but with a little string on the loading screen warning you about it, and maybe a padlock icon in the list for secure servers.

And oh yeah, I forgot SSCSM. That requires encryption, not for secrecy but for integrity. You might want to add this issue to the SSCSM project.

hecktest avatar Jul 19 '20 14:07 hecktest

The idea behind domain certs and CAs would be to allow authentication for servers not on the server list, but that's a much lower priority and that solution doesn't work for all servers as you said

rubenwardy avatar Jul 19 '20 15:07 rubenwardy

CAs would help but they're a bit more work, hence the lower priority for them. In the meantime, being able to manually inspect the cert would be useful for the unlisted server case.

hecktest avatar Jul 19 '20 17:07 hecktest

Isn't SRP able to create a symmetric session key for encryption?

Problems: First SRP is still insecure

Lejo1 avatar Jul 20 '20 09:07 Lejo1

Passwords are encoded using SRP before they're sent over the network, requiring quite some efforts by the attacker. See also: #1943 -> PR #2620.

DTLS would be a possibility instead of pain UDP. However, the transferred packets are usually very small (< 1 KiB), with unreliable parts mixed into it (player movements). I don't see any need to encrypt the network - this is a game, not a nuclear reactor remote software (which shouldn't exist in the first place ;) ).

I think player move should encrypt because a hacker can move you into lava if player move are not encrypted

Emojigit avatar Jul 30 '20 10:07 Emojigit

I asked on stack overflow: https://stackoverflow.com/questions/63171893/are-there-any-network-encryption-for-udp-that-support-big-packet

Emojigit avatar Jul 30 '20 11:07 Emojigit

I think player move should encrypt because a hacker can move you into lava if player move are not encrypted

That would require the hacker to do a middle man attack which is nothing you just do for killing a player in a game...

Sure there are Udp encryption algorithms. The Problem is just that encryption/decryption takes time, so a fast one should be used.

Lejo1 avatar Jul 30 '20 11:07 Lejo1

The reason movement shouldn't be encrypted is because it's a low latency, high frequency kind of information which must be sent as quickly as possible, and there's nothing sensitive about it. Same goes for plain button inputs.

I do wonder about the possibility of griefing a server with spoofed input packets, re-enacting the Dancing Plague of 1518. But can an attacker convincingly spoof input and movement packets without any information about the peers? Or maybe there's a way to trick the server into revealing the peer information?

hecktest avatar Jul 30 '20 13:07 hecktest

The reason movement shouldn't be encrypted is because it's a low latency, high frequency kind of information which must be sent as quickly as possible, and there's nothing sensitive about it. Same goes for plain button inputs.

I disagree, you should either encrypt everything or nothing(except auth) It's overcomplicated to not do it. You shouldn't notice the time needed for encryption when using a nice algorithm.

I do wonder about the possibility of griefing a server with spoofed input packets, re-enacting the Dancing Plague of 1518. But can an attacker convincingly spoof input and movement packets without any information about the peers? Or maybe there's a way to trick the server into revealing the peer information?

Sure! You just need to be somewhere between the server and client. Than you could pretty much spoof anything. You just don't get so easy between them ;)

I personally don't care if the connection is encrypted or not. Nobody would do such a hack to a minetest gaming server...

Lejo1 avatar Jul 31 '20 17:07 Lejo1

Well I disagree with this disagreement, anything you do on the server, you have to multiply by the amount of players connected. The cost adds up quickly. If there is a trivial way to pass movement data as plaintext, do it.

hecktest avatar Sep 05 '20 16:09 hecktest

Hmm, that's true. Maybe the best is not to add more encryption and keep everything as it is. Auth is encrypted that's the main thing.

Another idea is to encrypt only one channel(and put everything trusty in it)

Lejo1 avatar Sep 05 '20 16:09 Lejo1

The encryption could just be done at a low level, everything in the UDP packets past the protocol id and source peer id could be encrypted (except auth because it already uses SRP and would be used for key agreement).

anon55555 avatar Sep 27 '20 19:09 anon55555

Badly implemented crypto might just provide a false sense of security, minetest being relatively small means not many eyes checking if the implementation is correct (for instance the SRP implementation had a bug in it that resulted in the salt not being random in some circumstances for ~4 years before anyone noticed). If you are concerned the risks of game chat, etc being intercepted you are likely better of informing people of relatively secure means of communication online (PGP, Signal Protocol, OTR, etc) and how to use them correctly. Public key cryptography might be useful for other purposes (maybe uniquely identifying servers for SPCSM even if the domain or port changes?) but I think it would be ill-advised to promote it as a protection against eavesdropping.

red-001 avatar Oct 28 '20 23:10 red-001

I suggest limiting the scope of this issue to what @hecktest proposed:

Chat and form traffic should be encrypted. Maybe meta as well. Anything that involves big blobs of text. As it is, a MITM attack can be used to impersonate someone with privileges and send commands in their stead, including very dangerous ones like https://github.com/minetest/minetest/issues/10163, making this a vector for a server to get compromised. (We have enough botnets on the internet as it is.)

Chat is particularly important here.

appgurueu avatar Jul 05 '22 16:07 appgurueu

I suggest limiting the scope of this issue to what @hecktest proposed:

Chat and form traffic should be encrypted. Maybe meta as well. Anything that involves big blobs of text. As it is, a MITM attack can be used to impersonate someone with privileges and send commands in their stead, including very dangerous ones like #10163, making this a vector for a server to get compromised. (We have enough botnets on the internet as it is.)

Chat is particularly important here.

Why not just authenticate and encrypt all packets with ChaCha20 (or perhaps Salsa20) and Poly1305? This way the only things a malicious network can do is drop/delay packets and see packet sizes and timing. I really doubt that this would create a noticeable overhead if vectorized assembly implementations are used.

I'd recommend against AES because without hardware acceleration (e.g. on mobile devices) it's slow and often vulnerable to cache-timing attacks and preventing them makes it slower.

anon55555 avatar Jul 05 '22 22:07 anon55555

I am in favor of full network encryption using DTLS or similar, but I want to add that encrypting chat end-to-end can be done with CSMs. As far as I know, the client Waspsalive contains an implementation of that.

erlehmann avatar Jul 17 '22 22:07 erlehmann

For network cryptography, you could do this as followed:

  1. When initiating handshake it is best to use TLS or having a third party server to serves as a validator (either certificate authority or Serverlist server could do this) of this handshake session to avoid Trust on First Contact issue.
  2. I generally suggest using Diffie-Hellman Elliptic Curve Cryptography on Curve25519 for public key exchange between the game server and the client. If we're on UDP instead of TCP, I would advise against ChaCha20 since it's a streaming protocol whereas UDP is stateless and can be arranged out of order which would pose a problem for streaming cipher. Instead, I would normally suggest either using AES, Threefish, or other symmetric block cipher algorithm (Just don't use 3DES please.)
  3. You should only encrypt information that are sensitive like chat and authentication information, it doesn't make much sense to encrypt something like player movement however. You can instead use HMAC which is Hashed Message Authentication Code to ensure that packet is not tampered with and that it have a very low cost on computation requirement for such validation. HMAC can be summarized to simply hashing the content of the packet, encrypting the said hash and then append at the end of the packet.

Hope this helps.

CLanguagePurist avatar Aug 24 '22 10:08 CLanguagePurist

I really doubt it makes any sense discussing about specific ciphers at this point...


What we need is:

(1) A way to authenticate servers.

The difficulties here are:

  • Creating a LAN server should not be much more complicated than before.
  • It should still be possible to host a (global) minetest server without a domain and/or webserver, because that would be a barrier that prevents some servers from actually using the secure networking.
  • More?

To do this, we can generate X.509 certificates for the server. We could add multiple possible ways (all possible, but optional) to trust it, e.g.:

  • Via trust on first use (TOFU): The certificate's fingerprint can be stored in the server favourites. (Only works for ensuring it's still the same server, and can become outdated. We might want to identify servers by a UUID.)
  • Semi-automatically via an out-of-band channel: A fingerprint of the certificate, that the user copies from somewhere (i.e. a forum post).
  • Via the web PKI: Host a webserver on the same domain.
  • Manually via an out-of-band channel: By displaying a fingerprint on first server join. On a LAN server, the user can then maybe just ask the hoster if the checksum is correct.
  • Via some semi-central (that is, central, but the center can be configured, like the public server list) system.

(One could just use the shared key from SRP as pre-shared-key, but that would imo not be sufficient, as players can choose very weak passwords. It would however be good to use the SPR key to verify the certificate fingerprint again.)


(2) A network protocol for secure channels.

The simplest here would be to just swap UDP with DTLS.

We could also optionally compile minetest with a QUIC implementation, with the datagram extension for unreliable packets. In addition to security, this would also give us other networking benefits, like different priorities for different packets.

(FYI, gnutls looks to me like a good choice for DTLS (supports DTLS 1.2, is widely used, is easy to use, and we already depend on it through libcurl-gnutls), ngtcp2 could be used for QUIC (MIT licensed, can use gnutls connection as TLS backend).)


(3) An addition to the minetest protocol to negotiate what protocol should be used, and to download the certificate.

This should happen before the normal minetest handshake happens.

Client and server both have a priority list for supported protocols (set via settings), i.e. "encrypted_QUIC,partly_encrypted_DTLS,encrypted_DTLS,unencrypted_UDP". The client can then before join download the supported protocols from the server, and chooses its favourite one. (This should ideally be optional for the server, to hide that there's a minetest server running.) It also has to download and check the certificate. We could additionally store the certificate and the supported protocols in the public server list.

Running a minetest server on a http3 port would also be a nice feature.

Desour avatar Aug 24 '22 13:08 Desour

If we're on UDP instead of TCP, I would advise against ChaCha20 since it's a streaming protocol whereas UDP is stateless and can be arranged out of order which would pose a problem for streaming cipher. Instead, I would normally suggest either using AES, Threefish, or other symmetric block cipher algorithm (Just don't use 3DES please.)

ChaCha20 is not a streaming protocol, it's a stream cipher which is no worse than a block cipher for encrypting packets. You can get multiple streams out of one key using different nonces (you need nonces either way unless you're using something like ECB mode).

You should only encrypt information that are sensitive like chat and authentication information, it doesn't make much sense to encrypt something like player movement however.

It's simpler to just authenticate and encrypt everything rather than trying to decide what is and isn't sensitive. I doubt it would make a noticeable different to performance.

You can instead use HMAC which is Hashed Message Authentication Code to ensure that packet is not tampered with and that it have a very low cost on computation requirement for such validation.

I'd prefer a MAC like Poly1305, which is faster and if packets are limited to 512 bytes it can be mathematically proven (assuming random keys are used) that an attacker making n forgery attempts has a success probability of at most n/2^98. This means, for example, to get even a one in a billion chance of successful forgery an attacker must send more than more than 4 zettabytes of authentication tags.

HMAC can be summarized to simply hashing the content of the packet, encrypting the said hash and then append at the end of the packet.

That's not what HMAC does.

anon55555 avatar Sep 06 '22 21:09 anon55555

I was referencing the HMAC code from memory when working with BouncyCastle which literally does this at the time. Also I have lost interest in using nor do I care to contribute to Minetest, so congratulation everyone.

CLanguagePurist avatar Sep 10 '22 06:09 CLanguagePurist

I think we have to encrypt at least two things:

  1. Chat messages, contains /setpassword and/or messages the government dislike.
  2. SSCSM, which require encryption to ensure safety.

Emojigit avatar Sep 12 '22 01:09 Emojigit

There can also be confidential text in formspecs, formspec fields (filled out by client), mapblocks and whatnot. It makes not much sense thinking about what we don't need to encrypt before benchmarking if there's any real performance penalty by just encrypting everything.

And SSCSM doesn't need encryption if we don't trust the server more than we already do.

Desour avatar Sep 12 '22 11:09 Desour

For what it's worth - using TLS also comes with the benefit of allowing virtual hosts using SNI. Allowing multiple services to listen on the same port at the same IP can be very useful for hosting solutions.

dr-bonez avatar Sep 21 '22 20:09 dr-bonez

I suggest limiting the scope of this issue to what @hecktest proposed:

Chat and form traffic should be encrypted. Maybe meta as well. Anything that involves big blobs of text. As it is, a MITM attack can be used to impersonate someone with privileges and send commands in their stead, including very dangerous ones like #10163, making this a vector for a server to get compromised. (We have enough botnets on the internet as it is.)

Chat is particularly important here.

Why not just authenticate and encrypt all packets with ChaCha20 (or perhaps Salsa20) and Poly1305? This way the only things a malicious network can do is drop/delay packets and see packet sizes and timing. I really doubt that this would create a noticeable overhead if vectorized assembly implementations are used.

I'd recommend against AES because without hardware acceleration (e.g. on mobile devices) it's slow and often vulnerable to cache-timing attacks (preventing them makes it slower).

anon55555 avatar Oct 11 '22 09:10 anon55555

QUIC may be a good choice for Minetest:

  • QUIC has useful features in addition to security: customizable congestion control, reliable and unreliable data transmission, prioritising of streams and perhaps even control of the latencies. These features are needed in Minetest, e.g. mapblock packets should be prioritised lower than packets which hurt or teleport a player. This is also an advantage over TLS.
  • Efficient implementations of QUIC probably are or will be available. HTTP/3, which uses QUIC, has been standardized in 6 June 2022 and is used in the web, which could be a reason for a high demand for efficient QUIC.
  • Minetest developers do not need to implement and maintain their own low-level protocol.
  • Implementing a custom secure protocol would be bad for security in general because there is no proof that the custom protocol is really secure and most Minetest developers are not security experts I think.

It should be possible to get a shared key from SRP (the player's already secure login) and pass it to QUIC to establish the secure channel.

I'd recommend against AES because without hardware acceleration (e.g. on mobile devices) it's slow and often vulnerable to cache-timing attacks (preventing them makes it slower).

~I think Mobile devices which don't support browsing with a modern web browser are often too slow to play Minetest at all. I assume that modern web browsers always use AES for HTTPS (HTTP with TLS), so these devices should support AES well.~ Edit: Mobile devices often don't support AES implemented in hardware (see comment below).

HybridDog avatar Oct 11 '22 18:10 HybridDog

Implementing a custom secure protocol would be bad for security in general because there is no proof that the custom protocol is really secure and most Minetest developers are not security experts I think.

If we used ChaCha20 with Poly1305 to encrypt and authenticate raw UDP packets it wouldn't be too hard to prove security using indifferentiability:

In the ideal world, the client C and the server S are both is sending packets with distinct 64-bit nonces (these could replace Minetest RUDP's sequence numbers). After a packet is sent, the adversary A sees its size and nonce, and gains the capability to pass it on (possible repeatedly) to its intended recipient. The RUDP layer would stil need to be made robust against malicious packet dropping, delaying and replaying for security in this ideal world.

In the real world, the client C and the server S are both exchanging packets with the adversary B as specified by the protocol.

To prove security, construct a simulator Σ which simulates the capabilities of a real-world adversary using the capabilities of an ideal world adversary. This means the capabilities (Σ(A), C, S) and (B, C, S) are indistinguishable, which could be proven under the assumption that ChaCha20 is secure.

I assume that modern web browsers always use AES for HTTPS (HTTP with TLS), so these devices should support AES well.

Your assumption is incorrect, see https://blog.cloudflare.com/do-the-chacha-better-mobile-performance-with-cryptography/.

anon55555 avatar Dec 04 '22 15:12 anon55555

This issue seems like stale for a while.

What about using WebRTC ?

  • It uses TLS for handshake, and DTLS for UDP
  • Can carry data packages (eg. game data)
  • All of the cryptography decisions are offloaded to a standards workgroup
  • Brings in easy to support browser networking as well
  • Already established and battle tested libraries exist almost for all platforms

furkanmustafa avatar Apr 12 '24 17:04 furkanmustafa