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?
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.
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!
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.
There are a wide array of things you can do to add security to your service. Check this out
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.
Related
I try to wrap my head around how to really secure ajax calls of any kind that are publicly available.
Let’s say the JavaScript on a public page (so no user authentication of any kind) contains an AJAX call to a PHP script (REST API or just a script, it doesn’t matter) that does a lot of heavy lifting. So any user can just look into the source code, find the AJAX call, rebuild and execute it, and execute it again a million times in a second and DDoS your site that way - not so great. At first I thought a HTTP_REFERER check could be helpful, but as any header field, also this is manipulable (just use a curl request) so the gain of security wouldn’t be too high.
The next approach was about a combination of using session ids, cookies, etc. to build some kind of access key for every page viewer and when someone exceeds the limit the AJAX call would run into an error. Sounds great so far, but just by cleaning the cookies, etc. everything will be reseted. So also no real solution. But, of course! Use the IP! Great idea! Users in public networks, that use only one IP for internet access will be totally happy, if one miscreant will block the service for all of them by abusing the call... not. So, also no great solution.
So, I’m really stuck here and can’t think of any great answer for my problem.
I also thought about API keys, or something alike. But that is an information that is also extractable from the JavaScript source. So how to prevent other servers using your service in a proxy kind of manner serving your data to their users? (e.g. you implemented the GMaps API in your website (or any other API) and someone uses your script accessing the API with your key)
tl;dr
Is there any good way to really secure your publicly viewable AJAX calls from abusing them for DDoSing your site, presenting your data on other sites, etc.
I think you're overthinking what AJAX is. When your site makes an ajax request, server side, it's the same as any other page request (even if some scripts are more process intensive). You need to protect your entire site, and not just specific scripts. If your server does not have any DDoS protection, it can be attacked through any page. Look into services like CloudFare
As #Sage Mentioned it is similar to normal http request. You can use normal authentication as the http headers/cookie information will be passed on to the server every time you make ajax call. For clear view you can look into developer console on browser. Its the same as exposing you website root url. Just make sure you have authentications checks for ajax calls too.
I am new to the REST world. I am writing an ASP.NET MVC application. My requirement is to make a few REST calls from the client. I can either choose to make these REST calls from Javascript or I can do that in the C# code in the Controller. Which method is recommended? According to my understanding, the Controller runs on the Web Server and the Javascript runs on the browser. So is there any perf degradation if the REST calls are made from the Web Server.
Can someone suggest me the general practice around this? Are there any security gotchas for the same?
Thanks
Let us consider the pros and cons of doing this Server side
PROs:
You can do other processing on the data using the power of the server
You are not subject to cross domain limitations like you would be in ajax
Generally you do not have to worry about your server being able to access the resource, whereas on client you are at the mercy of users net restrictions, firewalls etc
More control over your http response\request lifecycle
CONS:
You will have to consume more bandwidth sending the resulting data down to the client.
You may have to do more work to leverage good caching practices
Dependant on having certain server side libraries\framework elements
Now although we have a much bigger list of Pros than cons... in the majority of cases you will still want to do this on the client... because the issue of double handling the data is actually a very big one, and will cost you both time and money.
The only reason you should actually do it server side is if you need to do extensive processing on the data, or you cannot circumvent CORS (cross domain) restrictions.
If you are just doing something simple like displaying the information on a webpage, then client side is preferable.
It strongly depends on your situation. If you simple display this data in your page without any actions, you can get it from javascript. If you want to work with this data, transform it, join it with other data or else, i recommend do this operations on server so get this data on server too.
I have an API (1) on which I have build an web application with its own AJAX API (2). The reason for this is not to expose the source API.
However, the web application uses AJAX (through JQuery) go get new data from its AJAX API, the data retrieved is currently in XML.
Lately I have secured the main API (1) with an authorization algorithm. However, I would like to secure the web application as well so it cannot be parsed. Currently it is being parsed to get the hash used to call the AJAX API, which returns XML.
My question: How can I improve the security and decrease the possibility of others able to parse my web application.
The only ideas I have are: stop sending XML, but send HTML instead. Use flash (yet, this is not an option).
I understand that since the site is public, and no login can be implemented, it can be hard to refuse access to bots (non legitimate users). Also, Flash is not an option... it never is ;)
edit
The Web Application I am referring to: https://bikemap.appified.net/
This is somewhat of an odd request; you wish to lock down a system that your own web application depends on to work. This is almost always a recipe for disaster.
Web applications should always expect to be sidelined, so the real security must come from the server; tarpitting, session tokens, throttling, etc.
If that's already in place, I don't see any reason why should jump through hoops in your own web application to give robots a tougher time ... unless you really want to separate humans from robots ;-)
One way to reduce the refactoring pain on your side is to wrap the $.ajax function in a piece of code that could sign the outgoing requests (or somehow add fields to it) ... then minify / obscurify that code and hope it won't get decoded so fast.
I'm doing some codeacadamy courses at the moment. It's a great service, highly recommended.
I've noticed they use some tracking. They use ajax posts to send user information to their tracking provider.
http://track.segment.io/
It sends some json -
{"data":{},"newId":"myemail.emailn#gmail.com","api_key":"sfdsdkjf","user_id":"myemail.email#gmail.com","callbackId":111,"attributes":{"firstSeen":"2012-02-15T17:28:23.978Z","lastSeen":"2012-02-15T17:28:23.978Z","temp":false},"context":{"timestamp":"2012-02-15T17:28:23.979Z","visit":{"id":"asfsaasfsa","start":"2012-02-15T15:23:11.000Z","end":"2012-02-15T17:28:23.978Z"}}}
You'll notice that as I've not set my user name it uses my email as a reference to who I am. this seems like bad practice to me, but I'm unsure why.
My question is -
Should they be sending this info over https? I thought any personal info should always be sent over https, but I don't really understand why. Is there a security risk here?
You're right, they should be sending personal info over https, since it is a secure connection which uses SSL.
That means that who ever is on your network can not (or, well, it will be very hard for him) to get the data of your requests.
Without the use of SSL, anyone who is sharing your network can in fact see all of the data you are sending/receiving.
Unfortunately, there's no way to enforce that.
Yes and no. There are always the possibility of man in the middle attacks. But you have to ask yourself... Is my email and API key really so dangerous in the hands of another person? This really goes into risk assessment of a project and calculating risk managment.
If the company feels like disclosure of these credentials cant be used to escalate an attack, then that's why this information is less secured. However, if there is a possibility of escalation, you are never going to know unless you yourself try haha.
You are correct that sending HTTP POSTS with a JSON payload is not as secure as using HTTPS. However, this is no more or less secure than any other HTTP communication that contains your personal information.
For example, if your email address was in a table on a normal HTML page on the server:
<table>
<tr><td>Email:</td><td>myemail.emailn#gmail.com</td></tr>
</table>
...then this would be just as much of a problem as the AJAX method.
It boils down to the requirements of the site. If you're doing something like online banking, HTTPS is a must. However, I doubt you have to worry about hackers intercepting HTTP traffic when you're using a site such as Code Aadamy, and HTTPS comes at a cost as well.
Currently I have developed a site which is used for handle financial transactions. I have seen that some of my customers have done JavaScript injection attacks and have done some transactions which are not possible. As a example I have checked his cash balance before he place the order. But some of them did change that by running the following javascript in the address bar. They have taken the varible name by looking in to page source.
javascript:void(document.accounts.cashBalence.value="10000000")
Since this is critical I want to fixed it quickly. So is there a way to prevent JavaScript injection attacks?
You can obfuscate or hash variable names and/or values. However,
Don't use JavaScript, do every logic in the server-side instead.
In the end it's not even a problem of Javascript. Your server talks to the outside world using HTTP. It sends data using HTTP and receives data using HTTP. Anybody can request data from it using HTTP and anybody can send data to it using HTTP.
Think about this again:
Anybody can send data to your server through the very simple protocol that is HTTP.
The HTML and Javascript you're sending to people's browsers is just a nice help, an interface, to allow them to easily send data to your server. They could do the same using the curl command on their command line or by telnet'ing into port 80 and talk really low-level to it.
If your server blindly obeys any and all commands sent to it without checking their validity, you have no security whatsoever. Security and validity checks belong on the server, not on the client side interface. Because HTML and Javascript aren't the only interface to your server, nor are they in any way protectable and hence trustworthy.
Javascript runs in the user's browser. You ultimately have no control over it and should not trust it. Any verification you do in the browser is merely for the user's convenience so they can be alerted of problems as early as possible.
The backend code that accepts the order should do the authoritative check of the user's balance.
No client-side scripting (including Javascript) is good for verification, It should all be done on the server-side.
It is too unreliable to trust it specially if it is for financial records!!
It should be used for a better "user experience". Form validation while typing or whatever but not this!
Have found that if you make it to where server only excepts out going data not incoming data it works best but that poses a problem, if you are using a website that takes user input on the connected client then your preaty much screwed I sugset a simple java script line that in a sence makes it to where before you can send any java script you have to enter a basic set of variables so in a sence just have a login page start with somthing like this
System.out.printin ("Welcome, Would you like to login to edit?")
Then { System.in = "Yes"}
To prevent Javascript injection, you should have a Validation Feature whenever you allow your user to enter something. Try to use libraries that determine Javascript scripts that are entered to the form.
Also when displaying user inputs, you should Escape Texts to display it as is and will not be evaluated by the browser.
Utilize your server, your should place your business logic to the server and not to the client whether using Javascript or not. All data sent to the client are just view and should not process any business logic.