0

I'm going to build 2 Web API projects that will be used in other web/mobile site projects across our company.

  • Web API are public facing
  • No SSL
  • Can be used in jquery ajax calls
  • Data itself is not private/sensitive data.

The Web API calls will be used on high traffic sites on front page [eg. to populate drop down list on homepage]

So I want some kind of mechanism to restrict Web API calls only for our company projects or at least prohibit somebody using my public Web API to create their site or any kind of attacks [like replay].

Here are few ways I thought of

  1. Make all Web API calls accessible only within Intranet [only access Web APIs through server side code]. That would make me lose the convenience of accessing it through ajax.
  2. Use username password in every request, but our sites wont use HTTPS. So it defeats the purpose
  3. Thought of using Nonce, but what happens when Nonce expires on my public facing pages? I should somehow refresh the page? I cannot ask user to do something, as the page is not user authenticated.
  4. Use OAuth to authenticate. It looks so complicated and would require authentication on every request and I'm afraid it would hit performance [as our sites will be high traffic]
  5. Just use uniqueID, and check the domain its coming from. Hoping, nothing major will happen

I'm thinking of going with 5. Please tell me your suggestions. Thanks in advance.

EDIT Our sites are not https, and only ReadOnly requests. My main concern is the performance. I do not want complicated security steps to slow down our Public WebAPI, as this will be called by many web projects within our company.

Nathan
  • 137
  • 3
  • 14

2 Answers2

2

Disclaimer - Do your own research (and probably wait for a couple more answers), I am no security expert, this is simply what I thought of in a few minutes.

Plan on this being an open api

Honestly it's damn hard to secure stuff, you can make your best effort attempt but really you're talking about letting anyone access an api via javascript, you don't have much chance in securing it completely. Every decision you make when making this api should be based on the idea that anyone can access it, do not send any private data unless you implement a real authentication scheme (eg not a custom one).

If your data isn't that important, then it shouldn't matter if it isn't secured all that well.

The next person who works on this may find the easiest way to get the functionality done, a lot of security vulnerabilities come through updating systems when you don't fully understand the original plan.

Token Based Authentication

Each site that is allowed your use your api inserts a unique id (guid) into a database with an origin site, client ip and expiry date. Depending on the lifecycle of your pages this could probably expire fairly quickly, but will be more expensive to do.

When javascript accesses your api they pass this token along, you api simply checks the token vs the ip in the database and ensures it hasn't expired.

It would be even better if you could use some standard form of auth, potentially using encrypted cookies like ASP.NET. I don't believe this is possible if you're cross domain though.

Checking the IP should help prevent a man in the middle attack where another site tries to allow users to use your api, it won't prevent them from using it directly themselves and doing whatever they like with the information.

You could try rate limit your api to prevent other sites using it to serve information to their users. This could be done by simply limiting how often you give out tokens and how many requests each token is allowed to make.

CORS

http://en.wikipedia.org/wiki/Cross-origin_resource_sharing

Because you may be using cross domain ajax calls you probably need to look into something called CORS. This will allow compatible browsers to make cross domain requests, for ones that don't support it you likely need to fall back to jsonp. This should also help eliminate cross-site scripting attacks in browsers that support it. AFAIK this is a browser technology, not a server one (apart from the http header), so again this won't prevent any client that doesn't play nice with this rule, but it can help protect your users.

Protection against CSRF

https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)

If you allow updating of any data, then I highly recommend looking into using a cross site request antiforgery mechanism. Maybe a token like MVC provides, where you give the a unique value in a cookie (from the api), and also require them to pass the value back in any post they make to the api. It's very simple to implement on both the server and client, and the server should not need to store anything in session to do this meaning it will work as long as the cookie is alive. This makes it very hard for a malicious party to make anyone else perform a request to your api. If you are doing any postbacks using forms instead of ajax you will need to ensure the token is added to your postback values. Remember this is not an authentication method, but one to try prevent CSRF.

You may be able to combine this with the authentication token, but again because it relies on sending cookies this probably isn't possible.

DOS Attacks

Also Try ensure the api methods aren't expensive, to help stop DOS attacks using a lot of cpu time. Of course if someone really wants to take down your site they can probably still do so, your job is to try limit their avenues.

Betty
  • 9,109
  • 2
  • 34
  • 48
  • I like the "Protection against CSRF" idea. Please explain how would I pass cookie "(from the api)"? my WebAPI is a separate application, and my Project1 is a separate web application. – Nathan Oct 03 '12 at 18:48
  • The CSRF cookie would only be for the web api domain, it would act just like a normal cookie, the web application shouldn't need to touch it. http://stackoverflow.com/questions/9793591/how-do-i-set-a-reponse-cookie-on-httpreponsemessage – Betty Oct 04 '12 at 04:14
0

If you're still looking, what you need is a lightweight message authentication method that will verify the authenticity of the message. Using a hash key in a fairly lightweight but still secure algorithm like SHA-1 you can compute a hash value for every request that you'll always authenticate on the server side before honouring the request. Avoid MAC-ing with constant bits of data like server or hostname. Instead, Use a component of the data being sent so that if it's modified in transit, validation fails. See this answer for the step-by-step

Number 5 is an Okay solution, but I always strongly caution against solutions that depend on the goodness and mercy of the web client to your application/api. Most people out there just want to hurt your app and will forge anything, including the host/referer http header with minimum effort.

Community
  • 1
  • 1
kolossus
  • 20,559
  • 3
  • 52
  • 104