Introduction
Hello,
I'm that typical programmer that know how to use api, but tend to realize that I should know more about using api, raises my shoulders and keep using what I know.
I know how to troubleshoot api (even though I hate doing it) and I know that most of the time it's a really good idea to heavily validate the data being sent to my own api, in case someone else likes to send their own values instead of intended.
Question
One thing I do can't grasp though is why is it considered necessary use SSL/https on api calls between 2 sites? For instance; my site does a curl to an api on another site. There is no user nor browser between the call of these 2 sites.
Perhaps I've missed some common rule in web practice, but where's the middle-man which can joink sent information at a situation like this?
I understand that a malicious software can collect your personal data when it's sent through your browser though.
The question is basicly; why is there a need for SSL when doings calls without any private user directly invovled in the call?
Extra thoughts
If it's the case where I've missed some really big information regarding api, let me know.
Thanks for your time!
A browser/user doesn't have to be directly involved to sniff network packets. Using cURL on your web server is the same as using a browser from your home computer except for the fact that the request is coming from a different computer/network and there is no GUI. Someone can still be listening somewhere in between the computer executing cURL (client) and the server that the API resides on (server).
It's best to require SSL for API calls because APIs usually require a key that grants access to the API. If this request is sent in plain text, anyone sniffing packets in between the server and client can see this API key and start using it. On the other hand, if the API request is set via SSL it will be encrypted and much more difficult to figure out.
Related
I am developing a web application that runs on Google App Engine. It has some HTTP GET methods to request data. I do not want any random web request to be able to receive data from the server. Only my web app (i.e., requests originating from my website) plus any mobile or desktop clients I develop should be able to request data from the server. How is this done? Note I am not talking about username/password authorization here. I am asking how to make sure that the client app who is making the request is authorized. Otherwise, anyone can make their client (e.g., a C# console app) and start using my data. I think the question is similar to this one: How to authenticate client application for trust of messages sent from it
Short answer is, you can't.
https://security.stackexchange.com/questions/826/how-can-i-securely-authenticate-the-client-application-sending-me-data
Long answer is, you can make it difficult for hackers. Usually this works by embedding a key in the application, obfuscating it, and obfuscating the code for getting the key. This doesn't make it impossible for someone to find the key, just harder.
One of the stronger consumer systems out there is Microsoft's Silverlight DRM, you might want to investigate how that work: http://www.iis.net/learn/media/iis-media-services/content-protection-in-silverlight
You can use 3scale. It provides authorization , stats, control of the requests made to your GAE application
https://code.google.com/p/appspotimage/wiki/APICreationArticle
Encrypt the request via your client. Decrypt at the server level. If decryption is successful and the request is well-formed, its authorized.
Otherwise, its an unauthorized client.
The catch?
Someone will be able to make an unauthorized client after they solve your method of encryption. This would most likely be after decompiling your program and trudging through obfuscated code, making it harder/time consuming, but it is still possible.
I have an API that is serving content to a mobile app, and have no current plans to use the API for other products. I have 2 main questions:
How to prevent someone from sniffing the API requests and making their own requests (this should not be an public API).
If preventing #1 is not possible completely, then how can I limit/throttle requests from un-approved consumers? Are there other concerns here?
Using an auth token (passed as A GET param) for each request satisfies #2 (I can revoke it at anytime) however I do not want to have to update the app to use a different token in future.
Also, there is no authentication for users in the mobile app, and the API is written in PHP.
What are the best practices in this area?
Here are a couple of suggestions that can help keep your API private.
Use TLS to discourage casual packet sniffing.
Make sure your clients verify the server certificate to prevent MITM attacks.
Encrypt or obfuscate the auth token in the client code so it's not obviously exposed in something like a string dump.
Ultimately, though, if someone really wants to access your API, they will - either through reverse engineering your client code, or more complex data interception techniques. The best you can hope for is to discourage access attempts by the average user.
How to prevent someone from sniffing the API requests and making their own requests (this should not be an public API).
I would echo the previous answer that you should use TLS as a matter of course, in order to encrypt the traffic on the wire to prevent sniffing. But I would add that you also need to deter "capture-replay" attacks, whereby an attacker may resend a previous message which they may have obtained (e.g. from a client-side log) despite the usage of TLS. In this case, if you are using a nonce (meaning "number once") and/or timestamp in your requests, with HMAC signing, then the replayed API request can be detected and blocked. I have written about an example of this on my blog: http://www.soatothecloud.com/2011/02/securing-apis.html . Amazon's APIs, for example, use this approach.
If preventing #1 is not possible completely, then how can I
limit/throttle requests from un-approved consumers? Are there other
concerns here?
As well as the HMAC signing (above), you can also consider monitoring incoming IP address range, device info (e.g. headers indicating the device type - Android vs iOS etc), and other factors which can be used to link multiple requests to particular clients, and then apply policies at the API level.
Full disclosure: I work for an API Management / API Gateway vendor (Axway) but the info above should be generic.
I'm working on a Windows Phone 7 application, and to go with it I will need a web service to send out live tile push notifications. I will save the clients URI channel in a database and every hour or so I will send out the correct live tile to all the subscribed clients. I will not be sending out any sensitive data to the clients, nor do the clients send any data to the service save for their channel URI, and I've made sure to protect the database against any sql-injections.
The exposed methods are for registering and unregistering a client, as well as sending the correct live tile to a client that requests it.
Given this information, does anyone have any recommendations on how I should secure the service, or is security even needed to begin with in this case?
Thanks!
EDIT:
Thanks for the answers! My peers decided to not use any security at all though, other than purging faulty requests from the database, since the scope of the application is quite limited and no sensitive data is being transmitted. Let's hope it won't bite us in our behinds later on, eh!
Unfortunately the best solution to this problem (at the moment) is to generate a hash in your app and use that to verify the data is really coming from your app. Obviously you'll need to obfuscate tyour code if doing this.
This is the best you can do without any authentication against the backend.
If you can, have the users register and authenticate with the backend and then tie this authentication token to the ANID of the device and do everything over SSL.
Unfortunately, currenlty, security of services and prevention of spoffed requests is quite tricky with WP7 without requiring a login to the backend.
Make sure you secure your channel to your backend service with SSL. This way the data you send to the server such as a the ChannelUri will be secure.
Building a hash into your application isnt security. People could get your XAP and decompile it to get the hash.
IMHO you are better to ensure your ChannelUri (unique to your app and not "stored" in your XAP anywhere) is secured when you send it.
On the backend just make sure you purge records that fail when you try and send it a tile notification. This will get rid of any records entered by non-phone parties.
Bottom line is that you need a login infrastructure with your backend to properly ensure only valid users are using your service.
I'm currently thinking how I could protect my REST API which is used only by my mobile application from being used by other applications?
Could a API-Key be a good solution, because just me know the secret API key.
Is there a better solution?
Leon, you keep mentioning "someone else using my API with another application". So, you want to tie your API to be used only by one application? So, you don't want to give access rights to a user, you want to give them instead to an instance of your application running on the user's mobile device.
In essence: You don't trust the user!
Well, in that case you need to make sure your application is closed source, need to code your credentials into your application in such a way that nobody can retrieve them or store the credentials for it in a specially encrypted manner on the device, the decryption key for it being readable only by your application. In a way, you need to implement a form of DRM to prevent people from doing stuff with data on their mobile device. And you need to hope that nobody can reverse engineer it.
If your app becomes popular / interesting enough, count on the fact that people who are very, very good at this sort of thing will look at your application and will break your encryption before you know it. Maybe, if you put the same amount of effort into it as Skype has, maybe then you can ward them off for a while.
But ask yourself: Why bother? Why don't I trust my users? Is it really worth it to jump through hoops like this to prevent some other application from using my API?
Just lead your user through a registration process in which each app instance gets a unique key from the server (or a unique HTTP auth password) and stores that somewhere on the user's mobile device. Then, to access the interesting features in the API, require the presence of this key/password. But don't go through extreme length to obfuscate or encrypt the key when you store it locally, it's not worth it. If you every detect misuse later, you can always revoke the access rights for a particular account on the server anyway.
Use HTTP Authentication. REST is all about using the facilities available in HTTP, so the native HTTP auth should be used. With basic authentication you’ll have to use HTTPS though. If you cannot do that use HTTP digest auth or NTLM.
All of them have different strengths and weaknesses, and not every one of them might be supported by your HTTP server and client library.
I have REST services that I was planning on protecting with Windows Integrated Authentication (NTLM), as it should only be accessible to those internal to the company, and it will end up being on a website that is accessible by the public.
But, then I thought about mobile applications and I realized that Android, for example, won't be able to pass the credentials needed, so now I am stuck on how to protect it.
This is written in WCF 4.0, and my thought was to get the credentials, then determine who the user is and then check if they can use the GET request and see the data.
I don't want to force the user to pass passwords, as this will then be in the IIS log, and so is a security hole.
My present concern is for the GET request, as POST will be handled by the same method I expect.
One solution, which I don't think is a good option, would be to have them log into Sharepoint, then accept only forwarded reqests from Sharepoint.
Another approach would be to put my SSO solution in front of these services, which would then force people to log in if they don't have credentials, so the authentication would be done by SSO, and since the web service directory could be a subdirectory of the main SSO page, then I could decrypt the cookie and get the username that way, but, that would be annoying for the mobile users, which would include the senior management.
So, what is a way to secure a REST service so that it is known whom is making the request so that authorization decisions can be made, and will work for iphones, android and blackberry smartphones.
I have the same problem so let me give you the details and would also appreciate feedback. Since you are using an internal system you have one extra option that I have listed.
My first option isn't perfect, yes it could be hacked but still - better than nothing. With each request you pass the device's unique identifier along with a hash. You generate the hash using a salt embedded in the application along with the id. On the server you match the incoming hash with one you generate at the server, with the passed unique identifier. If someone "roots" their device, and is smart enough they could find the salt - you can obscure it further but ultimately it could be stolen. Also, I keep all requests on SSL to just help hide the process. My "enhancement" to this process is to pass back new salts after each request. New devices get 1 chance to obtain the next salt or get locked out ... not sure about that step yet.
Now another approach, is to have the user enter a "salt" or username and password only an internal user would know - the device obtains a token and then passes it (on SSL) with each request. Nobody outside your company could obtain that so this is probably best. I can't use this since my app is in the app store.
Hope that helps! Let us all know if you ever found a good solution.
My current solution, in order to protect data in the system, is to force people to first log in to the application that the REST services support (our learning management system), as I have written an SSO solution that will write out a cookie with encrypted data.
Then, the REST service will look for that cookie, which disappears when you close the browser, and I don't care if the cookie is expired, I just need the username from it, then I can look in a config file to see if that user is allowed to use that REST service.
This isn't ideal, and what I want to do is redirect through the SSO code, and have it then send the person back to the REST service, but that is not as simple as I hoped.
My SSO code has lots of redirects, and will redirect someone to a spot they pick in the learning management system, I just need to get it to work with the other application.