RESTful API Authentication & Security - php

I am developing an Android and iOS application that will use a RESTful API that I developed on a separate server. The applications will simply poke at the endpoints to update data within the database and to retrieve information when needed. My problem is not doing that, the architecture of the API is already setup I just need to think about the most secure way to implement it.
I have an API Key system that requires any uses of the API to be paired with the requests which will prevent anyone without the key from accessing the API. This works well, but I am worried about people who are more determined to break through the system. Specifically on the Android side, applications can be decompiled and (some) of the code can be viewed. I am pretty sure that strings can be viewed so I am worried that if someone decompiles the application they will get ahold of the API Key and be able to access the API.
I am looking for suggestions to make the API more secure. I have already considered pairing another unique value with the API Key when updating information but I am not sure if this will work that well either.
Any suggestions are very appreciated it.

You are right about being worried that your application can be decompiled. Code and strings are stored in the clear. In fact this is rather trivial to do.
I've heard that someone looked at two applications: one contained email service password and username in clear text, very useful for spammers. Another had its "random" number algorithm exposed allowing hackers to generate today's "random" number and ride for free using public transport facilities.
You can raise the bar by:
Obfuscating your code with tools. Some tools will offer capability to encrypt strings.
Manually encrypt sensitive strings in your application using new encryption key per new install, split your encryption key and hide it in several different places, e.g. part in code, part in a database, part in OS and apply ACL to external locations
Use transport security (e.g TLS) to reduce risk of man-in-the-middle attacks
Use API rate limiter on the server side
Introduce geo location services to see if same API key is used from different locations at the same time

Related

How to store the API keys of my clients in a secure way?

I am developing a SAAS service that allows my clients to connect third party emailing tools (eg MailChimp). I therefore ask to enter their API key associated with the desired service to allow certain actions to be performed automatically on their account.
For that I record in their database their key (s) API and the connection is done. But from a security point of view, if my database comes to be hacked despite all the predispositions taken in terms of security (prepared requests etc) ... These are all the API keys of my clients that are revealed and also email addresses of their own customers that can be retrieved, used, resold ... Because the tools I connect essentially allows to store contacts, organize and send emails.
So I wonder what is the best practice to allow my clients to use the API of their favorite tools without endangering the security of their own accounts and data of their customers (emails, etc). I am aware that currently launching my web application with this data in clear in database would be dangerous.
I thought of several solutions:
Encrypt API keys in database, but I do not see how to test them (decryption) since it's not like a password?
Store API keys on a different database hosted elsewhere, but the problem of encryption remains the same ... no?
Use an OAuth stream: it seemed to be convenient, but all the services I want to connect via API do not offer this and I'm not even sure that this is really suitable for me.
I intend to host my SAAS on Amazon web services, I saw that it was proposing a service called "KMS" Key managament storing but I do not know if it is really adapted once again to my problematic ...
If someone has already had to answer this problem, or knows how to solve it, I want to be enlightened on it!
Note: Sorry for my bad english, i'm French.
All of the solutions you mentioned are somewhat valid and a combination is most likely the best answer. Your application needs access to these API keys so it's not really possible for a hacker to gain full control of your application and not gain control to the API keys. Full control being the key part - you can make it a lot harder to get to them.
Encryption
You would need encrypt them, not hash them, with something like AES. As you need to be able to decrypt them and use them in your requests towards the 3rd parties. This will help you protect against, eg. a database leak - if someone gets your database they would have to crack the encryption to get to them (as long as the encryption is properly implemented). The encryption/decryption key would of course have to be NOT in the database otherwise the whole thing has no point :)
Separation
Different database also makes sense - if someone dumps your main database they won't get to the API keys database and would have to get deeper into the application to access this database (ideally would be a completely separate DB server only accessible from your application).
Architecture of the solution matters too - you can have one server posing as a web-interface that is internet facing and that would talk to the backend server that is not internet facing over some limited (as much as possible) API to lower the attack surface. Only the backend server would then have access to the keys database and would perform the requests to the 3rd parties. Now an attacker has to jump through several servers to get even close to the keys.
Combining the above-mentioned will ensure one would have to obtain full control of your application (and all its parts) to get to the keys, the encryption key and bypass whatever other protection you might put in place.

A simple method to secure a simple read-only API

I have built a simple read-only API for our database, so that users can retrieve data from our database.
For example, the URL "http://xxxxx/getAllProfiles" will return a JSON result containing all profiles stored in the database.
The API is read-only, it is only implemented with some 'select' SQL queries. Thus the user cannot modify any of the data in the database via the API.
My company worries the API will be exploited by some random bots online, and has been asking me to build a security mechanism for this API. (It is worried if there is no key or something that prevents anyone from accessing the URL, our server would be visited too much. It is a small server.)
What would be the simplest secure mechanism that I can implement, using PHP? (We are also using Slim for the API, Amazon EC2 server with Ubuntu and Apache running on it, if this helps.) Preferably it can be implemented without the use of any database on server or client side.
If there's anything not clear, please let me know, I'll clarify.
Thanks.
Add:
Thanks for the comments.
Is there a way to NOT use a database? Like a smart way to generate a key or something... I'm thinking I'll provide a page so that user can input the domain, and an algorithm will convert this domain to a key. Then, for each request, the user should include this key. The server will grab the domain from the request header and use the same algorithm to calculate again. If the two calculated key matches, the request is accepted. I think this, at a minimum level, ensures that at the beginning there must be someone to input the domain and get the key, thus filtering some random bots out?
I am not sure if this is secure (at all)? But it sounds to me like it can filter out something.
I posted this question when I know very little about web development.
There are many ways to secure a REST API, e.g. JWT, Cookie, Basic Auth, etc.

Security in data transmission

I'm creating a server(PHP) to store data from android app. With POST query store name, password and email. These data as mentioned are stored on the server (database on hosting).
But I have a lot of questions how to do it correctly:
First is the backend, how to protect data and how to encrypt them?
I know that you can transfer token of android application on the web (server). And there it checked for accuracy, but android application is easy to decompile. How to be in this case?
Also heard of RSA but examples show how the mechanism works. And when used in RSA, I have the private key stored on the server and the public in android application? But what if I we obtain encrypted data from the server on android? I need to decrypt them using the private key. But the key on the server and store the private key on Android ill (paragraph 2, decompiling).
Other...
Please leave comments. Also describe every paragraph of my question, and it is desirable for each paragraph post a link with useful information. Also, I would appreciate any HELPFUL links related to this topic, well, especially your opinion and how best to do it.
I assume that you are trying to create a basic register/login-to-use-this-app mechanism.
Read the PHP FAQ article on password saving on why and how for secure data saving server-side. Basically, to hash (to irreversibly encrypt) sensitive data before directly saving them.
Regarding your second question,
Generally, it is not a big concern on directly transmitting sensitive data between client and server, because there can be these security measures:
Use HTTPS. This will encrypt the stream of data transmission, and it is less vulnerable to the connection being eavesdropped.
You may want to directly send the hash of the password instead of the password itself in the post request, or in other words, use the hash of the user password as the password.
Client frontend
In terms of internal storage, it is not possible to prevent other installed malicious apps from reading and using data you store, unless you (I am not familiar with this) store them in a storage that is only accessible by your own app.
Server backend
There are some servers that distribute OAuth tokens to clients, such as GitHub. However, if you only expect the server login API to be used by your own apps, OAuth isn't necessary in this case, since it is mainly used as a flexible permission bearer which you don't need to concern for your own app.
Instead, the more important thing is how you handle things server-side. For the web API that I once coded for my own server, although I don't expect others to use it, I made the API designed as if it is for the public to use, and pay attention to unexpected client input. This is because clients can be fake anytime, so never trust the integrity of what clients input. (Forgive my obsession, but I even considered backend of my JavaScript on webpages as "clients" to be safe)
I have never used nor have any comprehensive knowledge on other PHP frameworks, but when I work on my website, I would create a safety layer within my own backend code. I separate my backend into two levels, namely the database level and the interface level. The database level should try not let the interface level even get the data that are not supposed to be known by (the current authentication state of) the client, so as to minimize the chance of security vulnerability.
Client-server communication
So this only leaves the problem of data transmission, which is the main point of this question.
As mentioned above, HTTPS would be good enough to encrypt data transmission.
I do not know if this concept is practical, but after initial registration, it might be, if you are obsessive enough, possible to encrypt the data with a timestamp, etc. I am not quite sure about this, but disconnected tokens inspired me on this.
But how much protection you need still depends on what kind of data you are sending. For example, if you are simply tracking user usage, you don't really need a lot of protection for it. Just make sure that the user's original password cannot be leaked by hashing it.

PHP - Securely sending request/response between 2 servers?

Summary:
I've created an app in PHP. It's lead management system for a call center. I now need to allow a partner to be able to add new leads to the app by integrating our app with their proprietary CRM. In short, I guess I need to build an API for my app.
The easiest approach I can think of is a simple HTML post. Would this be considered too insecure? If so, what would be best approach for this type of situation?
Thanks for any help,
Andrew.
Through your quest to build an API, you'll most likely come across some of these. I'm going to outline the concepts that might come in very handy to actually build an API that is usable, and that follows open standards (which, in turn, makes it trivial for third-party to adapt existing code to interact with it).
API dispositions
The first keyword is: SSL. Don't ever think of not using it. This provides a secure socket layer on which communication can happen in a secure fashion, and consequently makes eavesdropping and MitM attacks significantly more difficult to conceive.
No matter what, do not skip on this. Certificates cost less than $60/year, so it is not exactly costly, and can save you a lot in the long run.
In terms of server techs, use what you want. Your main requirement is a webserver that can handle the four common HTTP verbs: GET, POST, PUT, DELETE. I'll explain why in a moment.
API authorisation
This one is the contentious field, as lots of people "think they have a secure way to do so". The answer is simply not true. The point of your authentication is to allow a client to easily authenticate with their credentials, but to prevent a third-party who is not privileged from doing so.
Simply adding an API key to the feed will just lead to someone eventually getting hold of it. I have seen this specific thing so many times that I strongly advise against it, especially as there are significantly easier options.
I'll go over a couple of things, labelling them as (A) or (S), respectively for Authentication and Signature. Signing is the method used to render your request tamper-proof. Authentication proves who you are.
HMAC-SHA512 signing (A) (S)
This technique is used by Amazon for all their S3/AWS APIs, and is a very lightweight method of signing and authenticating a request. I personally find it relatively ingenious.
The basic idea:
Round up all the GET and POST fields (including your public key)
Sort them alphabetically
Concatenate them using URLEncode or equivalent
Perform a HMAC hashing cipher on the data, with your private key as the key of the HMAC.
Append the result of 4 to your request.
This is simple and ingenious. What it guarantees:
You cannot change the request without knowing the private and public keys
You cannot change the key without changing the request
This neatly wraps both issues using the same HTTP request at the cost of one reserved GET/POST field. Amazon also requires the presence of a Timestamp in the request, which prevents replay attacks. Neat!
(For the reference: HMAC-ALGO = ALGO( (key XOR PAD) concat ALGO(key XOR PAD2) concat message). ALGO can be any hash cipher - SHA256 is preferred for its lightweight nature)
OAuth (A)
You've probably heard of it. the idea is simple: you get given a key and secret. This allows you to queue up for a temporary token. This token is then used to perform requests.
The main advantage of this is that lots of libraries exist to handle it, both client-side and server-side. The other advantage is that OAuth has two modes of operation: two-legged (server->server without client interaction) and three-legged (client->server->server).
The main drawback is 2 HTTP requests to get a token.
Simply sending private keys through (A)
... Leads to replay attacks. don't consider it.
A mixture of methods is a possible things. The HMAC signage is awesome when combined with OAuth, for example!
API conception
API endpoints these days follow two main standards: SOAP (XML-RPC), or REST. If you are building an endpoint to post leads, you may as well build the corresponding API to read leads and to delete them for the future.
Your API would therefore take the form:
/my/endpoint/
- GET: gets a list of leads
- POST: creates a new lead
/my/endpoint/ID/
- GET: get lead info
- PUT: modifies lead
- DELETE: deletes the lead
This allows you to future-proof your API conveniently as well.
A HTML post will suffice, that's not a problem. It would be even better if you're able to use HTTPS to ensure the transferred data is encoded, but this isn't critical.
The most common way of securing this kind of API is to provide a shared 'secret' or 'key', which is used to encode a hash. You'll then be able to verify that the request came from a trusted source, but it's up to the user to ensure that they keep the shared key a secret.
e.g. Users of your API will need to:
// build hash string to be sent with API POST request (use a sensible combination of values)
$string = sprintf('%s.%d.%d.%d', $username, $orderId, $currentTimestamp, $price);
// hash
$encodedString = sha1($string);
// concatenate with shared key
$stringWithKey = sprintf('%s.%s', $encodedString, $sharedKey); // GET KEY FROM SECURE PLACE
// hash again to get hash that will be sent with the POST request
$hash = sha1($stringWithKey);
Then you'll perform the same logic at your end from the POST values provided and verify that their hash matches the hash that you build with the user's shared key.
This is exactly what an API is for. I'd make a unique key per external account and require that API key for each $_GET or $_POST transaction that is sent to your server.
Might want to build an API management console while you're at it. Oh and don't forget the separate DB table for the API keys.
When you're done it'll be something like:
https://api.mysite.com/index.php?key=r328r93fuh3u4h409890fj34klj&other=something&another=somethingelse
You get the idea.

Implementing (secure) Api Keys in an app

I wrote a Web Application and I would like to allow other developers to get the information from it.
The server Im working on is not that awsome and cant handle that many request, so the idea is to generate and assign api keys to everyone that wants to query our information. With Api keys I can limit the daily requests and perhaps collect some statistics to see what information is really useful for the other developers.
The thing is, Im concerned about the security aspect of it. Since the Api key is going to be sent to our server (via GET/POST etc), someone could sniff the request with wireshark and get the developers API key without much effort, right?
I thought about generating a secret key and an API key. I could then instruct the other developers to concatenate them and send a hash of it to our API. I would then validate that the hash is valid and allow the request... But then the same problem would persist. A hacker could still sniff that hash and make requests on behalf of the other developer's app.
So my questions are
How can I avoid this problem?
Or better yet, Is my concern even valid? Is that a real problem?
Is there a better and secure way to allow access to my information without making it too complicated for the other developers?
What do you guys think?
I think you're trying to solve a bunch of different questions here.
If your objective is to limit the number of requests to your server, you should create a throttling mechanism. This is non-trivial, but I'd base it on IP address rather than a license key - a single licensed user might swamp your system with lots of requests. You can throttle by IP address without implementing a license mechanism.
If you want to create a licensing scheme, you need to understand cryptography etc. - it's a non-trivial problem. For instance, how do you stop a legitimate user sharing their license key with all their friends? How do you stop a hacker from stealing your key and sharing it with all of his friends?
There are a number of solutions to this - they all impose some degree of pain on your users. For instance, you can run your service on HTTPS; this stops snooping, but reduces performance. You can issue "tokens" for your service which expire after a certain number of uses; getting new tokens requires a cryptographic exchange (which might check your IP address). You might require a "challenge/response" type of logic (including an IP address validation). All these steps make life harder for your users; they probably won't thank you much for the extra work they have to do.
With respect to sniff, your problem can be solved with HTTPS on your server.
it definitely makes sense to put some authentication on the API if you want to limit access + potential some usage rate limits. If you use an API key and want to avoid sniffing then HTTPS is definitely the way to go. If that's not an option then you can also use a hash-style auth like oAuth 1.0 (http://oauth.net/core/1.0/) or Amazon AWS authentication. These work by issuing your API users with an ID and a Secret. They use the secret on the client side by inserting it into the message body, computing a hash and including the hash (not the secret) in the request. On the incoming side you compare the hash with the same operation done on the message content with their specific secret included.
This means that you can verify the sender without having to send the secret over the wire (note that the content still isn't secure - but you avoid passing the key over the wire with every request). The downside is that it's complex for developers to implement. Even if you use the oAuth 1.0 pattern which there are libraries for it's a bit of an overhead.
I work at 3scale and some of our tools might be helpful also - our systems provide API Keys, oAuth Secret sharing and also API rate limits out of the box (http://www.3scale.net and the PHP libraries are here: https://github.com/3scale/3scale_ws_api_for_php).

Categories