Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to secure Ajax link requests?

Imagine the next scenario: a user wants to register to a webpage and fills a form. While he is filling the form, jQuery keeps checking through a regular expression if fields are valid, etc...

Taking the email as the primary key which the user will use after registering to login, the email field needs to be checked with Ajax to let the user know if that email is registered or not. I want to check it with Ajax to avoid sending the full form and emptying it, refreshing page, etc...

So, when the user has ended filling the email field, the Ajax request is sent to the server, something like the next link:

example.com/[email protected] 

When check.php receives the email, it asks the database if it exists or not and returns a message like: User already exists if user exists or null if user does not exist.

The question is: if someone digs through my .js and finds out links similar to that, they could use that link to send a large number of requests to find out if those random emails exist. This could lead to heavy use of the database or in the worst cases even crashing and private information leaks.

Someone could do a huge for loop to check emails like:

//Getting the response of the next links example.com/[email protected] // Returns null example.com/[email protected] // Returns null example.com/[email protected] // Returns null example.com/[email protected] // Returns User already exists 

------------------------------------------------------------------------------------------------------------------------------------

Since i last accepted the answer, i kept investigating this and found the solution to avoid this behaviour. The following code is for JAVA but the logic can be applied to any other server-side language.

Before doing ANY ajax request to the server, I request a token to the server. This token looks like this fmf5p81m6e56n4va3nkfu2ns8n it is made by a simple method, it can, however, be more complex, but this is good to go.

public String getToken() throws UnsupportedEncodingException {     return new BigInteger(130, new SecureRandom()).toString(32); } 

When requesting the token, the server does not only return the token, but also a small script that in case someone uses browser to inspect element (and browser navbar) and such the script will run and the token will be cleared. Servlet returns something like this:

_html += "<head>"     + "<script> "     + "window.onload=function(){\n"     + "       document.body.innerHTML = \"\";\n"     + "    }"     + "window.location.href='http://mywebsite.com' "     + "</script>"     + "</head>"     + "<body>"     + "[" + token+ "]"     + "</body>"     + "</html>"; 

First empties the body then navigates back to wherever we want. javascript/jquery will however, catch the entire content as string, then I simply extract the string between [ and ]. This token is only available for the next request, so every AJAX request will have its unique token. On the 2nd reques the token just used is deleted.

After I get the token I append it as parameter to whatever link i request, something like this:

ajaxRequestObjet = $.ajax({     url: "http://localhost:8084/mywebsite.com/servlet", //<-- local tomcat server     method: "POST",     data: "type=AJAX&page=some-article&token=fmf5p81m6e56n4va3nkfu2ns8n" }); 

This method works fine against someone who inspects the website manually and try to use the links, but what about java/php/IIS servers that do this automaticly?

For this ask for header! Something like this:

boolean isAjax = "XMLHttpRequest".equals(request.getHeader("X-Requested-With"));  

It will be true only and only if XMLHttpRequest exists....

There is one last thing to keep in mind. Make sure 'Access-Control-Allow-Origin' header is NOT present in your app to make sure that any javascript NOT in your server wont get the server resources. If this header does not exist, chrome will return this:

XMLHttpRequest cannot load http://localhost:8084/mywebsite.com/servlet. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost' is therefore not allowed access. 

Java server was in tomcat and I had another apache for this tests, this is the small html present in apache which gave the error above:

<html> <head>     <script src="http://code.jquery.com/jquery-latest.min.js" type="text/javascript"></script>      <script>     ajaxRequestObjet = $.ajax({         url: "http://localhost:8084/mywebsite.com/servlet",         method: "POST",         data: "type=AJAX&page=Token"     });      ajaxRequestObjet.done(function (msg) {          alert(msg);     });      </script>  </head> <body> </body> </html> 
like image 424
Alpha2k Avatar asked Apr 24 '15 08:04

Alpha2k


People also ask

How can I make AJAX request secure?

There are some methods to secure AJAX calls and I give you a simple solution. This one use php session where a random key is generated and saved in session, then used in AJAX request to validate call request. The new url endpoint is http://www.myapp.ext/ajax/myplugin?skey=<Random key> .

Are AJAX requests safe?

If you're worried about the user attacking your web page content and the AJAX code in it and discovering something in the page that you didn't want them to know, then it is true that AJAX is insecure, since the user has physical access to the environment that the web page runs in.

What are the security issues with AJAX?

The Ajax calls are sent in plain text format, this might lead to insecure database access. The data gets stored on the clients browser, thus making the data available to anyone. It also allows monitoring browsing sessions by inserting scripts.

Are AJAX requests HTTP requests?

Ajax. Ajax is the traditional way to make an asynchronous HTTP request. Data can be sent using the HTTP POST method and received using the HTTP GET method. To make an HTTP call in Ajax, you need to initialize a new XMLHttpRequest() method, specify the URL endpoint and HTTP method (in this case GET).


2 Answers

While you can not control this 100%... there are a few options..

Try using the same methods that people use with Captcha scripts..

Basically when the user loads the form / page.. You generate a random string/id in their PHP session and store it.. When they send the ajax requests, have your ajax check also append the string/id and require it before allowing a check to perform else return a header of 500 or something..

Using this approach with sessions, you could set a allowed limit of checks (say 5) and once the user has tried more than 5 checks, They are required to reload the page or perform a human check (eg Captcha).. Then it resets their count.. Even allow a total of say 30 within 1 hour / per IP or something.

Also use smart events to trigger when the ajax check is done, eg field/tab change or on a button press.. Or when a valid email is detected.. but say .com.au would trigger twice.

Basically this way, even if someone sniffed your JS files and tried to automate the email checker.. It would require them finding a way to append the string/id that you generate and also limit their amount of requests performed.

Beyond this, there is not to much more you can do easily.. But there are still a few other idea's.

Most of them would work around using a PHP session / cookie.. Say for example if they check and find 3 email addresses.. Then again you set that as a limit and force them to require a manual submission or something.

See how the above suggestion goes for you, any questions do feel free to ask. But may take me a day or two to reply as weekend.. Also research how Captcha scripts work as plenty of source code for them.. As they work on the same idea.

Time Delays will simply look bad / make your site appear slow / bug the user with waiting for a response.

You need to limit the amount of look up's per session / ip address.. Otherwise there is always a way to get past these checks.. Basically once they hit a limit.. Force the user/ip/session to wait a few minutes/hours and verify them with a Captcha script so it can not be scripted...

Javascript Security / Hiding The Source

While you can not do this truly, you can do certain things generate the JS using a PHP page with a JS header.. so <script src='myjscode.php'></script> and this allows PHP to check for a valid session.. So stops external requests to an extent.. But this is mostly useful for allowing JS to be only available behind a membership/login..

Multiple Checks / If Possible In This Case

Depending on your approach, is this for a user to check if they already have an account? If so.. you could combine the email check with something like their name/country/age/dob ... So they would need to select two or three correct matching values before being able to get a check/response from the ajax call?

Maybe not in your case, but just thought would add this as well.

like image 163
Angry 84 Avatar answered Oct 05 '22 23:10

Angry 84


The JavaScript code on your website is executed on the computer of the user, so there is no way you could stop him from digging through your code. Even if you use a code obfuscator (for example, https://www.javascriptobfuscator.com/), the hacker could debug your application and record all requests send to the server.

Everything security-relevant has to happen on the server. You could limit the amount of requests from a specific IP address.

like image 36
Johannes Reuter Avatar answered Oct 05 '22 22:10

Johannes Reuter