I'm a little confused as to how to prevent cross site forgeries. Still. I know there is a wealth of information out there, but I'm confused.
In Steven Anderson's post he describes a form like this:
<body onload="document.getElementById('fm1').submit()">
<form id="fm1" action="http://yoursite/UserProfile/SubmitUpdate" method="post">
<input name="email" value="hacker#somewhere.evil" />
<input name="hobby" value="Defacing websites" />
</form>
</body>
On someone else's site.
The solution given is a "anti-forgery" token, generated by the server, that is POST-ed back to with any requests in a hidden form. That's cool, but what is to stop the hacker just downloading the form page, extracting the token and POSTing it?
My application for this is: On the sign-up for to my website I'd like a AJAX function that sends the currently entered Username to the server which should respond "True/False" if it is available or not. This happens onKey so the user can pick a username that has not been used already. The Submit button will enable when all the conditions for "new user" are met.
Clearly this is an opportunity for a hacker to use the service to "test" lots of usernames to see if they available - I know it's not exactly internet-banking level sort of risk, but I'd still like to service only requests from my application, not a hacker.
Any ideas how about these queries?
UPDATE:
So in my scenario. I generate a Token (say some hashed value of the client's IP address) and the service expects to receive this back if it is give the information about whether the username is available or not.
-- The problem remains, someone off domain simply calls the service e.g. /generateToken This looks at the client's IP... could be a hacker who knows.
Returns
{ token: 4uru32br }
Which is then submitted to the /isUsernameAvailable?token=4uru32br&partialUsername=usernam
Where does that get me?
what is to stop the hacker just downloading the form page, extracting the token and POSTing it?
The same-origin policy, that's what.
I'd like a AJAX function that sends the currently entered Username to the server which should respond "True/False" if it is available or not.
That's a user-enumeration vulnerability right there.
Any ideas how about these queries?
Here's your new process:
Use email addresses for usernames.
Use CAPTCHA to prevent automation on registration forms.
Email username does not exist:
Show "success" message. Send email to address with one-time link. Register user after returns to your site with that link.
Email username does exist:
Show "success" message. Send email to that address with message saying "someone is trying to create an account with this address but it already exists".
You're mixing up CSRF and user enumeration.
The solution given is a "anti-forgery" token, generated by the server,
that is POST-ed back to with any requests in a hidden form. That's
cool, but what is to stop the hacker just downloading the form page,
extracting the token and POSTing it?
Say Bob is a normal user on your site.
Chuck is an evil attacker.
Bob goes on your site and submits the comments form (in your code example). If there is CSRF protection, a token is included in this form too:
<input type="hidden" name="csrf_token" value="zxcvbnnmm1235152" />
Bob's session has token zxcvbnnmm1235152 stored for him server-side.
Chuck also has a login to your site because he has registered.
However, when he goes to this page he gets this token instead:
<input type="hidden" name="csrf_token" value="lklkljlk898977" />
If Chuck downloads the page, gets Bob somehow (e.g. sends him an email) to access this page on Chuck's server, because the csrf_token doesn't match Bob's, Chuck can't post the message as Bob.
Bob can continue just fine, because the token in the form matches the one associated with his session.
CSRF is about stopping Chuck from submitting stuff as Bob, using Bob's browsing session.
My application for this is: On the sign-up for to my website I'd like
a AJAX function that sends the currently entered Username to the
server which should respond "True/False" if it is available or not.
This happens onKey so the user can pick a username that has not been
used already. The Submit button will enable when all the conditions
for "new user" are met.
Clearly this is an opportunity for a hacker to use the service to
"test" lots of usernames to see if they available - I know it's not
exactly internet-banking level sort of risk, but I'd still like to
service only requests from my application, not a hacker.
Yes, this is your user enumeration vulnerability.
Have username as email, and follow this answer on how to make this secure.
The anti-forgery token is not a random code. Nor a reused token for several requests.
Rather, the server couples the token with the callers ip-address or session, for example by encrypting the ip+salt with a server-key.
Thus, if the attacker tries to download the token from your site, it won't be usable by the real client
Related
This is my current understanding of recaptcha (using v2 invisible)
We load the api.js script onto our site
We add data attributes to the button
User clicks button
A listener somewhere in the api.js script fires because it's listening for an event on a tag with those data attributes
This is where it gets fuzzy and I start guessing:
api.js gathers browsing info from the user's cookies and information about how they interacted with the site. Based on this it determines how likely you are are to be a bot and if you are below a certain threshold it gives you a test. Whether you pass the test then gets further factored into your score and all of that gets encoded into a token, which we receive in our callback that we specified on the button's data attribute.
We pass this token to the back end with the rest of our form
From the backend, we make an API request to Google to convert the token into usable information about whether the user passed or failed.
At this point I get confused about why this wasn't just what the api.js script returned in the first place. Does this step only exist in order to give Recaptcha information to further improve it? I just don't understand why this step is here, unless I'm misunderstanding what is going on earlier in the process. Am I getting these we steps wrong? Thanks.
The whole point for captchas is that your server (instead of client in the browser) can verify that the (HTTP) request it received was generated from a real person's actions, when interacting with your application.
This is why your client sends a recaptcha token to your server and your backend consults with the captcha provider about this token and receives trusted information about the original client. In this scenario, your server does not trust the client, so it receives only a token from it. Then it communicates with the trusted captcha provider server-to-server and validates that the token it received from the client is valid and the user behind it is legitimate.
If your client sent the original response from the captcha provider to your backend server, there would be no way for your server to know whether this was a legitimate response from the captcha provider, or a fake one from the client.
I'm trying to better understand the mechanism for how Spring CSRF protection works. Suppose I have a site https://example.com/ where people can vote on candidates. Users can also exchange messages. I also have a user logged in, and another user that sends her a message saying to click on the link https://example.com/vote/candiate/30.
If a user clicks on this link, won't the browser send both the CSRF token and the session ID for the logged in user, thereby bypassing the CSRF protection check?
The reason a link is usually not a problem regarding CSRF is that CSRF is only an issue when the request changes something. A link (a GET request) should not change anything. If it does, like in your example it adds a vote to the candidate I suppose, any link from an external origin (a different website) would also be able to exploit "normal" CSRF by just linking to that url.
The problem in the example is not that CSRF protection is inadequate in Spring, the problem is that voting in this case is a GET request, and GETs are not usually protected against CSRF by design. The solution is to change the vote request to a POST, which would then be protected against CSRF (and which would also be more RESTful btw).
Main idea :
When request is submitted, the server received special cookie and waits for defined value in this cookie. If this value will be differet , the request should fail.
So, if service returns form for moving money between accounts, this form includes parameter, that expected to receive when form is submitted, and if data would be sent without this parameter, request wouldn't be proccessed
App was developed in Web API. We are using AntiForgery Token validation for all the POST calls in xyz.com. Registered xyz.com users get email alerts for the contents they are signed up for. Users click item from email to view the content details. On click of item first click event is being saved in SilverPop and silverpop redirects to actual content in xyz.com. Details page is being loaded with out any issues after authenticating the user based on few query string parameters. Issue is when user make a post call(to saving for later, book mark etc) App is throwing Antiforgery token mismatch error. Sorry for bad English and long question. Strange part of this issue is We are unable to replicate this error and its not occurring consistently. We have two server and 1 load balance hosted in AWS not using sticky session enabled. Using Forms cookie authentication. finally, this issue kept occurring though we run with 1 server. Thanks for reading and appreciate if any one could help.
*User must be Authenticated to validate CSRF token ? This xyz.com makes few api get and post calls.
I'm using Symfony2 and protecting my forms with a CSRF token.
I have a comments system based on Ajax calls. If a user wants to edit his comment, here's what's happening:
A user hits the edit button.
A "fresh" comment edit form is loaded via ajax.
The user edit and submit the form via ajax.
The edited comment is sent back in response.
Is loading the "fresh" edit form via ajax a security risk?
If the form were already in the loaded page and couldn't be requested via ajax, an attacker could not guess the CSRF Token, but since he can request the form he can get his hands on the Token..
Couldn't he..?
Maybe an example will make it clearer:
Dave is an innocent registered user in my site (www.acme.com).
Dave logged in my site and then visited www.evil.com. He doesn't know that, but when he visited evil.com a script was executed.
The script sent an ajax request to www.acme.com/comments/123/edit and got the edit form in response.
It then filled in that form with it's malicious content and submitted that form (again, with ajax).
Will evil's evil plan work?
As far as i understand, there is no risk if your form contains CSRF token field. Default Symfony2 CSRF token depends on session which is not availiable for the attacker (and also on intention). So when the attacker requests the form there is attacker's (not user's) session id used.
Does anyone know how to protect cross site form submit? For example if I have register page and user have to enter there own email and password and I do not want anyone submit email and password value from other site to myweb site.
Store secret randomly generated key inside users session. When user will open page with form put inside form hidden input with that value. Check if both match while validating received data after form is submitted.
If you mean you don't want people to be able to submit data in a form hosting on another website to your server one way of preventing that would be to check the Referrer HTTP header however this is not going to work all of the time as it relies on data being sent by the browser and is easily faked.
You would also end up causing hassle to those who turn off HTTP Referrer sending.
Another way to get this to work might be sending an <input type="hidden" value="dsahdbashdbhas[keyboard mash]" /> which will have a value you generate (when the user requests the page) based on their IP address. Then when you process the form you can check for this value and if it isn't correct you can drop the request.
If this is to prevent automated form filling then you should use CAPTCHA
In the web security world, this is a vulnerability known as Cross-site Request Forgery (CSRF). You should be sure to read the Cross-Site Request Forgery Prevention Cheat-Sheet --and other pages-- at OWASP