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

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?

Related

Is accepting all client certificates considered insecure for a public OPC UA server?

I am aware of certificate chains when validating a client certificate. Still, this either puts a lot of burden on the server administrator or restricts clients, which can be unfavorable when implementing a public OPC UA server.
An implementation of the client certificate validator that accepts all certificates for message encryption/signing is certainly possible. But would such an implementation be considered insecure in that matter?
If yes, how?
Yes, it is considered insecure.
Aside from the (hopefully) obvious use case, where certificates ensure you know exactly what client applications are allowed to connect to the server, certificates are also the first line of defense against malicious clients and are part of a "defense in depth" strategy.
A malicious actor that can't establish a secure channel with the server doesn't have much to work with. A malicious actor that can establish a secure channel can, e.g., open many connections, create many sessions (without activating, potentially causing a DoS are you use resources), attempt to guess credentials, re-use default credentials that an application may ship with, etc...
Further... in the face of the recent CIS alert re: ICS/SCADA devices + OPC UA servers, you'd be a bit of a fool to willingly ship a less secure product for the sake of convenience.

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

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.)

Best practice for secureing an existing socket connection, without SSL

In Best practice for secure socket connection, the OP wants to secure the connection between two sockets, without SSL.
Thomas Pornin suggests SSH is the answer.
Is this answer based on SSH port forwarding of existing sockets, or just switching to SSH in general?
If not, and the question was how to make existing sockets more secure without SSL, what is the best way to to do that?
If a client on port 10 connects to a server on port 20, how can the server restrict access so that only client on port 10 can connect? And that it really is the client on port 10 (not an imposter)? (Availability only for an authenticated client).
The answer there is any form of the SSH protocol, which is based on channels. You can use those channels to transmit fairly arbitrary information, including port-forwarded data or terminal sessions, or anything you can turn into a byte stream. That said, TLS is generally much easier to implement in code because the libraries are ubiquitous and designed to be used this way. SSH is easier to implement in scripts on Unix-like systems because it has a powerful command-line API.
In most cases, TLS is the better choice. Unless you have a very specialized problem, TLS is almost always the better choice. So the question here is, what problem do you have that TLS doesn't work for? If it's "I hate TLS" then sure, SSH. But TLS is better in most cases.
TLS authenticates using client certificates. SSH authenticates using your private key. In either case, the cert/key is stored in a file that the client reads and uses to authenticate to the server.
It's not clear from your question what you mean by "client" or "imposter" here. Anything that has access to the cert/key will be authorized (possibly requiring a user-provided password), so those must be protected. If when you say "client" you mean "my application," that is not a solvable problem. You can authenticate people. You can to some extent authenticate machines (particularly if you have an HSM or similar piece of security hardware available). You can weakly authenticate that client is claiming to be on port 10, but this is generally useless and extremely fragile, so I wouldn't pursue it. You cannot authenticate software over the network in any meaningful way.
Short answer, though, is to use TLS unless you have a very specialized problem and a good security expert to help you design another solution (and your security expert will almost certainly say "use TLS").

Peer 2 Peer call using PJSIP and PJSUA

I am still learning about SIP and all its protocols, specifically trying to integrate PJSIP into an iPhone application to make p2p calls.
I have a question about a peer 2 peer connection using PJSUA. I am able to
make calls perfectly to other clients on my local network by calling directly using the URI:
sip:192...*:5060
I am curious if this will work for
making direct calls to other SIP URIs that are not on the local
network without using server configuration - if not this way, is there another way of making p2p calls without server configuration?
thanks in advance,
You can make calls without server configuration, as a general principle, but something needs configuring. As mattjgalloway points out in the comments below your question, the most robust solution is a can of worms involving ICE which provides a kind of "umbrella" protocol for things like STUN.
Last time I touched this issue, I had the requirement that I couldn't use internet-based SIP servers to help. I came up with the idea of a registry of sorts: your client can define a bunch of "address spaces" with particular routing requirements. For SIP URIs in your LAN, you define no routing; for URIs in your company's VPN-accessed network, you define a route passing through your VPN connection; for everything else you define a route through your internet router.
By "define a route", I mean that when you place a call to a URI in some particular address space, you store what IP will go into a Contact header, what Route headers you might need, and so on.
Thus, the process of making a call becomes:
Look up in the set of address spaces for a match.
Ask that address space for the suitable bits needed to make a workable INVITE (appropriate Contact header details, Route headers, etc.)
Construct a normal INVITE, mutating as necessary for the previous step.
Send the INVITE as normal.
This essentially reproduces half of what ICE would give you, in a manually administrated form. "Half", because this ensures that one SIP agent can make calls such that the SIP routing all works. The missing half is you still need some kind of registrar somewhere, and each agent in your contact list needs to have the necessary setup to receive incoming calls. (If an agent's behind a NATting internet router, the router would need to either run a SIP proxy, or forward ports 5060, 5061 to a particular machine (which might be an agent, or a proxy serving the LAN's agents).
It is, indeed, a large can of worms.
The basic issue is to solve the problem of getting transport ports anywhere on the internet for multimedia traffic.
Many companies/experts have tried to solve this situation. A possible way out of is to buy a domain and setup a basic registrar using YATE or Asterisk on an address accessible from the internet and configure it to also use ICE as needed. Your iphone application at both ends could register automatically to it upon start. Then make P2P calls.

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.