views:

173

answers:

5

I have been creating an application using UDP for transmitting and receiving information. The problem I am running into is security. Right now I am using the IP/socketid in determining what data belongs to whom.

However, I have been reading about how people could simply spoof their IP, then just send data as a specific IP. So this seems to be the wrong way to do it (insecure). So how else am I suppose to identify what data belongs to what users? For instance you have 10 users connected, all have specific data. The server would need to match the user data to this data we received.

The only way I can see to do this is to use some sort of client/server key system and encrypt the data. I am curious as to how other applications (or games, since that's what this application is) make sure their data is genuine. Also there is the fact that encryption takes much longer to process than unencrypted. Although I am not sure by how much it will affect performance.

Any information would be appreciated. Thanks.

A: 

You can look at HMAC

Wikipedia:

In cryptography, HMAC (Hash-based Message Authentication Code), is a specific construction for calculating a message authentication code (MAC) involving a cryptographic hash function in combination with a secret key. As with any MAC, it may be used to simultaneously verify both the data integrity and the authenticity of a message.

Each client would need to get a unique token which only they know. Every message they send, they'll make a hash based on the token and the message and send it along with the message itself. Then you can verify that the message came from a specific client.

Ikke
HMAC is for integrity of data, i didn't get the point how it prevents the IP spoofing?
berkay
+1: a challenge/response upon session start, then every message would have a signature over (data+session key) appended
Robert
@Berkay: it's nearly impossible that the spoofer "knows" the seed of the client (used to calculate the HMAC), so the server could safely drop all messaging not having a positive HMAC.
Robert
whatever the clients are spoofed their IP addresses? you will distribute each client different key? then it comes to use IPSEC.
berkay
The point of UDP is that it is light weight, a hmac using md5() has significantly greater overhead in computation and bandwidth than TCP which is immune to this spoofing problem. (hmacs are immune to hash collisions, so md5() is safe.)
Rook
Its a bit baffling why people insist on throwing a HMAC at everything.
Rook
@TheRook - how can HMACs can be immune to hash collisions if the 'H' in HMAC stands for 'hash' ??? If you have to stick to UDP because of implementation restrictions, you cannot just take TCP instead of UDP.
Robert
@Robert in order to calculate a hash collusion you must know the entire message. If you know the secret key used in an HMAC then you can forge the resulting hash and generating a collision does not help. Further more in the md5() attack the attacker must be able to control the prefix of the message. If the key is prepended then an md5() hash collision is impossible. Please read "practical cryptography" by Bruce Schnieier.
Rook
Further more an HMAC is not the correct secuirty system for this vulnerability, which is gone into greater detail in my own post.
Rook
A: 

If you absolutely need to verify that a particular user is a particular user then you need to use some form of encryption where the user signs their messages. This can be done pretty quickly because the user only needs to generate a hash of their message and then sign (encrypt) the hash.

For your game application you probably don't need to worry about this. Most ISPs wont allow their users to spoof IP addresses thus you need to only worry about users behind NAT in which you may have multiple users running from the same IP address. In this case, and the general one, you can fairly safely identify unique users based on a tuple containing ip address and UDP port.

bboe
The point of udp is being light weight. The use of encryption would significantly increase the overhead of the protocol when compared to TCP which is immune to spoofing.
Rook
I disagree. The point of UDP is being real-time as opposed to reliable. In a game environment you care less about reliability and more about low latency. The overhead of putting packets in order is mostly due to network round-trip times not the extra code in the TCP stack. Furthermore, I speculate computing a hash over a datagram and computing a signature for it does not introduce a bottleneck compared to average internet latencies.
bboe
@bboe The use of a stream cipher with udp would save a few bits of bandwidth when compared to TCP. However, in general I believe this purposed security system is misusing resources. Especially the resources of the developer to implement this purposed secuirty system. SSL/TLS is a free and the most secure solution to this problem.
Rook
+1  A: 

One solution is to use TCP because it is immune to spoofing the source address over the open internet because of the three-way-handshake (More information on why TCP source address spoofing is impossible.). If you still want to use UDP, you could have a simulated three way handshake to begin the connection. A session id could then be added to each UDP packet. This will increase the connection overhead by 2 packets and a few bits per packet, however you will still gain from UDP's speed for the rest of the session when compared to tcp.

However, using TCP or UDP as a transport layer still leaves you open to other attacks such as Sniffing and Man in The Middle attacks using arp spoofing or dns cache poising. Another problem is if both the attacker and the gamers are on the same local lan, such as a wireless network or another broadcast network then you are able to receive traffic regardless of the source/dest address and ONLY THEN does spoofing a three way handshake become possible (and an hmac can't help!). The best soltuion is to use SSL/TLS as your transport layer which solves all of these problems.

You should not reinvent the wheal, but if you need to encrypt UDP for some reason you should use a Stream Cipher like RC4-drop1024 or even better a Block Cipher like AES 256 in OFB Mode. This will save bandwidth over other modes of encryption because they round up to the largest block size.

EDIT: Based on Marts comment for (Datagram Transport Layer Security)DTLS I did some digging and I found there is an official RFC and its supported by OpenSSL and should be exposed using the pyOpenSSL library. I recommend using the RC4-SHA cipher suite to reduce overhead, this suite is supported by SSL 3.0 (newest). However DTLS will probably have more overhead (LAG!) then TCP.

Rook
For UDP, the solution would be using DTLS, not reinventing the wheel using chiphers directly. Considering the original question, original poster will not probably get it right at the first time.
Mart Oruaas
@Mart Oruaas Cool i didn't know about DTLS, if its built from TLS you should be able to negotiate the use of a stream cipher which will bandwidth.
Rook
I have looked into TCP and it seems like a good choice to prevent what I am asking. However many articles I have read discourage it from games. Technically couldn't a session ID be spoofed as well? Just send packets increasing the # until we get a reply that works? I will look into the Ciphers as they look interesting. One thing to note for others is that data from the client has to be read and used somehow. Therefore hashing the data won't work. Adding a hash to the front of the data would increase the data size to unbearable levels.
Charles
@Charles Please read the "more information" link on why this is impossible. With spoofing UDP you can send outgoing datagrams full of bogus data, but you must have a valid source address in order to receive traffic to complete a three-way-handshake.
Rook
I am confused. The link is referring to TCP, and then you discuss UDP three way handshake or are you talking about simulated three way handshake earlier? Are you saying because they are spoofing their address, they cannot actually receive any response back? If not, would appreciate a more direct response. Thanks.
Charles
http://en.wikipedia.org/wiki/IP_spoofing covers TCP briefly as well. You are pretty much right - attacker cannot receive the response back and as hard-to-predict initial sequence number is thrown into the mix, he cannot do very much without being able to observe the legitimate traffic.
Mart Oruaas
@mart oruaas thanks for backing me up.
Rook
@Charles I'm not exactly sure what your question is. You can implement a three way handshake over absolutely anything. I mean why not? Whats keeping specifically *you* from doing it?
Rook
@Charles Another thing to note, malicious players will be unable to spoof another players traffic if they don't know that players ip address. I think the majority of games rely on this.
Rook
TCP is no more immune to spoofing than UDP. It might harder to spoof TCP packets, but it is by no means impossible as you state. Spoofing is an inherent problem in the IP protocol and is not unique to either of the major transport protocols.
jathanism
@jathanism Could you please explain how you plan on establishing a TCP connection without being able to accept incoming communications. I have posted 2 links to backup my argument, and in an academic environment its proper to post supporting evidence for your arguments.
Rook
I wasn't trying to discredit what you stated, that TCP was immune to spoofing and that TCP source-address spoofing is impossible. Those things are in fact possible, and are even stated as such in the article you linked. Establishing a spoofed TCP connection is improbable, but still not impossible given the correct circumstances. Protection against spoofing relies heavily on packet filtering, which unfortunately is still done incorrectly by many admins. (http://www.symantec.com/connect/articles/ip-spoofing-introduction is a good rundown on the topic). I just wanted to clarify. :)
jathanism
MITM can happen _anywhere_, (ISP, backbone, etc) - it's just a matter of weather it's worth it or not. Keep in mind that a self signed cert will not help against MITM either, unless you negotiate trust on first connection to a server, in which case the first connection is the point of failure. @Charles: Are the game servers run by one organization or can anyone host them?
Longpoke
A: 

DTLS is likely the best solution, however, it appears to be very poorly documented. I've been looking for a similar solution for a while now and all of the references I've seen to OpenSSL's DTLS implementation suggests that you'll be needing to dig through the OpenSSL examples & source code to figure out how to use it... which, to me, means I'm going to make 10 serious security mistakes when I try to set it up. Also, I don't believe the pyOpenSSL liberary exports this functionality.

An alternative I've been considering is the Secure Remote Password Protocol. The advantage of this solution is that it gives you strong mutual authentication (on par with the security of Kerberos according to the docs) and, just as importantly in your case, it provides both ends with a shared session key that can be used for encryption.

Given the shared key, each packet could contain AES256_CBC( <random starter block for CBC><user-id><sequence_number><application data> ) If the decryption succeeds in providing the anticipated user-id, the packet is authenticated as coming from your user and the sequence number can be used for avoiding replay attacks.

One downside to SRP is that, in Python, the number crunching is pretty slow. I modified the demo Python code into something a bit more usable and found that it took about 300ms to perform a single client-server SRP exchange (2Ghz CPU). However, a straight-forward implementation in C++ of the SRP algorithim using the BigNumber support in the OpenSSL took only 2ms. So, if you intend to go this route, I'd highly recommend using a C/C++ implementation of the algorihim for production code. Otherwise, you'll likely only be able to handle a few logins per second.

Rakis
This secuirty system is very close to what I said, except you left out the most important part in that all of this adds **LAG**. The attack is to stop spoofing, not ease dropping.
Rook
Rakis
A: 

I'm breaking this down into four levels of security.

  • Extremely Insecure - Anyone on the network can spoof a valid request/response with generally available prior knowledge. (ie syslog)

  • Very Insecure - Anyone on the network can spoof a valid request/response only if they have at least read access to the wire. (Passive MITM) (ie http accessable forum with browser cookies)

  • Somewhat Insecure - Anyone in the network can spoof a valid request/response if they can read AND make changes to the wire (Active MITM) (ie https site with self-signed cert)

  • Secure - Requests/Responses cannot be spoofed even with full access to the wire. (ie https accessable ecommerce site)

For Internet games the very insecure solution might actually be acceptable (It would be my choice) It requires no crypto. Just a field in your apps UDP packet format with some kind of random practically unguessable session identifier ferried around for the duration of the game.

Somewhat insecure requires a little bit of crypto but none of the trust/PKI/PSK needed to prevent Active-MITM of the secure solution. With somewhat insecure if the data payloads were not sensitive you could use an integrity only cipher with (TCP) TLS/ (UDP) DTLS to reduce processing overhead and latency at the client and server.

For games UDP is a huge benefit because if there is packet loss you don't want the IP stack to waste time retransmitting stale state - you want to send new state. With UDP there are a number of clever schemes such as non-acknowledged frames (world details which don't matter so much if their lost) and statistical methods of duplicating important state data to counter predictable levels of observed packet loss.

At the end of the day I would recommend go very insecure or somewhat insecure /w DTLS integrity only.

Einstein