Send CSRF token to javascript - php

Suppose I maintain a anti CSRF token at server side in a session
How am I supposed to pass the token to client side application if my form generation is going to be dynamic(i.e. form will be created after some action has been performed by javascript)
Is there a way to pass the token to javascript so that I can inject the token in the form.
One working way that I found is send a cookie to the browser containing the token which will be then extracted by javascript.
Any suggestions?

I would suggest starting out from a secure token, and then improving it through JavaScript according to dynamic form Creation.
Eg, like:
<input type="hidden" name="csrftoken" value="hgdillksdbgjksdbkvbskb">
Where the "value" parameter is generated on server-side when page loads.
And then you have a script like:
csrftoken = document.mainform.csrftoken.value;
# Do something with the CSRF token, like add dynamic values, like sha256(csrftoken + "dynamicvalue");
document.mainform.csrftoken.value = csrftoken;
The main idea of this, is to prevent, that even if they manage to get a exploit that would allow a adverisary to read the JavaScript code, they still cannot make up a valid CSRF token, since they cannot read the original "csrftoken" value that was inside the form at page load.
This can also be used to "chain" AJAX requests, like that you start out with the token X during page load. Then you transform it to Y using JavaScript, send it in a AJAX request. In the next AJAX request, you can use Y as base in the algoritm, to create Z, and send to the server. A attacker cannot gain access to X, thus they cannot either get access to Y neither Z, even if they would in some way be able to exploit running JavaScript code to reveal itself.
Note that page contents cannot be read by a adversiary due to Same origin policy. But Javascript can contain exploits that would make it possible to read the actual running JavaScript code. Theres no such exploits currently, but better be safe than sorry.

Sure. If you're dynamically generating the form on the client side then you're doing it from some kind of template. The token should be an argument to that creation function.
Pass the token along to the client at request/render time and then inject it into the form as a hidden element at form generation time.

Related

Preventing CSRF with tokens in a AJAX based application

I'm using tokens to prevent CSRF attacks in my application. But this application is single page and heavily AJAX based, so I need to find a way to provide a valid token for N actions in a single page:
e.g. A document fragment loads with 3 possible actions, each action needs a token to work properly but server side has just one valid token at time...
Since each token is just a encrypted nonce (the value isn't based in a specific form), I came with the idea of automatize the token assignation for each action with something like this:
The App intercepts an AJAX call, and check if it's a sensitive action (i.e. delete a user)
A token is requested to the server before the action proceed
The token is generated and then added to the action request
The action in executed since the request included a valid token
Do the same for any subsequent actions executed via AJAX
I believe that method isn't effective enough because the attacker can use a script that does exactly the same my App does (retrieve token and append to the request).
How can I improve my method to be effective against CSRF attacks?
Additional info: My backend environment is PHP/Phalcon and the tokens are generated using Phalcon.
A simpler method than using tokens for an AJAX only might be to check headers that can only be present in an AJAX request from your own domain.
Two options are:
Checking the Origin Header
Checking the X-Requested-With header
The Origin header can also be used for normal HTML form submissions, and you would verify that this contains the URL of your own site before the form submission does its processing.
If you decide to check the X-Requested-With header, you will need to make sure it is added to each AJAX request client side (JQuery will do this by default). As this header cannot be sent cross domain (without your server's consent to the browser first), checking that this is present and set to your own value (e.g. "XMLHttpRequest") will verify that the request is not a CSRF attack.
I had to deal with something similar awhile ago. Requesting nonces with ajax is a super bad idea – IMHO, it invalidates the whole point of having them if the attacker can simply generate it without reloading the page. I ended up implementing the following:
Nonce module (the brain of the operation) that handles creation, destruction, validation and hierarchy of nonces (e.g., child nonces for one page with multiple inputs).
Whenever a form / certain input is rendered, nonce is generated and stored in a session with expire timestamp.
When the user is done with an action / form / page, the nonce with it's hierarchy is destroyed. Request may return a new nonce if the action is repetitive.
Upon generating a new nonce old ones are checked and expired ones are removed.
The major trouble with it is deciding when the nonce expires and cleaning them up, because they grow like bacteria on steroids. You don't want a user to submit a form that was open for an hour and get stuck because the nonce is expired / deleted. In those situations you can return 'time out, please try again' message with the regenerated nonce, so upon the following request everything would pass.
As already suggested, nothing is 100% bullet proof and in most cases is an overkill. I think this approach is a good balance between being paranoid and not wasting days of time on it. Did it help me a lot? It did more with being paranoid about it compared to improving the security dramatically.
Logically thinking, the best thing you could do in those situations is to analyse the behaviour behind the requests and time them out if they get suspicious. For example, 20 requests per minute from one ip, track mouse / keyboard, make sure they are active between the requests. In other words ensure that requests are not automated, instead of ensuring they come with valid nonces.

Disallowing PHP file to be accessed directly

I have an html form which when it gets submitted it calls a JavaScript function which by using Ajax gets information from a PHP file using post and displays it back to the page.
The question is, is it possible to make the PHP file only accessible when using the above method instead of users being able to access it directly if they go through the JS method and find it's location?
Edit: Adding a bit more information to help people out. Ajax is calling an external php file in order to update the contents of the website based on what the php file returns. Since all the Ajax calls are made in the JavaScript someone can easily find out the location and the arguments the function is using and basically call the php file directly, which is what I'm trying to avoid.
Using PHP sessions is a bit hard in this case, since I'm using Ajax I can't destroy the session once the external PHP file is done since if I do the session never renews because I'm using Ajax to update the content of the website without refreshing it.
I agree with limscoder.
Here is how I use tokens on submitting forms.
1) initialize it and save it on server (when the page is loaded on the client side)
$token = $_SESSION['token'] = md5(uniqid(mt_rand(),true));
2) add it to the form
<input type="hidden" name="token" value="<?php echo $token;?>" />
3) when submitted I check the token using
if(isset($_SESSION['token'], $_POST['token']) && $_SESSION['token'] == $_POST['token'])
{
//code goes here
}
It sounds like you're describing a type of cross site request forgery. The normal way of preventing this is by including a server generated token as a form value, and then validating it against a value stored in the user's session when the form is submitted. Check out the link for instructions on how to properly generate and validate the token.
You can test what page called your script by checking the HTTP_REFERER (http://php.net/manual/en/reserved.variables.server.php)
BUT...it can be spoofed, so will only discourage casual attempts at getting to your data
Is the html page secured? If anyone can just access the html page to call your ajax page, why bother to spend time trying to secure it. :)
However if you really need to do so, you might need to convert the html page to a php page so that you can generate a token to be placed in the form. A good token would be the sha of a secret string appended with the year, month, day and hour. When the token is sent back, use the same way to generate a test token and compare the two. This makes the token valid only for 1 hour. Of cause, in the ajax, you might need to test against last hour's token, in case the user got the form at the last minute of the hour and submits after the hour.
Edit---
If your main concern are bots then just use a captcha test.

How to protect against cross domain http requests? (server side)

I've read some questions on SO about denying cross domain requests but all just state to rely on the client side protection ( same origin policy ) . Are there any layers of protection that can be done server side ? Should i rely on header- origin , header - referer ? Some say header referer get's modified by some anti-spyware programs . Some say ff doesint include origin header option (but it does) , some say chrome doesnt and so on :) .
I know headers can be modified (referer can be modified even with setrequestheader method) , but , if you ever done any protection server side for this matter please share any ideeas .
P.S. : A possibility would be to tokenise each request (all type of requests , requests that only get data , requests that change data on server etc ) but that would be a pain in the ass ...
P.P.S. : omg don't spam about synchroniser token pattern ... as i said in the firs P.S. yea that would be a solution , any other ideeas?
Mayor question is against which kind of attacks you want protect?
If you want protect against CSRF, then you need process form with random security token.
Like
<input type="hidden" name="token" value="random value generated on server side for each request" />
After form will submitted you need compare token from request and token stored in session on server side.
If you want deny load some kind of resources from other domains (like loading images or scripts on evil.com from you server), then you can add to each resource similar token.
Like
<img src="/images/mysuperimg.png?token=<token>" />
etc.
I suppose you have heard of CSRF?
here's an overview CSRF works and how it's prevented:
anyone can request a page from your site, the same way anyone can also POST on your site. let's say you have a registration form. one can copy your form, and put in any HTML page, remove the JS validations, and spam you infinitely. sounds like a threat right?
however, you can prevent this by using a session id. this is a unique string (usually MD5 or SHA-1), that is stored on a session variable in PHP before rendering the page. this session id is also rendered in a hidden input form on your form. now when the form is submitted, PHP checks if that session id sent with the form is a match with a the session id stored in the session variable. if it's valid, you proceed, and the one stored in the server is nullified so that it wont be reused.
also, if a certain time has elapsed, that session id should expire. so lets say if a user has lingered on a form for more than your 15 min expiry. using that form will be invalid. you'd have to refresh the page to get a new session id
now you might ask how to use this on page requests rather than forms?
i know of 2 ways to send over session ids to the server, and that is either by cookie or via appending your sessionid in the url.
for cookie, it works the same way. if your page is generated by your server, the page creates the session id on your server and sends a copy as a cookie. the next page request, you read the cookie of the request, get it's session id, compare with the one on the server, and if equal, request is valid, you proceed. otherwise, it's invalid.
for those who have disabled cookies, you can append the sessionid in the url of every link you have on the page. notice that on some sites, they have a url parameter of sid, or sessid and so on? that's how they pass it. every link in your page will be appended this id. and upon clicking the link, all the server does is get that session id from the url, and compare it with the server.
quite long answer :D

How to prevent POST requests from ajax (obtained through firebug)

How would I prevent users from spamming a post request? For example, a form is submitted via Ajax post. Using firebug I can see the post request, but I noticed that this request can be easily repeated by right clicking on it and selecting "open in a new tab" How can I prevent something like this?
When a valid user logs in or begins a session, generate a random token string and place it in a hidden form field. Each time a valid post is made by a valid user, generate a random token string and store it in $_SESSION while also returning it to the client browser. When a the browser makes another Ajax post request, it must also send that token string which you compare against the $_SESSION.
That way you can only make an Ajax post if your server has previously sanctioned it. It prevents anyone who simply knows the Ajax handler's URL from sending HTTP requests to it.
Any web form can be posted to in any number of ways. What you need to do is make sure the server-side script that processes the form has the logic needed to "ignore" spammy requests.
You can't reliably. But you can check for the HTTP_X_REQUESTED_WITH header which is usually send along with ajax requests. It can be spoofed though, and can also not be there for genuine ajax requests.

Jquery $.post and PHP - Prevent the ability to use script outside of main website

I have a PHP script setup using Jquery $.post which would return a response or do an action within the targeted .php file within $.post.
Eg. My page has a form where you type in your Name. Once you hit the submit form button, $.post is called and sends the entered Name field value into "mywebsite.xyz/folder/ajaxscript.php"
If a user was to visit "mywebsite.xyz/folder/ajaxscript.php" directly and somehow POST the data to the script, the script would return a response / do an action, based on the submitted POST data.
The problem is, I don't want others to be able to periodically "call" an action or request a response from my website without using the website directly. Theoretically, right now you could determine what Name values my website allows without even visiting it, or you could call an action without going through the website, by simply visiting "mywebsite.xyz/folder/ajaxscript.php"
So, what measures can I take to prevent this from happening? So far my idea is to ensure that it is a $_POST and not a $_GET - so they cannot manually enter it into the browser, but they could still post data to the script...
Another measure is to apply a session key that expires, and is only valid for X amount of visits until they revisit the website. ~ Or, just have a daily "code" that changes and they'd need to grab this code from the website each day to keep their direct access to the script working (eg. I pass the daily "code" into each post request. I then check that code matches in the ajax php script.)
However, even with these meaures, they will STILL have access to the scripts so long as they know how to POST the data, and also get the new code each day. Also, having a daily code requirement will cause issues when visiting the site at midnight (12:00am) as the code will change and the script will break for someone who is on the website trying to call the script, with the invalid code being passed still.
I have attempted using .htaccess however using:
order allow,deny
deny from all
Prevents legitimate access, and I'd have to add an exception so the website's IP is allowed to access it.. which is a hassle to update I think. Although, if it's the only legitimate solution I guess I'll have to.
If I need to be more clear please let me know.
The problem you describe is similar to Cross-Site Request Forgery (CSRF or XSRF). To protect you against this you could put a cookie into the browser and have the cookie value sent in the post form too (by hidden field or just add it to $.post). On server side check both those fields, if they match the request probably came from your site.
However the problem you describe will be quite hard to protect against. Since you could easily make a script (or use Crul) to forge all kinds of requests and send to your server. I don't know how to "only allow a browser and nothing else".
Use the Session variable as you say plus...
As MyGGAN said use a value set in a cookie (CVAL1) before rendering the submit forms. If this cookie is available (JS Code Check will verify) then submit.
On the server side:
If this cookie value exists and the session variable exist then the HTTP Request came from your website.
Note: If the script (form) is to presented under another domain DO NOT allow the cookie value (CVAL1) to be set.
Do not allow HTTP Requests on the Server Side Scripts if extra Http Headers Are not available (like x-requested-with: jquery). JQuery sends a request with an X-* header to the server.
Read more on Croos-Site Request Forgery as MyGGAN suggests.
I am not really sure REMOTE_ADDR would work. Isnt that supposed to be the end users IP addr?
Firstly, you could make use of
$_SERVER['HTTP_REFERER'], though not always trust-able.
The only bet that a valid post came from your page would be use a captcha.
try to use HTTP_SEC
// SECURITER
if ($_SERVER[HTTP_SEC_FETCH_SITE] != "same-origin")
die();
if ($_SERVER[HTTP_SEC_FETCH_MODE] != "cors")
die();
if ($_SERVER[HTTP_SEC_FETCH_DEST] != "empty")
die();

Categories