I intend to have a PHP web service accepting JSON-RPC over TLS (HTTPS). Every client will have an API key that I will use for identification purposes. Is that enough security, is there a JSON-RPC security specific standard?
That's a fine way of doing things. Here's an overview of the requirements and components play in your security scheme:
Checklist
Here's the checklist of what security is needed, and how you would address it:
A third party can't eavesdrop on your communications. HTTPS provides this.
A third party can't tamper with your communications. HTTPS provides this too.
The client can authenticate the server. HTTPS provides this (*).
The server can authenticate the client.
Client authentication
There are lots of way to authenticate the client. Here are a few exaples:
Use the API key to calculate an HMAC of the request and include the HMAC as a header in the request. (**) The most secure, but more complicated to set-up. The key advantage is that should your server be compromised, API keys won't be exposed.
Include the API key itself in the request. Easier to set-up, may be sufficient security depending on your requirements.
...
(*): So long as the client library does. HTTPS requires that you use a certificate that validates your site corresponds to the domain name. Unfortunately, many HTTPS libraries do not validate this by default.
(**): You should also use a nonce to prevent against replay attacks.
You could be signing a request using a secret salt (+hashing algo of choise, MD5 will do fine) because this way an eavesdropper cannot obtain the "API key" and forge his own requests. Use a very long salt.
The salt also acts to protect against intentional altering of a message by a successfull eavesdropper.
How can there be a man in a middle? TLS(SSL) is not much security against man in the middle attacks, unless you issue whitelisted certificates per client. For example, the server in the middle (attacker) obtains valid certificates, or the client application is not checking for various certificate validity settings (expiration dates, etc.). If not under your control, it is likely that clients of your RPC server will connect without doing any sort of security checks. This is a widespread problem. Eavesdropping usually implies access to your (or your client's) network so this could mean poisoned DNS traffic redirects to the rogue server.
Wether your or your client's network connection is secure enough to exclude the possibility of DNS poisoning, or your client is checking the certificates for validity, or you force the client to use whitelisted SSL certificates, are things only you can influence or decide upon.
You might also want to prevent replay attacks by assigning a unique number for each request (possibly overkill if these API calls are just for reading) for denying duplicate requests.
The API keys you mentioned, are generally used when browser side JavaScript clients are involved to track usage. API keys are reissued, when stolen, to identify and disable unauthorized apps (and maybe automatically make a list of the fraudulent domain names for further [lawsuit] action).
Related
I am currently managing two servers that have a shared secret key.
I would like to be able to send data between the servers in a manner that even if someone is listening in the middle, the data will be only read if someone has the secret key.
My requirements are:
encryption
authentication
But also:
freshness: so that old encrypted data that has been intercepted in
the past will not be accepted if transmitted now by someone else.
I was wondering if defuse/php-encryption is applicable to this scenario given that it provides encryption and authentication.
I also took a look at libsodium but I want to stay away from PECL if possible.
Thank you.
I would suggest that you use an existing cipher suite that can "blanket secure" the entire connection between the two parties. Then, in any case, use digital certificates (they can be self-signed ...) to secure the connection. (Do not use "shared secrets," a.k.a. "passwords.")
TLS (the successor to SSL) is used by HTTPS secure web-sites. (Be sure to use the current version of this protocol!)
VPN (as "OpenVPN" or "IPSec") provides "a secure router" between two subnets. The advantage of this strategy is that the two parties don't have to do anything to obtain a secure, reliable connection: it’s just there.
SSH is also able to do "tunneling," but it's too-easy (IMHO) for data to wind up actually being passed insecurely, and it really doesn't provide identity-verification.
These cipher suites will provide you with three very important guarantees:
The data is not intelligible to any other party.
There is no "man in the middle." The parties can identify exactly with whom they are communicating.
Messages received are known to be "exactly what the sender sent."
Nothing in-secure is passing "out of band" between the two parties.
... and yet, they operate completely "in the background," just as you routinely see TLS doing when you connect to a secure web-site. "It is secure, and 'it just works.'" It is very important that your scheme be unobtrusive to authorized users.
I have two web applications which need to communicate data between them, for example when an employee is added in Application A, i make a CURL request / POST request ** and pass some of the employee data and Store it in **Application B.
The functionality is working fine, now i want to make the request flow secure, these two application i.e. Application A and Application B are on two different WebServers built on different technologies. One in PHP and Other in Java.
So when a record is added in PHP i send CURL request and save data in java. **The PHP application is built for distribution which would be sent to the end users.**
How i can make sure that the POST requests i send are secure. Any ideas?
How i can make sure that the POST requests i send are secure.
Well, the answer depends. Who do you want to make the requests secure from? What kinds of attacks are you worried about? I'll go through a few possible vectors here:
The End User
It is impossible to protect against an end user attacking your system.
Given that you're distributing the application to them, and they control the networking stack, it's literally impossible to 100% protect against the user from doing something nefarious.
You could obfuscate the source, and do all sorts of tricks to make it harder, but ultimately if the user has the program, and its running on their hardware, they can do what they want with it. Including attempting to extract encryption or authentication keys from the application.
An External Attacker
To protect against an external attacker without access to either system, there are some steps to take.
Use SSL for the communication.
This encrypts the traffic so that an attacker cannot see or modify the data in transit.
Use certificate pinning
In the application that you ship to the client, include a copy of the certificate that you use for your server. That way you can detect an attacker who tries to masquerade as your server (via DNS spoofing, or other attacks).
Verify SSL Peers.
This forces CURL to check the certificates to ensure they match.
Authenticate the client using secure cryptography
Generate a public key / private key pair. Store the private key on the client, and the public key on the server.
When issuing a request, sign it using the private key, the time of the request.
On the server, when you get the request, validate that the request time is greater than the last seen request (to prevent replay attacks). Then validate the signature using the private key, then store the request time as the last seen request.
Don't roll your own crypto. It won't help. Security Through Obscurity is not security. At least when it involves cryptography...
Here are some points which may result in surity of secure data transfer:
Use of SSL requests will be helpful.
Use an app token which will only known to applications. So while receiving and sending data you verify that token.
Try encrypted data transfer using some mechanism known to applications only, if don't want to use SSL.
Your own Algorithm to encrypt decrypt the request and its parameters, which only the receiving, sending applications will be knowing.
Many more..
First of all, a better question would be is this possible? My gut instinct is that it isn't entirely, but there may be some clever ways. Even if they just act as a deterrent, make it slightly harder for some one to hack, or even make it easier for me to detect suspicious activity.
Basically, I'm building a web service using PHP for my C#.NET program to connect to. Among other things, one of the most important purpose the web service serves is verifying license data. The program sends the licence key entered by the user to be checked, and if it is valid the web service will return the Name of the person who purchased the licence key so that the program knows to activate itself.
I am fully aware that there is no perfect anti-piracy scheme and that is my software will be cracked if people want it bad enough. However, I do not believe that there isn't anything I can do to make it very hard for people to crack my software.
I do have an SSL certificate so the program will be communicating with the web service using HTTPS, however that's the only security I have at the moment. I have thought about
Using long and obscure names so that the functions are hard to guess
Using MD5 to disguise the functions
Adding a username and password
Checking the User-Agent
etc.
However, I have read that there are applications available to simply extract strings from programs, which would render those measures completely ineffective. Still, I don't know how technical users have to be to use those applications. Is it still worth adding some of these measures to stop casual piracy? Which measures are the better ones and what will be the most effective?
Thanks in advance
You can distribute your C# application with a certificate bundled and sign your requests with the certificate. The server can then verify if the request was signed by your application and reject any other request.
Edit: Whoops, I only now understood that you want to secure you application even when in the hands of a malicious user. This, I don't think is possible. A hacker can decompile, scan the memory, read and decode files, etc and your certificate will be available in there if you distribute it with the application. An alternative would be to distribute an external security token (hardware device or flash storage) which will need to be plugged-in to the client computer. The token holds the certificate, keys or cyphers used to sign/encrypt your requests and it therefore doesn't stay with the application.
Your server-side SSL certificate will only guarantee that the communication channel is secure and the server is not lying about his identity. It doesn't guarantee anything about the client connecting. To also be sure that the client is identified, you need to use a form of client certificate that your server recognises.
I have a HTTP REST API in PHP used by an iPhone application.
Some webservices from this API are secured with a user authentication in the HTTP request credentials but I want to avoid "man in the middle" attacks by providing fully encrypted requests data.
I'm not really skilled in security issues and I couldn't find any clear answer to my question anywhere :
Is HTTPS relevant for STATELESS REST API ?
From what I understood, HTTPS does 2 things :
encrypt your session
prove to the client that the server he is talking to is secured
So at first sight it does not respond to my need which is to encrypt the data between my server and the application because the API does not use sessions. But I still have doubts.
Can someone make it clear to me ?
My other solution would by to encrypt requests data with public/private keys system. Would it be more suitable ?
Thank you !
Yes, it is. HTTPS has nothing to do with the application, it's a tunneling protocol. Even though TLS is itself a stateful protocol, the HTTP part going over it is not.
Just like if you were using a VPN, you can still have a REST based application. The TLS just sets up and tears down the tunnel automatically for each connection.
That said, there's value in leveraging the pipelining aspects of HTTP and HTTPS to improve throughput over TLS connections, but that's a performance tuning aspect unrelated to the application itself.
HTTPS is very relevant, and yes, that's because of the two points you mentioned. Did you know that OAuth 2 actually enforces HTTPS?
Doing all the encryption yourself could be an option as well, but you lose the part where the API is easy to use.
Most man-in-the-middle attacks on "simple" HTTP requests involve stealing credentials and faking requests, but they can also read the data sent and received. If your issue is with the data being unreadable, use HTTPS. If fake requests are the only problem, an authentication protocol such as OAuth 1 (not 2) would suffice.
If you do not want to implement SSL you may want to check out http://www.jcryption.org/ I don't know if it will work in a stateless environment, but may be worth a try. It is basically a jquery plugin that handles creating key pair associations for data being transmitted. May only be for form submission though. We used to use it to encrypt login credentials at my old company.
Definitely use, HTTPS if the data is sensitive - it encrypts at the transport layer which is what you are looking for. As already pointed out oAuth 2.0 mandates it essentially. You can potentially avoid man in the middle by using hashing/signing as in oAuth 1.0 and avoid having to use SSL but the body still goes in the clear then (you've avoided sending the API credentials in the clear but not the body).
We have the following:
iPhone native app, with login form that posts to:
A php script on remote web server which checks against MySQL user table.
For security, would it be best practice to use some two-way encryption to encrypt every request? including this initial login? otherwise the user and pass will simple be passed to the web app in the clear?
I suppose https would take care of it automatically...
It would be very wise to use SSL or TLS (the protocols that HTTPS uses) to communicate with the server. You could likely get this set up rather easily on a *nix or Windows server using OpenSSL. If you're on a shared host, they likely have an option to purchase an SSL certificate that's valid for a given period of time. This is a fairly trivial process and usually requires about a week (average) with most hosts to get set up.
It should also be noted that while it is never a bad idea to encrypt the login process, it will not make your system more secure "over all" if you have a login from the web that is not secured. For instance, if you secure communication with mobile devices, but not with desktops or laptops, your security may be for nigh. The security of your application is only as strong as its weakest link, so securing your entire application (for all platforms) is very important.
Also, keep in mind that a user's login credentials are only as valuable as the data or resources that they protect: if you encrypt the login information, it is also a good idea to encrypt the rest of the application as well. Wireless sniffing technology could easily steal session data, private user information, or other sensitive data. Securing the entire user session--rather than just the login procedure--is in your users' best interest.
Hope this helps!
Using https is probably the way to go. It's what it was designed for.