Skip to content

Commit d09f48e

Browse files
committed
Ruby: flag up protect_from_forgery calls without an exception strategy
1 parent 1c3c921 commit d09f48e

File tree

3 files changed

+35
-4
lines changed

3 files changed

+35
-4
lines changed

ruby/ql/lib/codeql/ruby/frameworks/ActionController.qll

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,3 +297,23 @@ class ActionControllerSkipForgeryProtectionCall extends CSRFProtectionSetting::R
297297

298298
override boolean getVerificationSetting() { result = false }
299299
}
300+
301+
/**
302+
* A call to `protect_from_forgery`.
303+
*/
304+
private class ActionControllerProtectFromForgeryCall extends CSRFProtectionSetting::Range {
305+
private ActionControllerContextCall callExpr;
306+
307+
ActionControllerProtectFromForgeryCall() {
308+
callExpr = this.asExpr().getExpr() and
309+
callExpr.getMethodName() = "protect_from_forgery"
310+
}
311+
312+
private string getWithValueText() { result = callExpr.getKeywordArgument("with").getValueText() }
313+
314+
// Calls without `with: :exception` can allow for bypassing CSRF protection
315+
// in some scenarios.
316+
override boolean getVerificationSetting() {
317+
if this.getWithValueText() = "exception" then result = true else result = false
318+
}
319+
}

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,23 @@
5050
<code>skip_before_action</code>.
5151
</p>
5252

53+
<p>
54+
Care should be taken when using the Rails
55+
<code>protect_from_forgery</code> method to prevent CSRF. The default
56+
behaviour of this method is to null the session when an invalid CSRF token
57+
is provided. This may not be sufficient to avoid a CSRF vulnerability -
58+
for example if parts of the session are memoized. Calling
59+
<code>protect_from_forgery with: :exception</code> can help to avoid this
60+
by raising an exception on an invalid CSRF token instead.
61+
</p>
62+
5363
</example>
5464

5565
<references>
5666
<li>Wikipedia: <a href="https://en.wikipedia.org/wiki/Cross-site_request_forgery">Cross-site request forgery</a></li>
5767
<li>OWASP: <a href="https://owasp.org/www-community/attacks/csrf">Cross-site request forgery</a></li>
5868
<li>Securing Rails Applications: <a href="https://guides.rubyonrails.org/security.html#cross-site-request-forgery-csrf">Cross-Site Request Forgery (CSRF)</a></li>
69+
<li>Veracode: <a href="https://www.veracode.com/blog/managing-appsec/when-rails-protectfromforgery-fails">When Rails' protect_from_forgery Fails</a>.</li>
5970
</references>
6071

6172
</qhelp>

ruby/ql/src/queries/security/cwe-352/CSRFProtectionDisabled.ql

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/**
2-
* @name CSRF protection disabled
3-
* @description Disabling CSRF protection makes the application vulnerable to
4-
* a Cross-Site Request Forgery (CSRF) attack.
2+
* @name CSRF protection weakened or disabled
3+
* @description Disabling or weakening CSRF protection may make the application
4+
* vulnerable to a Cross-Site Request Forgery (CSRF) attack.
55
* @kind problem
66
* @problem.severity warning
77
* @security-severity 8.8
@@ -16,4 +16,4 @@ import codeql.ruby.Concepts
1616

1717
from CSRFProtectionSetting s
1818
where s.getVerificationSetting() = false
19-
select s, "Potential CSRF vulnerability due to forgery protection being disabled."
19+
select s, "Potential CSRF vulnerability due to forgery protection being disabled or weakened."

0 commit comments

Comments
 (0)