New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CSRF protection from cross-origin <script> tags #13345

Merged
merged 1 commit into from Dec 17, 2013

Conversation

Projects
None yet
9 participants
@jeremy
Member

jeremy commented Dec 17, 2013

Extend protect_from_forgery to cover GET requests with JavaScript responses, protecting apps from cross-origin <script> embedding that may leak sensitive data.

TODO

  • Changelog
  • Update Security guide
  • Test actions that use Accept rather than an explicit format
  • Test actions that had neither .format nor Accept
@jeremy

View changes

Show outdated Hide outdated actionpack/lib/action_controller/metal/request_forgery_protection.rb Outdated
@acapilleri

This comment has been minimized.

Show comment
Hide comment
@acapilleri

acapilleri Dec 17, 2013

Contributor

👍 Thanks!

Contributor

acapilleri commented Dec 17, 2013

👍 Thanks!

@carlosantoniodasilva

View changes

Show outdated Hide outdated actionpack/lib/action_controller/metal/request_forgery_protection.rb Outdated
@rafaelfranca

This comment has been minimized.

Show comment
Hide comment
@rafaelfranca

rafaelfranca Dec 17, 2013

Member

Tests are broken 😢

Member

rafaelfranca commented Dec 17, 2013

Tests are broken 😢

@rafaelfranca

View changes

Show outdated Hide outdated actionpack/CHANGELOG.md Outdated
@rafaelfranca

View changes

Show outdated Hide outdated actionpack/CHANGELOG.md Outdated
CSRF protection from cross-origin <script> tags
Thanks to @homakov for sounding the alarm about JSONP-style data leaking
@jeremy

This comment has been minimized.

Show comment
Hide comment
@jeremy

jeremy Dec 17, 2013

Member

@rafaelfranca fixed the other broken tests, they hit the same-origin verification 😁

Member

jeremy commented Dec 17, 2013

@rafaelfranca fixed the other broken tests, they hit the same-origin verification 😁

@rafaelfranca

This comment has been minimized.

Show comment
Hide comment
@rafaelfranca
Member

rafaelfranca commented Dec 17, 2013

:shipit:

@carlosantoniodasilva

This comment has been minimized.

Show comment
Hide comment
@carlosantoniodasilva
Member

carlosantoniodasilva commented Dec 17, 2013

👍

jeremy added a commit that referenced this pull request Dec 17, 2013

Merge pull request #13345 from jeremy/get-csrf
CSRF protection from cross-origin <script> tags

@jeremy jeremy merged commit 39ca25f into rails:master Dec 17, 2013

@jeremy jeremy deleted the jeremy:get-csrf branch Dec 17, 2013

@homakov

This comment has been minimized.

Show comment
Hide comment
@homakov

homakov Dec 19, 2013

Contributor

@jeremy probably instead of exception it should respond with "please send x requested with header to verify request origin"

Contributor

homakov commented Dec 19, 2013

@jeremy probably instead of exception it should respond with "please send x requested with header to verify request origin"

@jeremy

This comment has been minimized.

Show comment
Hide comment
@jeremy

jeremy Dec 19, 2013

Member

@homakov thought about that.. responding with 403 Forbidden so it's clear it's a client error not an application error

App devs can use rescue_from to do that today. But then they'd never get exception emails / notifications and they remain ignorant of the issue. We do that with CSRF also, and it feels strange for an app to ignore unauthorized requests. We just don't have a good convention or API for alerting devs about attacks that were thwarted. Could do that with an AS notification channel: publish security events, let apps/plugins consume them and report and alert.

In any case, this is starting as small as possible. I hope we'll see PRs that do a default rescue_from for this exception, or add separate response strategies like CSRF token verification handling uses.

Member

jeremy commented Dec 19, 2013

@homakov thought about that.. responding with 403 Forbidden so it's clear it's a client error not an application error

App devs can use rescue_from to do that today. But then they'd never get exception emails / notifications and they remain ignorant of the issue. We do that with CSRF also, and it feels strange for an app to ignore unauthorized requests. We just don't have a good convention or API for alerting devs about attacks that were thwarted. Could do that with an AS notification channel: publish security events, let apps/plugins consume them and report and alert.

In any case, this is starting as small as possible. I hope we'll see PRs that do a default rescue_from for this exception, or add separate response strategies like CSRF token verification handling uses.

@jeremy

This comment has been minimized.

Show comment
Hide comment
@jeremy

jeremy Apr 15, 2014

Member

@TechFounder Sounds like you're making a GET request that has a JavaScript response, but you aren't passing the X-Requested-With request header. You'll need to track down where and why.

Member

jeremy commented Apr 15, 2014

@TechFounder Sounds like you're making a GET request that has a JavaScript response, but you aren't passing the X-Requested-With request header. You'll need to track down where and why.

@harmdewit

This comment has been minimized.

Show comment
Hide comment
@harmdewit

harmdewit Apr 22, 2014

In our production server i'm getting ActionController::InvalidCrossOriginRequest:Security warnings in my app for requests with format=*/*. The strange thing is that most requests are correctly called with format=js and some with the strange format=html and even fewer with format=*/*. Only the requests with format=*/* are raising the error and return status 500. I'm trying to reproduce requests with format=*/* but without success.

Am i seeing these inconsistencies because of browser differences? I'm using jquery-rails, is it incorrectly setting the dataType?

harmdewit commented Apr 22, 2014

In our production server i'm getting ActionController::InvalidCrossOriginRequest:Security warnings in my app for requests with format=*/*. The strange thing is that most requests are correctly called with format=js and some with the strange format=html and even fewer with format=*/*. Only the requests with format=*/* are raising the error and return status 500. I'm trying to reproduce requests with format=*/* but without success.

Am i seeing these inconsistencies because of browser differences? I'm using jquery-rails, is it incorrectly setting the dataType?

@masonforest

This comment has been minimized.

Show comment
Hide comment
@masonforest

masonforest Jan 22, 2015

@harmdewit did you ever figure this out? I'm having the same issue.

masonforest commented Jan 22, 2015

@harmdewit did you ever figure this out? I'm having the same issue.

@harmdewit

This comment has been minimized.

Show comment
Hide comment
@harmdewit

harmdewit Jan 22, 2015

I'm not sure what the issue was after this long time but putting this into our ApplicationController seemed to fix it

+  def non_xhr_javascript_response?
+    unless request.get?
+      content_type =~ %r(\Atext/javascript) && !request.xhr?
+    end
+  end

harmdewit commented Jan 22, 2015

I'm not sure what the issue was after this long time but putting this into our ApplicationController seemed to fix it

+  def non_xhr_javascript_response?
+    unless request.get?
+      content_type =~ %r(\Atext/javascript) && !request.xhr?
+    end
+  end
@masonforest

This comment has been minimized.

Show comment
Hide comment
@masonforest

masonforest commented Jan 22, 2015

Thanks @harmdewit! 😃

@masonforest

This comment has been minimized.

Show comment
Hide comment
@masonforest

masonforest Jan 22, 2015

I'm not sure what is requesting format=/ either.

Another solution I came up with is to reorder the respond_to formats:

So I changed this:

respond_to do |format|
     format.js do
       ...
     end
     format.html
end

to this:

respond_to do |format|
     format.html
     format.js do
       ...
     end
end

That way format=/ will return html.

masonforest commented Jan 22, 2015

I'm not sure what is requesting format=/ either.

Another solution I came up with is to reorder the respond_to formats:

So I changed this:

respond_to do |format|
     format.js do
       ...
     end
     format.html
end

to this:

respond_to do |format|
     format.html
     format.js do
       ...
     end
end

That way format=/ will return html.

oliverguenther added a commit to oliverguenther/openproject that referenced this pull request Aug 10, 2015

Fix ActionController::InvalidCrossOriginRequest in specs
rails/rails#13345 introduced CSRF protection
to gets with JavaScript responses.

myabc added a commit to myabc/openproject that referenced this pull request Aug 19, 2015

Fix ActionController::InvalidCrossOriginRequest in specs
rails/rails#13345 introduced CSRF protection
to gets with JavaScript responses.
@flyfy1

This comment has been minimized.

Show comment
Hide comment
@flyfy1

flyfy1 Apr 7, 2017

What case it's trying to defence against? Why do we need to check if content_type =~ %r(\Atext/javascript)?

What case it's trying to defence against? Why do we need to check if content_type =~ %r(\Atext/javascript)?

This comment has been minimized.

Show comment
Hide comment
@jeremy
Member

jeremy replied Apr 10, 2017

This comment has been minimized.

Show comment
Hide comment
@flyfy1

flyfy1 Apr 11, 2017

Thanks, that's really helpful :)

flyfy1 replied Apr 11, 2017

Thanks, that's really helpful :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment