Can a malicious player see what's being sent by the game in POST if I use https to communicate with my web server? - unity3d

I have a high score database on my webserver, communicating over https.
Can a malicious player see the unencrypted content of the POST request, or is it already encrypted before he gets a chance to see it?

If the player is able to install a new root certificate on their computer that your game will trust, they can use mitmproxy or some other HTTPS intercepting proxy to observe any communication between your game and the server.
Basically, the way such proxies work is that they pretend to be the server your game (or a browser) tries to connect to, and can do so by presenting a dynamically generated certificate saying so, signed by the proxy's own root certificate. Obviously, for this to work, the user needs to tell their system (and specifically Unity) to trust this custom root certificate. But if they can do that, then Unity will happily accept the proxy's claim that it is indeed your server, since it sees a valid signed certificate saying so.
I don't know enough about Unity's HTTPS implementation to say for sure whether adding custom root certificates like that is possible. But, in the absence of certain knowledge that it's not, I would assume that it most likely is. In particular, if Unity just delegates certificate management to your OS, then adding the custom root certificate to the OS list of trusted roots (which any user with administrator privileges can generally do) will make Unity also trust it.
You might be able to prevent this attack by implementing some form of certificate pinning, so that your game knows what the legitimate server's certificate is supposed to look like, and refuses to communicate with a server presenting some other certificate, even if it's signed by what the user's OS considers a trusted root. But that may be non-trivial to set up.
(Also, even if you can prevent this particular attack, the player might still be able to intercept your data before it is sent over HTTPS e.g. by attaching a debugger to your game or by monkey-patching the Unity API used to transmit the data some other way. In general, it's very hard to stop a sufficiently skilled and motivated user from finding out what your software does as long as it's running on their computer.)

Related

Authenticating lots of clients for a REST API

We have a large number of small devices deployed in the wild that communicate with a central server via a REST API. It will send a status update on a regular basis with some sensor data and will also ask the server if there are any software updates that need to be applied. If there are, it will download it etc.
I'd like some way to prevent my server API from being used by unauthorised clients. Here are the solutions that I have and the issues which I anticipate. This question is somewhat open ended but it is mostly a question of best practices for, what I think is, a common situation.
Keep a single username/password on the server and then use basic auth over https. This is simple but if I change it, I'd have to somehow change the credentials on all of my devices (which number in the low thousands). This is hard to do reliably. There's also a problem with how the devices are going to get the update without first changing their creds.
The second is to create a username/password for every device. Then I can update individual ones and manage them but there's a lot of state on the server and I'm worried about having this much data on the server.
Some kind of automatic key based system whereby the devices can ask for an expirable key and then use that for all transactions. If the key expires or is invalidated, that device can't connect anymore. This would necessitate some kind of id for the device which I'm not sure how to handle.
So, how would I do this?
Update
In our setup, we have assigned hostnames for each of the devices we're going to deploy created beforehand. Once the devices switch on, they will contact the server with their hostnames and thereby register themselves. The MAC address and other information is passed as part of the initial registration handshake.
So, the "unique identifer" which was mentioned in the answer (and comment) by Noksi is the hostname. This can be easily spoofed (since the hostnames have a pattern). However, when the devices first come online, we can get the mac and, after that, only refresh the token if the request comes from the same mac. This opens up the possibility of a fake registration happening the first time though.
If there is some way to uniquely identify each device (similar to a MAC address) then that would be the key. Keep a registry of the devices and each device would register with the server. the server would provide the device with a token and associate it (the token) with the registered device. the device uses that token to make requests. tokens can be made to expire and renewed as needed or can be black listed if needed. This seems to be similar to option 3 in the proposed options.

Secure RESTful API via HTTP(S): How to deal with the certificate host check without host name (only IP address)?

For implementing a RESTful API via HTTP I need a way to secure communication (encryption of communication, prevention of man-in-the-middle and replay attacks).
The API is supposed to be used for communication between software PC clients (Windows, Linux), smart phones, hardware clients on the one hand and an embedded device (the server) on the other hand.
If I use HTTPS with one (all embedded devices ever manufactured can use the same one I think) self-signed certificate (that clients have embedded/store somewhere) I get all the benefits I want.
Now I have got one issue:
As the embedded devices are always accessed by IP address, the client side host check for the certificate is going to fail. Whatever is written in the certificate is NOT going to be the host that answers.
E.g. with libcurl I have to disable the check via
curl_easy_setopt(curlEasyHandle, CURLOPT_SSL_VERIFYHOST, 0L);
This doesn't hurt too bad for self-written clients - but clients are also supposed to be written by 3rd party developers. What I find awkward now, is that 3rd parties have to know, that they have to disable the host check (and they have to do it...).
Also, I am not sure if disabling this check is always possible with whatever http/TLS lib that 3rd parties are using.
A certificate issued for an IP address (if even possible?!) is not an option, as the IP address can be changed by the user of the device.
Is there a way for a certificate to be "host neutral"? Or is a part of my approach incorrect and I should do something differently? Or is there nothing that can be done about it and everybody implements it like this?

How to prevent connection to the server without my client application?

A client asked me to do a back-end server for its iPhone application and want only users who bought the application to be able to call the server.
The problem is that he doesn't want to add a login system to the application, so that it seems to me there is no completely safe way to prevent someone without his application calls the server.
In any case, even if it can not be completely prevented, it would be sufficient to make it difficult to access servers without the application.
What is the best way to achieve this? Again, I do not need to fully protect the connection, there is no transit of sensitive information, I just want to make things a little more complicated for people who want to take advantage of server without paying the application.
The idea that seems most simple is to encrypt the data with a key stored within the client and known to the server, so that the message can be decrypted only decompiling the code and finding the key (of course instead of a key you could put a list of keys, which change every 6/12/24 hours).
Could this be a reasonable solution?
This will never be possible. Welcome to the nature of the client-server architecture. You can never trust the client. Just make sure the functionality you are exposing is safe.
well if its a paid app you could release the app for free with all the functionally locked down until a user does a in app purchase and then you could verify the receipt on your server therefore proving that the device is a iOS Device?
sharing a key between the client and the server seems to be a good way to go. But instead of depending on the stored keys only, try combining them with a Unique identifier, such as UUID and send it to server both with the combined key, and the UUID itself.
At that point users UUID will be his identifier (username) and the combined key will be his token (password). And this will be a login-like mechanism.
An SSL connection is not enought to prevent other people from getting the URL for the requests? Or even better using an SSL connection with a basic auth?

Is there a way to add fiddler certificates for https decryption that will work across various users on a machine?

Is there a way to add fiddler certificates for https decryption that will work across various users on a machine? Or is it always user specific?
http://groups.google.com/group/httpfiddler/browse_thread/thread/b6acb3d48932d678
You can copy the Fiddler root certificate into the machine's Trusted
Root store (using mmc.exe to load the MACHINE's copy of certmgr.msc)
but that likely won't do exactly what you want because it sounds like
you imagine you'd run the Fiddler instance within each user's account
rather than just having one instance run centrally? That would be
problematic because when it's actually re-signing the traffic,
Fiddler's looking in the user's personal store for the root
certificate to use. I could easily change Fiddler to look in the
machine store first, although I'm not sure what the implications would
be for the private key's accessibility.
You'd probably be better off just having the user enable HTTPS
decryption themselves. If the goal is to simply capture traffic, you
can use FiddlerCap (fiddlercap.com) and the HTTPS option is right on
the home screen.

Secure communication between django server and iphone app

I'm writing an iPhone application that needs to send small bits of information (two strings of under 128 characters each, at a time, and this doesn't happen too frequently) to a server when users interact with it. I would like this information to remain confidential, so I'm thinking of some sort of encryption or secure connection would be necessary.
My question is about the server side of things. The server the iPhone app has to communicate with is written in django and is running on lighttpd. What is the most appropriate way (or what is a standard way) of doing this. I was thinking https, which I know on the iPhone I can use ASIHTTPRequest to do a POST request, but I don't know what it requires on the server side. Do I need a certificate? How does the data get encrypted/secured? Are there any django modules to help with this? Do I have to do something to configure lighttpd?
Would something like xml-rpc or json-rpc be simpler? Is it possible to secure such communication? At what level would that occur?
Any help would be much appreciated.
Using xml-rpc or json-rpc are only means to encapsulate your data into a form that is easy to transport. Your iPhone app can transform the Objective C data using one of those formats and your Django server app can transform the data back into Python objects.
Neither of these have anything to do with security.
Creating an HTTPS (SSL) connection encrypts all communication between the client (iPhone) and the server (Django). You will need to get a certificate for the server side. This indicates to the client that the server is who it claims to be. Your next line of research down this path should be about how to configure lighttpd to handle SSL traffic. Once lighttpd negotiates the SSL communication, your Django app will operate as it does for non-secured traffic.
This is your best choice.
If, for whatever reason, you don't want to use SSL, then you could find strong encryption libraries for both ends of the communication. The iPhone app could encrypt the data, send it over an HTTP connection and the Django app could decrypt it. For example, the pycrypto Python library implements strong encryption ciphers such as AES and Blowfish. You might be able to find an implementation of one of these ciphers written in Objective C.
Did you notice that this is getting increasingly complex?
Go with SSL. It's the way security is done for HTTP-based communication.
Hmm it looks like this might be what you're after, have you seen it?
Setting up SSL for Lighttpd/Django
If I read that right, that setup allows your server to answer https and http requests (?)
Then if your whole app isn't going to be https there's this SSL Middleware to help configure some paths as ssl and some not.
If you use https (SSL) on the server side it shouldn't matter if you use XML-RPC or JSON-RPC. All the data you transfer will be encrypted and secure.
I can only speak from our Rails application and nginx. I bought a SSL certificate from GoDaddy (very cheap) and nginx is setup to encrypt the content (Rails is not doing this itself) on the fly when it sends it out. On the iPhone ASIHTTPRequest will be responsible to decrypt the data. All other layers shouldn't be concerned about the encryption, you can send anything you want.
You might also be able to use a self-signed certificate. We decided to use GoDaddy as we also use the SSL certificate for regular browsers, and those show a warning message to the user if they encounter a self-signed certificate, which obviously scares people away.