Implementing security over a network layer that doesn't support security - networking

Foreword: I don't really know much about security or encryption or how it works.
I am developing a small server for a game that uses ENet, which doesn't support higher level things such as security (e.g. SSL/TLS in the TCP world) to, as I think they said, maintain simplicity and embeddability. Supposing that this game requires at least some reasonable degree of security and authentication (e.g. logging in and such), what would be a good approach?

Related

Best way to encrypt data and prevent replay attacks over HTTP

I'm working on IoT gateway which will collect data from IoT devices. IoT device is a constrained device which couldn't use HTTPS.
It sends periodically small amount of data - from sensors, with some aditional information as time, message id, unit id etc.
Right now we've got an implementation of gateway as REST API in Java open for everyone. So It accepts requests as JSON from any device, without ensuring that data comes from our device are not corupted or compromised.
Without having ability to secure data by HTTPS, what is the best way to design interface between gateway and device?
Without having ability to secure data by HTTPS, what is the best way to design interface between gateway and device?
You can still use a symmetric encryption/authentication to ensure integrity and confidentiality, which should be feasible even for low end devices
As an inspiration you may have a loot at JWE with a shared key.
You could limit replays using some timestamp/counter or having idempotent consumers.
Regardless that - missing tls/https ypu have to take care of a lot of things, such as how to protect a shared key, update if revoked, etc
If the device can't do https (with any set of cipher suites) you will probably have to make serious compromises and not have some aspects of a secure connection. A bit simplified, but https is pretty much the minimal full suite of how it can be done, there is nothing "unnecessary". You might not need everything, but it entirely depends on your usecase and threat model. Before implementing this, you should have a full understanding of exactly what https provides, and how, so you can use applicable parts. Also note that this is not at all straightforward to implement, a custom implementation will likely be vulnerable.
How constrained is your device really? There are small implementations of TLS that wouldn't require you to compromise on security such as wolfSSL.
Footprint sizes (compiled binary size) for wolfSSL range between 20-100kB depending on build options and the compiler being used.
Regarding runtime memory usage, wolfSSL will generally consume between 1-36 kB per SSL/TLS session.
Anyway, I would not recommend you try and implement your own cipher suite unless you REALLY know what you are doing.
Given the kind of tools you've mentioned having access to (HTTP/JSON), I suggest looking at JOSE, which is a standardized way of signing and encrypting this kind of data. Specifically you'll be interested in JWE, JWS, and JWT. The learning curve for JOSE is unfortunately somewhat steep and the docs are somewhat sparse, but it is quite effective and implemented on a variety of platforms, and will save you a lot of headache in inventing your own protocols (which is quite difficult to do correctly). I've had pretty good luck building custom systems around JOSE.
There are some key questions you need to ask:
Do you need mutual authentication, or only authentication of the device? If the device only writes and never reads, then you likely only need to authenticate the device and not the server.
Can you accept the risk of a single shared secret baked into the devices? The problem with a single shared secret is that if any device is reverse engineered, then all protection is lost until you phase out all devices with that key.
Can you accept the manufacturing cost of a per-device secret? Depending on your manufacturing process, generating a unique secret for each device may be difficult.
Can you accept the on-device storage space and processing requirements of a client certificate? If not, can you accept the logistics of maintaining a server-side database of every device's key? (If you can except neither, then you'll have to go with a single shared secret for the whole system.)
My gut feeling is you're talking about a device that can handle the complexity of a client cert, but not a full HTTPS stack. If you also can handle the complexity of generating a certificate during manufacturing, or your customers are willing to register their devices, then I recommend the following:
During manufacture or registration, generate a certificate and signing request. Send it to your server to be signed, and install the signed X.509 on the device. (Generating a CSR on the device is also an option, but many small devices lack the entropy to generate a decent random number. There are tradeoffs either way.)
Generate a certificate for the server, and install its public key on all devices.
Assuming the amount of data you're sending is small, I'd bundle it all into the JWT (web token), encrypted to the server's public key, and signed with the client's private key. Typically JWTs are used to exchange authentication information, but they're really just a standardized container for sending signed and encrypted JSON data, so they really can be anything you want.
In order to prevent replay attacks, the server needs to keep track of messages its seen before. There are two main approaches I like, depending on your situation:
Make the jti (JWT ID) a combination of the timestamp and a random value (in which case the server just needs to keep a cache of recent JTIs and reject too-old timestamps)
Make the jti a combination of the device id and a monotonically increasing message id. The server then needs to keep track of the last-seen message id for each device, and reject any ids less-than-or-equal to that.
If you don't need encryption, look at JWS instead, which just signs the data. None of these techniques require encryption, and it's a little simpler if you take that part out (you don't need a server certificate, for example). You can still prevent replays, and only allow trusted clients to connect. It is possible for someone to reverse engineer your device and pull out its client cert. The advantage of a client cert is that if you discover the abuse, you can then just ban that one cert. With a shared secret you can't do that.
The basic advantage of all of this is that JOSE is based on JSON, which is something you already understand and know how to parse and work with. But it's also reasonably compact for a string-based protocol. It's also extremely flexible in terms of algorithms, which makes it much easier to implement on smaller hardware. You could build all the same things by hand using public/private keys, but JOSE has already thought through many of the tricky security problems.
If only it were better documented....

Is there a way to avoid MITM attacks without encryption?

After the player is authenticated, he receives a random, unique identification token. Every packet sent by him includes the token. A typical message would be:
token sequence_number commands
The problem is that, if somebody saw a packet, the person would be able to act as the player and give all the player's coins to somebody else for example. Or read the player's messages, or do anything short of stealing personal info.
So I thought encryption would be a requirement. But I've found many people advocating against it, one even says "it's complete paranoia" (https://gamedev.stackexchange.com/a/25551/33993).
Is there a way to avoid MITM attacks without encryption? If not, is avoiding them unnecessary?
The linked question says, "Only if it is an in-game purchase/micro-transaction - and then why not just use something tried and true like HTTPS."
Https is regarded as sufficient for MITM protection.
By which I mean: Yes!, you should send your traffic on Https!
It will have an impact on performance, but (obviously) lots and lots of effort has gone into optimizing that. A lot of the cost happens on establishing an Https connection. For an ongoing game connection, you should be able to keep it open, and the performance impact will be lessened.
As commenters have mentioned, Https uses TLS for encryption. You can build your own TCP or even UDP protocol using TLS, as well, but these days I'd recommend if possible, use boring old TCP/Https. All the platforms have APIs for it, there's ways to make it realtimey, and it plays probably the easiest with home routers & firewalls, and will be unsurprising when you explain it to others.
See pusher and socket.io and long polling for examples of using http/https for realtime.
MITM protection without encrypting the communication channel is difficult. You could use a Message Authentication Code (MAC) to protect key components from being changed. But you still need a shared secret that has to be exchanged over a different channel or using encryption (HTTPS).
You might want to take a look at the Hawk authentication scheme on how to exchange data securely over an unencrypted channel.
Typical encryption (example: HTTPS) is not sufficient to defeat MITM (http://en.wikipedia.org/wiki/Man-in-the-middle_attack) attacks. The wiki page has a simple example of how MITM is able to defeat encryption. There are complex methods to defeat MITM but they are typically overkill for a web game.
To answer your question, encryption does not defend against MITM, but it is necessary to implement encryption as it has more to do with securing sensitive information (example, passwords, session keys etc) as it passes through the internet. Otherwise anyone listening on the network will be able to see those information in plain text.

What are the options for an encrypted transport

I am working on an application that needs to encrypt all of its traffic on a LAN environment and so the speed of encryption is important and the cpu time needs to be reduced to let the application have more cpu cycles for itself. I am thus trying to understand what are my existing options besides rolling my own since I'm not a cryptographer.
I am trying to go now for a comprehensive list of all semi-valid options to be able to measure and test them:
TLS -- Not considered fast, maybe possible to tune the ciphers
SSH -- Maintaining ssh tunnels may be a burden
UDT -- Should be high performance, how is the optional encryption?
CurveCP -- By DJB so encryption is good, not sure about the transport part
MinimaLT -- DJB contributed crypto know-how, others did the transport
IPSec -- non-trivial to configure
What else I missed?
Go with TLS. The chances that the provider has heard of it and that acceleration is already present is rather high. SSH would also be an option, but it is generally used for administration.
About the other options:
UDT -- Should be high performance, how is the optional encryption? Good question, and a quick search did not find too much information, so avoid.
CurveCP -- By DJB so encryption is good, not sure about the transport part Anything mainly done by DJB requires university grade understanding of cryptography.
MinimaLT -- DJB contributed crypto know-how, others did the transport. See above. The main documentation seems to be a paper about MinimalLT.
IPSec -- non-trivial to configure And possibly security at the wrong level. Personally I would avoid, may be tricky to setup on a cloud provider.
So there you are, in the end transport level security always seems to gravitate towards TLS.
Try to go for a ciphersuite with AES and ECDSA/ECDH(E) if you want a high chance of a speedy implementation and a high level of security.

What are the benefits of not supporting UDP in cloud network? (thinking of Windows Azure case)

Azure, Rackspace and Amazon do handle UDP, but GAE (the most similar to Azure) does not.
I am wondering what are the expected benefits of this restriction. Does it help fine-tuning the network? Does it ease the load balancing? Does is help to secure the network?
I suspect the reason is that UDP traffic does not have a defined lifetime nor a defined packet to packet relationship. This makes it hard to load balance and hard to manage - when you don't know how long to hold the path open you end up using timers, this is a problem for some NAT implementations too.
There's another angle not really explored here so far. UDP traffic is also a huge source of security problems, specifically DDoS attacks.
By blocking all UDP traffic, Azure can more effectively mitigate these attacks. Nearly all large bandwidth attacks, which are by far the hardest to deal with, are Amplification Attacks of some sort and most often UDP based. Allowing that traffic past the border of the network greatly improves the likelihood of service disruption, regardless of QoS sureties.
A second facet to that same story is that by blocking UDP they prevent people from hosting insecure DNS servers and thus prevent Azure from being the source of these large scale amplification attacks. This is actually a very good thing for the internet overall, as I'd think the connectivity of Azure's data centers are significant. To contrast this I've had servers in AWS send non stop UDP attacks to our datacenter for months on end, and could not successfully get the abuse team to respond to it.
The only thing that comes to my mind is that maybe they wanted to avoid their cloud being accessed through an unreliable transport protocol.
Along with scalability, reliability is one of the key aspects in Azure. For example Sql Azure and Azure Storage data is always replicated in at least three places and roles with at least two instances have a 99.95% uptime in their SLA.
Of course, despite its partial unreliability, UDP has its use cases, some of them enumerated in the comments from the feature voting site, but maybe those use cases are not a target for the Azure platform.

I want to build a decentralized, reddit-like system using P2P. What existing p2p library should I base it on?

I want to build a decentralized, reddit-like system using P2P. Basically, I want to retain the basic capabilities of reddit, but make it decentralized, to make it more robust and immune to censorship. This will also allow people to develop different clients to match the way they want to browse it.
Could you recommend good p2p libraries to base my work on? They should be open-source, cross-platform, robust and easy to use. I don't care much about the language, I can adapt.
Disclaimer: warning, self-promotion here !!!
Have you considered JXTA's latest release? It is probably sufficient for what you want to do. Else, we are working on a new P2P framework called Chaupal, but it is not operational yet.
EDIT
There is also what I call the quick-and-dirty UDP solution (which is not so dirty after all, I should call it minimal).
Just implement one server with a public address and start listening for UPD.
Peers located behind NATs contact the server which can read how their private IP address has been translated into a public IP address from the received datagrams.
You send that information back to the peer who can forward it to other peers. The server can also help exchanging this information between peers.
Then peers can communicate directly (one-to-one) by sending datagrams to these translated addresses.
Simple, easy to implement, but does not cover for lost datagrams, replays, out-of-order etc... (i.e., the typical stuff that TCP solves for you at the IP stack level).
I haven't had a chance to use it, but Telehash seems to have been made for this kind of application. Peer2Peer apps have a particular challenge dealing with the restrictions of firewalls... since Telehash is based on UDP, it's well suited for hole-punching through firewalls.
EDIT for static_rtti's comment:
If code velocity is a requirement libjingle has a lot of effort going into it, but is primarily geared towards XMPP. You can port off parts of the ICE code and at least get hole-punching. See the libjingle architecture overview for details about their implementation.
Check out CouchDB. It's a decentralized web app platform that uses an HTTP API. People have used it to create "CouchApps" which are decentralized CouchDB-based applications that can spread in a viral nature to other CouchDB servers. All you need to know to write CouchApps is Javascript and learn the CouchDB API. You can read this free online book to learn more: http://guide.couchdb.org
The secret sauce to CouchDB is a Master-to-Master replication protocol that lets information spread like a virus. When I attended the first CouchConf, they demonstrated how efficient this is by throwing a "Couch Party" (which is where you have a room full of people replicating to the person next to them simulating an ad hoc network).
Also, all the code that makes a CouchApp work is public by default in special entities known as Design Documents.
P.S. I've been thinking of doing a similar project, but I don't have a lot of time to devote to it at the moment. GOD SPEED MY BOY!

Resources