mirror of
https://github.com/github/codeql.git
synced 2026-04-29 10:45:15 +02:00
use taint config for data flow
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @name Manually checking http verb instead of using built in rails routes and protections
|
||||
* @description Manually checking HTTP verbs is an indication that multiple requests are routed to the same controller action. This could lead to bypassing necessary authorization methods and other protections, like CSRF protection. Prefer using different controller actions for each HTTP method and relying Rails routing to handle mappting resources and verbs to specific methods.
|
||||
* @kind problem
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 5.0
|
||||
* @precision low
|
||||
@@ -13,6 +13,8 @@ import ruby
|
||||
import codeql.ruby.DataFlow
|
||||
import codeql.ruby.controlflow.CfgNodes
|
||||
import codeql.ruby.frameworks.ActionController
|
||||
import codeql.ruby.TaintTracking
|
||||
import DataFlow::PathGraph
|
||||
|
||||
// any `request` calls in an action method
|
||||
class Request extends DataFlow::CallNode {
|
||||
@@ -70,32 +72,24 @@ class RequestGet extends DataFlow::CallNode {
|
||||
}
|
||||
}
|
||||
|
||||
// A conditional expression where the condition uses `request.method`, `request.request_method`, `request.raw_request_method`, `request.request_method_symbol`, or `request.get?` in some way.
|
||||
// e.g.
|
||||
// ```
|
||||
// r = request.request_method
|
||||
// if r == "GET"
|
||||
// ...
|
||||
// ```
|
||||
class RequestMethodConditional extends DataFlow::Node {
|
||||
RequestMethodConditional() {
|
||||
// We have to cast the dataflow node down to a specific CFG node (`ExprNodes::ConditionalExprCfgNode`) to be able to call `getCondition()`.
|
||||
// We then find the dataflow node corresponding to the condition CFG node,
|
||||
// and filter for just nodes where a request method accessor value flows to them.
|
||||
exists(DataFlow::Node conditionNode |
|
||||
conditionNode.asExpr() = this.asExpr().(ExprNodes::ConditionalExprCfgNode).getCondition()
|
||||
|
|
||||
(
|
||||
any(RequestMethod r).flowsTo(conditionNode) or
|
||||
any(RequestRequestMethod r).flowsTo(conditionNode) or
|
||||
any(RequestRawRequestMethod r).flowsTo(conditionNode) or
|
||||
any(RequestRequestMethodSymbol r).flowsTo(conditionNode) or
|
||||
any(RequestGet r).flowsTo(conditionNode)
|
||||
)
|
||||
)
|
||||
class HttpVerbConfig extends TaintTracking::Configuration {
|
||||
HttpVerbConfig() { this = "HttpVerbConfig" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
source instanceof RequestMethod or
|
||||
source instanceof RequestRequestMethod or
|
||||
source instanceof RequestEnvMethod or
|
||||
source instanceof RequestRawRequestMethod or
|
||||
source instanceof RequestRequestMethodSymbol or
|
||||
source instanceof RequestGet
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
exists(ExprNodes::ConditionalExprCfgNode c | c.getCondition() = sink.asExpr()) or
|
||||
exists(ExprNodes::CaseExprCfgNode c | c.getValue() = sink.asExpr())
|
||||
}
|
||||
}
|
||||
|
||||
from RequestMethodConditional req
|
||||
select req,
|
||||
"Manually checking HTTP verbs is an indication that multiple requests are routed to the same controller action. This could lead to bypassing necessary authorization methods and other protections, like CSRF protection. Prefer using different controller actions for each HTTP method and relying Rails routing to handle mappting resources and verbs to specific methods."
|
||||
from HttpVerbConfig config, DataFlow::Node source, DataFlow::Node sink
|
||||
where config.hasFlow(source, sink)
|
||||
select sink.asExpr().getExpr(), source, sink, "Manually checking HTTP verbs is an indication that multiple requests are routed to the same controller action. This could lead to bypassing necessary authorization methods and other protections, like CSRF protection. Prefer using different controller actions for each HTTP method and relying Rails routing to handle mappting resources and verbs to specific methods."
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
edges
|
||||
| ManuallyCheckHttpVerb.rb:11:14:11:24 | call to env : | ManuallyCheckHttpVerb.rb:11:14:11:42 | ...[...] : |
|
||||
| ManuallyCheckHttpVerb.rb:11:14:11:42 | ...[...] : | ManuallyCheckHttpVerb.rb:12:8:12:22 | ... == ... |
|
||||
| ManuallyCheckHttpVerb.rb:19:14:19:35 | call to request_method : | ManuallyCheckHttpVerb.rb:20:8:20:22 | ... == ... |
|
||||
| ManuallyCheckHttpVerb.rb:27:14:27:27 | call to method : | ManuallyCheckHttpVerb.rb:28:8:28:22 | ... == ... |
|
||||
| ManuallyCheckHttpVerb.rb:35:14:35:39 | call to raw_request_method : | ManuallyCheckHttpVerb.rb:36:8:36:22 | ... == ... |
|
||||
| ManuallyCheckHttpVerb.rb:51:16:51:44 | call to request_method_symbol : | ManuallyCheckHttpVerb.rb:52:10:52:23 | ... == ... |
|
||||
| ManuallyCheckHttpVerb.rb:59:10:59:20 | call to env : | ManuallyCheckHttpVerb.rb:59:10:59:38 | ...[...] |
|
||||
nodes
|
||||
| ManuallyCheckHttpVerb.rb:4:8:4:19 | call to get? | semmle.label | call to get? |
|
||||
| ManuallyCheckHttpVerb.rb:11:14:11:24 | call to env : | semmle.label | call to env : |
|
||||
| ManuallyCheckHttpVerb.rb:11:14:11:42 | ...[...] : | semmle.label | ...[...] : |
|
||||
| ManuallyCheckHttpVerb.rb:12:8:12:22 | ... == ... | semmle.label | ... == ... |
|
||||
| ManuallyCheckHttpVerb.rb:19:14:19:35 | call to request_method : | semmle.label | call to request_method : |
|
||||
| ManuallyCheckHttpVerb.rb:20:8:20:22 | ... == ... | semmle.label | ... == ... |
|
||||
| ManuallyCheckHttpVerb.rb:27:14:27:27 | call to method : | semmle.label | call to method : |
|
||||
| ManuallyCheckHttpVerb.rb:28:8:28:22 | ... == ... | semmle.label | ... == ... |
|
||||
| ManuallyCheckHttpVerb.rb:35:14:35:39 | call to raw_request_method : | semmle.label | call to raw_request_method : |
|
||||
| ManuallyCheckHttpVerb.rb:36:8:36:22 | ... == ... | semmle.label | ... == ... |
|
||||
| ManuallyCheckHttpVerb.rb:51:16:51:44 | call to request_method_symbol : | semmle.label | call to request_method_symbol : |
|
||||
| ManuallyCheckHttpVerb.rb:52:10:52:23 | ... == ... | semmle.label | ... == ... |
|
||||
| ManuallyCheckHttpVerb.rb:59:10:59:20 | call to env : | semmle.label | call to env : |
|
||||
| ManuallyCheckHttpVerb.rb:59:10:59:38 | ...[...] | semmle.label | ...[...] |
|
||||
subpaths
|
||||
#select
|
||||
| ManuallyCheckHttpVerb.rb:4:8:4:19 | call to get? | ManuallyCheckHttpVerb.rb:4:8:4:19 | call to get? | ManuallyCheckHttpVerb.rb:4:8:4:19 | call to get? | Manually checking HTTP verbs is an indication that multiple requests are routed to the same controller action. This could lead to bypassing necessary authorization methods and other protections, like CSRF protection. Prefer using different controller actions for each HTTP method and relying Rails routing to handle mappting resources and verbs to specific methods. |
|
||||
| ManuallyCheckHttpVerb.rb:12:8:12:22 | ... == ... | ManuallyCheckHttpVerb.rb:11:14:11:24 | call to env | ManuallyCheckHttpVerb.rb:12:8:12:22 | ... == ... | Manually checking HTTP verbs is an indication that multiple requests are routed to the same controller action. This could lead to bypassing necessary authorization methods and other protections, like CSRF protection. Prefer using different controller actions for each HTTP method and relying Rails routing to handle mappting resources and verbs to specific methods. |
|
||||
| ManuallyCheckHttpVerb.rb:20:8:20:22 | ... == ... | ManuallyCheckHttpVerb.rb:19:14:19:35 | call to request_method | ManuallyCheckHttpVerb.rb:20:8:20:22 | ... == ... | Manually checking HTTP verbs is an indication that multiple requests are routed to the same controller action. This could lead to bypassing necessary authorization methods and other protections, like CSRF protection. Prefer using different controller actions for each HTTP method and relying Rails routing to handle mappting resources and verbs to specific methods. |
|
||||
| ManuallyCheckHttpVerb.rb:28:8:28:22 | ... == ... | ManuallyCheckHttpVerb.rb:27:14:27:27 | call to method | ManuallyCheckHttpVerb.rb:28:8:28:22 | ... == ... | Manually checking HTTP verbs is an indication that multiple requests are routed to the same controller action. This could lead to bypassing necessary authorization methods and other protections, like CSRF protection. Prefer using different controller actions for each HTTP method and relying Rails routing to handle mappting resources and verbs to specific methods. |
|
||||
| ManuallyCheckHttpVerb.rb:36:8:36:22 | ... == ... | ManuallyCheckHttpVerb.rb:35:14:35:39 | call to raw_request_method | ManuallyCheckHttpVerb.rb:36:8:36:22 | ... == ... | Manually checking HTTP verbs is an indication that multiple requests are routed to the same controller action. This could lead to bypassing necessary authorization methods and other protections, like CSRF protection. Prefer using different controller actions for each HTTP method and relying Rails routing to handle mappting resources and verbs to specific methods. |
|
||||
| ManuallyCheckHttpVerb.rb:52:10:52:23 | ... == ... | ManuallyCheckHttpVerb.rb:51:16:51:44 | call to request_method_symbol | ManuallyCheckHttpVerb.rb:52:10:52:23 | ... == ... | Manually checking HTTP verbs is an indication that multiple requests are routed to the same controller action. This could lead to bypassing necessary authorization methods and other protections, like CSRF protection. Prefer using different controller actions for each HTTP method and relying Rails routing to handle mappting resources and verbs to specific methods. |
|
||||
| ManuallyCheckHttpVerb.rb:59:10:59:38 | ...[...] | ManuallyCheckHttpVerb.rb:59:10:59:20 | call to env | ManuallyCheckHttpVerb.rb:59:10:59:38 | ...[...] | Manually checking HTTP verbs is an indication that multiple requests are routed to the same controller action. This could lead to bypassing necessary authorization methods and other protections, like CSRF protection. Prefer using different controller actions for each HTTP method and relying Rails routing to handle mappting resources and verbs to specific methods. |
|
||||
|
||||
@@ -38,6 +38,14 @@ class ExampleController < ActionController::Base
|
||||
end
|
||||
end
|
||||
|
||||
# Should not find
|
||||
def baz2
|
||||
method = request.raw_request_method
|
||||
if some_other_function == "GET"
|
||||
Resource.find(id: params[:id])
|
||||
end
|
||||
end
|
||||
|
||||
# Should find
|
||||
def foobarbaz
|
||||
method = request.request_method_symbol
|
||||
@@ -56,7 +64,15 @@ class ExampleController < ActionController::Base
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# Should not find
|
||||
def resource_action
|
||||
case request.random_method
|
||||
when "GET"
|
||||
Resource.find(id: params[:id])
|
||||
when "POST"
|
||||
Resource.new(id: params[:id], details: params[:details])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class SafeController < ActionController::Base
|
||||
|
||||
Reference in New Issue
Block a user