6

I have http://example.com/index.html, which from within the HTML uses JavaScript (XmlHttpRequest) to call a web services at http://example.com/json/?a=...&b=...

The web service returns to index.html a JSON array of information to then be displayed on index.html.

Since anyone can view the source code for index.html and see how I'm calling the JSON web service (http://example.com/json/), how do I prevent people from calling my JSON web service directly?

Since the web service is essentially an open read into my database, I don't want people to abuse the web service and start fetching data directly from the web service, start DoS my server, fetching more information than they should, etc..

UPDATE:

Is there no way to limit requests for http://example.com/json/ to only come from the same server (IP) and URL request of http://example.com/index.html?

Meaning, can't http://example.com/json/ detect that the Requester is ($_SERVER['REQUEST_URI'] == http://example.com/index.html) and only allow that?

Hank
  • 1,151
  • 2
  • 10
  • 9
  • 2
    Umm, hello? This is exactly your question that we're already answering over here: http://stackoverflow.com/questions/2576734/how-to-prevent-direct-access-to-my-json-service – Matchu Apr 05 '10 at 13:46
  • @Matchu, it's similar but not the same (as even noted by Joshua Smith's comment on the linked StackOverflow post) – Hank Apr 05 '10 at 13:52
  • "How to prevent direct access to my JSON service" == "how do I prevent people from calling my JSON web service directly?". I did note that this time you gave the rationale, which means we can actually give you reasonable alternative solutions, but it's still the same question. – Matchu Apr 05 '10 at 13:58
  • `$_SERVER['HTTP_REFERRER']` is what you are looking for, but it's useless for preventing DoS since it can be easily faked. Same applies for `X-Requested-With` header as I wrote below. It's important to understand that every countermeasure relying on **client side** operation can always be circumvented, since client can be never trusted. – jholster Apr 05 '10 at 15:38
  • By using one-time token (CSRF protection) you can force the user to load your index.html (or whatever) before accessing JSON url, but again, it does **not** prevent DoS. – jholster Apr 05 '10 at 15:40
  • If the service is called from Index.html, isn't the request made from browser's context? So ultimately the request contains host header address of the user's browser(can be any IP address). Right? – Arnab May 14 '18 at 19:34

5 Answers5

4

There are no easy way to prevent that. If your service isn't extremely popular and thus being likely target for denial of service attacks, I wouldn't bother.

One thing which came into my mind is using disposable tokens (valid for 10 or 100 requests).

Other (naive) approach is checking that X-Requested-With header exists in request, but of course that can be easily faked. So, my advice is: do nothing unless the problem is real.

One more idea: hash calc. The idea is to require client performing rather expensive calculation per every request, while validating the calculation in server side is cheap. For a single request the overhead is very small, but say for 1000 requests it may take significant amount of CPU time. I have no idea if hashcalc has been used to prevent DoS'ing web services. Some years ago it was proposed as antispam measure, but never became popular.

jholster
  • 5,066
  • 1
  • 27
  • 20
  • How would a disposable token work and be generated from an index.html file? – Hank Apr 05 '10 at 14:15
  • Well, the attacker could anyway re-fetch index.html to get new token, so neither is that very efficient countermeasure, unless you limit how many tokens are generated per minute per ip etc. – jholster Apr 05 '10 at 14:47
  • Related to HTTP_X_REQUESTED_WITH, I don't believe that's available in all languages ... e.g. PHP – Hank Apr 05 '10 at 15:40
  • In PHP you can access it via $_SERVER['HTTP_X_REQUESTED_WITH']. It won't stop real attackers, but prevents fetching the JSON by copy-pasting URL into browser's address field. – jholster Apr 05 '10 at 15:47
1

I would keep track of the IP addresses making the requests. If you ever saw a large number of requests coming from the same IP, you could block it or offer a CAPTCHA.

machineboy2045
  • 349
  • 4
  • 4
1

Answer is really simple, use CSRF protection. http://en.wikipedia.org/wiki/Cross-site_request_forgery

Simply, when user comes to your site (index.php), put in session: CSRF=(RANDOM_HASH)

Ask for JSON request, example.com/json.php?hash=$_SESSION['CSRF']

And in json.php check if $_GET['hash'] matches $_SESSION['CSRF']

Simple as that... It's Server-Side solution!

confiq
  • 2,795
  • 1
  • 26
  • 43
  • 5
    The idea is to prevent an attacker from accessing the services directly. Your approach won't solve that. The attacker will just access index.html, gets the token and thereafter makes the call to the service directly to get whatever information he wants. – Sripathi Krishnan Apr 05 '10 at 14:35
  • I assume this would be a one-time token. How can I do this without needing index.php, can I do this just with index.html? – Hank Apr 05 '10 at 14:49
  • File suffix doesn't matter, but CSRF requires "dynamic" pages, i.e. cannot be done with static files. – jholster Apr 05 '10 at 15:04
  • Of course it can't be done with static files and it's not ideal protection. However it will help restricting the server. As said before me, there are no easy way to prevent that... – confiq Apr 05 '10 at 17:29
0

There are a wide array of things you can do to add security to your service. Check this out

Jason
  • 2,503
  • 3
  • 38
  • 46
0

You can't properly secure a web-service that is callable from client-side javascript.

You can try security through obscurity techniques like javascript obfuscation, but it won't stop someone motivated.

rogeriopvl
  • 51,659
  • 8
  • 55
  • 58