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

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from

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.

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

not exists(ActionController::ProtectFromForgeryCall call |
c.getSelf().flowsTo(call.getReceiver())
)
select c, "Potential CSRF vulnerability due to forgery protection not being enabled"

Check warning

Code scanning / CodeQL

Alert message style violation Warning

Alert message should end with a full stop.
@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.

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.

None yet

1 participant