Play and CSRF

205 views
Skip to first unread message

Adam Williams

unread,
Jan 4, 2017, 9:33:14 AM1/4/17
to play-fr...@googlegroups.com
Hi all,

I don't work with Play myself, but in my free time I do some web
security related work and have reported issues to organisations such as
Curse, GitHub, ASK4, WBS/University of Warwick and others - some as part
of bug bounty schemes. I've noticed in the last few months that
applications built with Play tend to be very good when it comes to XSS
but are disproportionately vulnerable to cross site request forgery.
I've seen 3 or 4 like this, and most of them are still vulnerable.

A few days back I reported a couple of issues (including a CSRF) in an
open source Play project and was able to see the diff required
(https://git.io/vMOxY) to stop the forms being vulnerable to a CSRF
attack. No less than 12 "@import views.html.helper.CSRF" lines, 25 "@
CSRF.formField" lines and an additional dependency that needed to be
added and configured. From what I understand, out of the box (activator
new test play-scala), Play applications are not secure against this sort
of attack. The cookes aren't SameSite=strict and POST requests are just
accepted. There's not even a Referer check. It's a ton of effort with
Play to fix these sorts of vulnerabilities and I can see why developers
don't bother, especially those that "just want to get things done".

Looking at Django for a moment, the CsrfViewMiddleware is activated by
default and the site is safe. The developer will immediately have their
POST/other unsafe requests fail if they neglect to include a token.
ASP.NET MVC Core automatically adds a "__RequestVerificationToken" to
all <form> elements and new project templates automatically include a
filter (AutoValidateAntiforgeryTokenAttribute) which causes unsafe
requests to have their token validated. Laravel's skeleton includes a
VerifyCsrfToken middleware class which is enabled by default.

Has there been any prior discussion on this? I believe the CSRF
protection should be on by default and opt-out (in the play-scala and
play-java seeds). I do understand that some developers will have no need
for this sort of protection (web APIs mostly), but they should have to
*consciously* opt out. I thought I'd flag this up in the hope of having
some discussion/potential behaviour changes.

Regards,
Adam

kyle valade

unread,
Jan 4, 2017, 1:23:25 PM1/4/17
to Play Framework, ad...@adamwilliams.eu
I'm with you, though to be fair, you have to add a line to all of your Django forms to include the CSRF field, too. 

It actually is possible to make CSRF globally enabled by adding a line to the Filter class, but it's extra work, and you have to do some gross stuff to be able to test your controllers, which requires some thrashing due to the process being poorly documented (see my question here). Maybe the CSRF logic could be added in as part of the default Filter along with a method in the request builder for tests?

The default of having sessions never expire kind of bugs me too, but maybe that's just nitpicky...

But thanks for the heads up - it's a good reminder to double-check everything.

Adam Williams

unread,
Jan 5, 2017, 3:32:35 PM1/5/17
to play-fr...@googlegroups.com
That's interesting, I assumed all the CSRF validation stuff would automatically be turned off during unit/integration testing but I'm not too familiar with how Play works. I'm surprised the problem you described is not a common issue people hit up against (or doesn't seem to be documented in that way anyway).

I guess the main difference with django is that if you neglect to include that line the forms don't work, which is safer. It'd be nice if it wasn't necessary, especially since it seems the Play templates support some form helpers already that seem to me like they could do this automagically - but I agree the form fields themselves aren't the worst of it.

https://github.com/playframework/playframework/issues/6324 looks related to enabling CSRF filtering by default, so I'll express some support there.

Thanks for your insight on this!
--
You received this message because you are subscribed to the Google Groups "Play Framework" group.
To unsubscribe from this group and stop receiving emails from it, send an email to play-framewor...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/play-framework/3f07bd65-a632-47ba-b3fb-26e858893cf5%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Will Sargent

unread,
Jan 9, 2017, 9:03:35 PM1/9/17
to play-fr...@googlegroups.com
Has there been any prior discussion on this? I believe the CSRF protection should be on by default and opt-out (in the play-scala and play-java seeds). I do understand that some developers will have no need for this sort of protection (web APIs mostly), but they should have to *consciously* opt out. I thought I'd flag this up in the hope of having some discussion/potential behaviour changes.

They are.  The play-scala-seed and play-java-seed projects that are the first thing you see on https://playframework.com/download contain CSRF and security filters here:

--
Will Sargent
Engineer, Lightbend, Inc.


To unsubscribe from this group and stop receiving emails from it, send an email to play-framework+unsubscribe@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Play Framework" group.
To unsubscribe from this group and stop receiving emails from it, send an email to play-framework+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/play-framework/586E8166.5080409%40adamwilliams.eu.

kyle valade

unread,
Jan 10, 2017, 7:32:22 AM1/10/17
to Play Framework
Oh interesting - thanks for the pointer - that's great to know. However, the play-java-seed project is different than the one the documentation tells you to start with.

Here, we are told to use `activator new my-first-app play-java`, which, if I'm not mistaken, uses this template, which doesn't have CSRF enabled by default. I can submit a PR to make the play-*-seed the project mentioned in the docs, alternatively, the play-java/scala templates could be changed if you prefer.

And is there anything obvious that we're missing for testing CSRF forms, or is creating a token from the DefaultCSRFTokenSigner and adding it to the fakeRequest the recommended method?

Thanks!
To unsubscribe from this group and stop receiving emails from it, send an email to play-framewor...@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Play Framework" group.
To unsubscribe from this group and stop receiving emails from it, send an email to play-framewor...@googlegroups.com.

Will Sargent

unread,
Jan 10, 2017, 7:58:09 PM1/10/17
to play-fr...@googlegroups.com
Okay, I've filed https://github.com/playframework/playframework/issues/6867 to get the documentation updated.  I'll see about hitting this in the next couple of days.

If you can update the play-java / play-scala templates on github to reflect the giter8 templates it'd be much appreciated.

--
Will Sargent
Engineer, Lightbend, Inc.


To unsubscribe from this group and stop receiving emails from it, send an email to play-framework+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/play-framework/8a077fcb-dbf5-4122-aecb-fe08d0ec57ec%40googlegroups.com.

Will Sargent

unread,
Jan 10, 2017, 8:03:54 PM1/10/17
to play-fr...@googlegroups.com
I've also updated the download page to be a bit more explicit about what's OOTB secure and filed https://github.com/playframework/playframework/issues/6868 to rename the starter projects.

--
Will Sargent
Engineer, Lightbend, Inc.


Will Sargent

unread,
Jan 10, 2017, 8:06:29 PM1/10/17
to play-fr...@googlegroups.com
And is there anything obvious that we're missing for testing CSRF forms, or is creating a token from the DefaultCSRFTokenSigner and adding it to the fakeRequest the recommended method? 

Sorry, I don't follow.  There's a controller spec that is generated when you use "g8Scaffold form" and that should contain the CSRF token in the `addToken` method:


--
Will Sargent
Engineer, Lightbend, Inc.


kyle valade

unread,
Jan 25, 2017, 1:08:15 PM1/25/17
to Play Framework
Thanks Will! Yeah, I'll take a look at that this week.
Reply all
Reply to author
Forward
0 new messages