model some ActionController user input sources (params)

This commit is contained in:
Alex Ford
2021-06-15 12:48:03 +01:00
parent 9227f3a0c3
commit 5941eb2be4
3 changed files with 113 additions and 0 deletions

View File

@@ -0,0 +1,87 @@
private import codeql_ruby.AST
private import codeql_ruby.Concepts
private import codeql_ruby.controlflow.CfgNodes
private import codeql_ruby.DataFlow
private import codeql_ruby.dataflow.RemoteFlowSources
private import codeql_ruby.ast.internal.Module
private class ActionControllerBaseAccess extends ConstantReadAccess {
ActionControllerBaseAccess() {
this.getName() = "Base" and
this.getScopeExpr().(ConstantAccess).getName() = "ActionController"
}
}
// ApplicationController extends ActionController::Base, but we
// treat it separately in case the ApplicationController definition
// is not in the database
private class ApplicationControllerAccess extends ConstantReadAccess {
ApplicationControllerAccess() { this.getName() = "ApplicationController" }
}
// TODO: Less clumsy name for this?
/**
* A `ClassDeclaration` for a class that extends `ActionController::Base`.
* For example,
*
* ```rb
* class FooController < ActionController::Base
* def delete_handler
* uid = params[:id]
* User.delete_all("id = ?", uid)
* end
* end
* ```
*/
class ActionControllerControllerClass extends ClassDeclaration {
ActionControllerControllerClass() {
// class FooController < ActionController::Base
this.getSuperclassExpr() instanceof ActionControllerBaseAccess
or
// class FooController < ApplicationController
this.getSuperclassExpr() instanceof ApplicationControllerAccess
or
// class BarController < FooController
exists(ActionControllerControllerClass other |
other.getModule() = resolveScopeExpr(this.getSuperclassExpr())
)
}
}
/**
* A call to the `params` method within the context of an
* `ActionControllerControllerClass`. For example, the `params` call in:
*
* ```rb
* class FooController < ActionController::Base
* def delete_handler
* uid = params[:id]
* User.delete_all("id = ?", uid)
* end
* end
* ```
*/
class ActionControllerParamsCall extends MethodCall {
private ActionControllerControllerClass controllerClass;
ActionControllerParamsCall() {
this.getMethodName() = "params" and
this.getReceiver() instanceof Self and
this.getEnclosingModule() = controllerClass
}
ActionControllerControllerClass getControllerClass() { result = controllerClass }
}
/**
* A `RemoteFlowSource::Range` to represent accessing the Action Controller
* parameters available to a controller via the `params` method.
*/
class ActionControllerParamsSource extends RemoteFlowSource::Range {
ActionControllerParamsCall call;
ActionControllerParamsSource() { this.asExpr().getExpr() = call }
// TODO: what to use here?
override string getSourceType() { result = "ActionController::Metal#params" }
}

View File

@@ -0,0 +1,18 @@
actionControllerControllerClasses
| ActiveRecordInjection.rb:12:1:34:3 | FooController |
| ActiveRecordInjection.rb:37:1:48:3 | BarController |
| ActiveRecordInjection.rb:50:1:51:3 | BazController |
actionControllerParamsCalls
| ActiveRecordInjection.rb:19:30:19:35 | call to params |
| ActiveRecordInjection.rb:22:29:22:34 | call to params |
| ActiveRecordInjection.rb:25:31:25:36 | call to params |
| ActiveRecordInjection.rb:29:20:29:25 | call to params |
| ActiveRecordInjection.rb:32:48:32:53 | call to params |
| ActiveRecordInjection.rb:40:10:40:15 | call to params |
actionControllerParamsSources
| ActiveRecordInjection.rb:19:30:19:35 | call to params |
| ActiveRecordInjection.rb:22:29:22:34 | call to params |
| ActiveRecordInjection.rb:25:31:25:36 | call to params |
| ActiveRecordInjection.rb:29:20:29:25 | call to params |
| ActiveRecordInjection.rb:32:48:32:53 | call to params |
| ActiveRecordInjection.rb:40:10:40:15 | call to params |

View File

@@ -0,0 +1,8 @@
import codeql_ruby.controlflow.CfgNodes
import codeql_ruby.frameworks.ActionController
query predicate actionControllerControllerClasses(ActionControllerControllerClass cls) { any() }
query predicate actionControllerParamsCalls(ActionControllerParamsCall call) { any() }
query predicate actionControllerParamsSources(ActionControllerParamsSource source) { any() }