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..
Related
I have an iPhone app that is using my php api on the server but it is currently open if someone knows the url. I want to make sure that no one can use this API until I am ready to make it a public api (if I even do)
I have read this article but I am unsure what they mean when they say:
[CLIENT] Before making the REST API call, combine a bunch of unique data together (this is typically all the parameters and values you intend on sending, it is the “data” argument in the code snippets on AWS’s site)
I don't understand how if I hash the parameters I plan on sending with my api secret how this is more secure than just hashing the api secret if I send the parameters/values unencrypted.
HTTPS the API and use an API key. Then you'll know that only people (you in this case) with the key can have access to the API.
You're correct about it not being more secure. That's why I suggest you SSL the connection. Unless you plan on encrypting everything you transmit back and forth.
The public/private key scenario will also work well. HTTPS requires very minimal effort.
Digital signatures provide a way of validating a message sent over an insecure connection.
Setup: each client will have its own private key and public key (only the private key needs to be stored on the client). The server will store the public keys for each client. The public key can be visible to all and can be used by the server to identify the client. The private key, known only to the client, it is never shown to anyone.
The client signs the request: along with the rest of the request data, the client will hash the combined request data and encrypt the hash with the private key. The server will generate the hash the same way (leaving the signature out of the hash calculation), then decrypt the signature using the public key. If the hashes match, the request is authentic.
Note that HTTPS allows for client certificates, so you can leverage existing tools to accomplish all of the above without writing a single line of server-side code (you just have to configure your web server; the only trick is to make sure the server only accepts certificates it already has). Moreover, the amount of client side code should be minimal: you shouldn't need to do much more than set the connection to use the client certificate. Since you're controlling the clients, you can use self-signed certificates and add the server as a certificate authority. There are a number of questions on SO about using client certificates in iPhone apps; you can start by reading through them.
Note also that any scheme to protect the web API only works so long as copies of the app are in trusted hands. Should anyone untrustworthy get ahold of it, they can use the app or extract any secret data used by the app and access the API as they will.
For development purposes you can just use your web server settings to allow requests from your ip only.
I built an application in an objective c that performs user registration into DataBase (MYSQL) using PHP with METHOD - GET.
Is there any way for me to know if the received parameters came through the app and not via computer or manually?
I mean, anyone can discover the address of the server running the PHP code and embed
some manually parameters as: reg.php?name=someuser&pass=password.
If your application has some kind of secret token and you use HTTPS with certificate validation then it's less likely to be a problem.
Remember that the contents of your application can be read by the user if they're determined, and the contents of your API calls can be intercepted and examined with a proxy application if you're not careful to validate the SSL endpoint against known-good certificates.
Normally registrations are sent via POST, not GET.
You can either transmit the secret directly, as a sort of proof that you're using the Objective-C application, or to make it harder to discover, then by signing your request using something like SHA256 where that secret is a salt.
The short answer is that yes, this is a security vulnerability.
Resolving this security vulnerability via $_POST Method
If you were to use the $_POST method instead, name and pass would be passed in the document's headers; going undetected in the URL. Then your web application could test for the presence of these variables, which would allow you to reject users who try to access the script from outside of your Obj-C app.
Better yet, also include a security token or hash parameter in the $_POST method, and test for the presence of that in your web application. On top of this, don't forget to clean your input before you allow it to touch your database, as an extra safety precaution.
Fixing further security issues & vulnerabilities
The web application might use HTTPS.
Should check for the presence of other environment variables to indicate if the client is accessing your website from the Obj-C environment.
My iOS app needs to connect to a mysql server. To accomplish this, I'd like to create a webapp that acts as the middleman between the client side apps and the server side database.
My concern is that someone can simply figure out the URL that my app uses and pass their own URL parameters - and since the webapp has no idea whether legitimate data is being sent from my iOS app vs. someone just typing in the properly crafted URL from any web browser, the system will be vulnerable.
Let's say I have a PHP function for marking a user as "verified" (after I send them an email verification code). This is pretty standard stuff, but what's stopping someone from making the same request from a web browser?
Of course, the user that the app uses to make database queries will have limited privileges, so the rest of the database won't be at risk. However, even having users activating their accounts from outside the app would be catastrophic.
The option that I thought of was using https so that even if the user figures out the URL, they won't know the password and wouldn't be able to sniff it since it's encrypted from start to finish. Unfortunately, https can be expensive for a poor college student, so I'd like an alternative if one exists.
As stated before, there is no 100 % security possible. But there are several solutions that put together give great security.
Https
As you point out, this is an important part , as it prevents sniffing.
Sessions
Use sessions and don't allow any request without a valid session ( except the first, that must authenticate the app ).
Fingerprint
Check the user agent and set extra http headers, to get a fingerprint unique to your app. ( Still someone could sniff, but he needed to use curl or similar. )
Obfuscate requests
Build your query string and apply a hash function. The server needs to implement the reverse function. ?43adbf764Fz instead of ?a=1&b=2
Encrypt
This goes a step further. Use a shared secret to calculate a hash. On the server repeat the same. This is already strong security. In order to break, one needs to reverse engineer your app.
Use unique shared secret
You say it is a app for iOS. Upon installation a unique token is generated by iOS. Have your app register this token with your server. Like this you have a strong shared secret unique to each installation, and there would be no way to hack your web app.
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).
I have an iPhone app that is using my php api on the server but it is currently open if someone knows the url. I want to make sure that no one can use this API until I am ready to make it a public api (if I even do)
I have read this article but I am unsure what they mean when they say:
[CLIENT] Before making the REST API call, combine a bunch of unique data together (this is typically all the parameters and values you intend on sending, it is the “data” argument in the code snippets on AWS’s site)
I don't understand how if I hash the parameters I plan on sending with my api secret how this is more secure than just hashing the api secret if I send the parameters/values unencrypted.
HTTPS the API and use an API key. Then you'll know that only people (you in this case) with the key can have access to the API.
You're correct about it not being more secure. That's why I suggest you SSL the connection. Unless you plan on encrypting everything you transmit back and forth.
The public/private key scenario will also work well. HTTPS requires very minimal effort.
Digital signatures provide a way of validating a message sent over an insecure connection.
Setup: each client will have its own private key and public key (only the private key needs to be stored on the client). The server will store the public keys for each client. The public key can be visible to all and can be used by the server to identify the client. The private key, known only to the client, it is never shown to anyone.
The client signs the request: along with the rest of the request data, the client will hash the combined request data and encrypt the hash with the private key. The server will generate the hash the same way (leaving the signature out of the hash calculation), then decrypt the signature using the public key. If the hashes match, the request is authentic.
Note that HTTPS allows for client certificates, so you can leverage existing tools to accomplish all of the above without writing a single line of server-side code (you just have to configure your web server; the only trick is to make sure the server only accepts certificates it already has). Moreover, the amount of client side code should be minimal: you shouldn't need to do much more than set the connection to use the client certificate. Since you're controlling the clients, you can use self-signed certificates and add the server as a certificate authority. There are a number of questions on SO about using client certificates in iPhone apps; you can start by reading through them.
Note also that any scheme to protect the web API only works so long as copies of the app are in trusted hands. Should anyone untrustworthy get ahold of it, they can use the app or extract any secret data used by the app and access the API as they will.
For development purposes you can just use your web server settings to allow requests from your ip only.