Skip to content
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

Ruby: Add a query for CSRF protection not enabled #14308

Merged
merged 16 commits into from
Apr 2, 2024

Conversation

hmac
Copy link
Contributor

@hmac hmac commented Sep 25, 2023

Specifically in Rails apps, we look for root ActionController classes without a call to protect_from_forgery.

@github-actions
Copy link
Contributor

QHelp previews:

ruby/ql/src/queries/security/cwe-352/CSRFProtectionNotEnabled.qhelp

CSRF protection not enabled

Cross-site request forgery (CSRF) is a type of vulnerability in which an attacker is able to force a user to carry out an action that the user did not intend.

The attacker tricks an authenticated user into submitting a request to the web application. Typically this request will result in a state change on the server, such as changing the user's password. The request can be initiated when the user visits a site controlled by the attacker. If the web application relies only on cookies for authentication, or on other credentials that are automatically included in the request, then this request will appear as legitimate to the server.

A common countermeasure for CSRF is to generate a unique token to be included in the HTML sent from the server to a user. This token can be used as a hidden field to be sent back with requests to the server, where the server can then check that the token is valid and associated with the relevant user session.

Recommendation

In the Rails web framework, CSRF protection is enabled by the adding a call to the protect_from_forgery method inside an ActionController class. Typically this is done in the ApplicationController class, or an equivalent class from which other controller classes are subclassed. The default behaviour of this method is to null the session when an invalid CSRF token is provided. This may not be sufficient to avoid a CSRF vulnerability - for example if parts of the session are memoized. Calling protect_from_forgery with: :exception can help to avoid this by raising an exception on an invalid CSRF token instead.

Example

The following example shows a case where CSRF protection is enabled with a secure request handling strategy of :exception.

class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception
end
  

References

@hmac
Copy link
Contributor Author

hmac commented Sep 25, 2023

This might be a bit over-sensitive. We could reduce the FP rate by looking for specific routes which map to actions in controllers with no protect_from_forgery setting.

@hmac
Copy link
Contributor Author

hmac commented Sep 25, 2023

protect_from_forgery is automatically enabled in Rails >= 3.0, unless config.default_protect_from_forgery = false is set. We should a) check the Rails version, assuming >= 3.0 if we can't determine the version, and b) only alert if rails < 3.0 or config.default_protect_from_forgery = false.

@hmac hmac force-pushed the hmac-rb-csrf-not-enabled branch from 2e80b34 to eed03fd Compare October 10, 2023 11:08
@hmac hmac force-pushed the hmac-rb-csrf-not-enabled branch from be6dac5 to f31a483 Compare October 12, 2023 09:51
hmac added 12 commits February 23, 2024 11:13
Specifically in Rails apps, we look for root ActionController classes
without a call to `protect_from_forgery`.
Generate an alert for every controller class that doesn't have or
inherity a `protect_from_forgery` setting.
This query only applies to codebases using Ruby on Rails < 5.2, or where
there is no call to `csrf_meta_tags` in the base ERb template.
csrf_meta_tag is an alias for csrf_meta_tags, retained for backwards
compatibility.
Only generate an alert on the top-most vulnerable Rails controller in
the controller tree.
`ActionController::API < ActionController::Base` is a base controller
class, so we should recognise it as such.
CSRF protection only needs to be explicitly enabled on Rails
applications < 5.2 _or_ those that don't include a `load_defaults` call
with a version >= 5.2.
@hmac hmac force-pushed the hmac-rb-csrf-not-enabled branch from 0253837 to 3c6436e Compare February 23, 2024 11:58
@hmac hmac force-pushed the hmac-rb-csrf-not-enabled branch from 3c6436e to f5be407 Compare February 23, 2024 12:02
@hmac hmac force-pushed the hmac-rb-csrf-not-enabled branch from 7275cbc to dd092fd Compare February 26, 2024 11:03
@hmac
Copy link
Contributor Author

hmac commented Feb 27, 2024

DCA finally ran successfully, and the results look good to me.

@hmac hmac marked this pull request as ready for review February 27, 2024 10:05
@hmac hmac requested a review from a team as a code owner February 27, 2024 10:05
Copy link
Contributor

@joefarebrother joefarebrother left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good 👍

@hmac hmac merged commit 409f46e into github:main Apr 2, 2024
24 checks passed
@hmac hmac deleted the hmac-rb-csrf-not-enabled branch April 2, 2024 10:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants