Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit e5f0206

Browse files
authored
Merge pull request #208 from github/action-controller-1
Model accesses to `ActionController` parameters via `params` method
2 parents 5163514 + 0238c19 commit e5f0206

4 files changed

Lines changed: 147 additions & 0 deletions

File tree

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/**
2+
* Provides an extension point for for modeling user-controlled data.
3+
* Such data is often used as data-flow sources in security queries.
4+
*/
5+
6+
private import codeql_ruby.dataflow.internal.DataFlowPublic as DataFlow
7+
8+
/**
9+
* A data flow source of remote user input.
10+
*
11+
* Extend this class to refine existing API models. If you want to model new APIs,
12+
* extend `RemoteFlowSource::Range` instead.
13+
*/
14+
class RemoteFlowSource extends DataFlow::Node {
15+
RemoteFlowSource::Range self;
16+
17+
RemoteFlowSource() { this = self }
18+
19+
/** Gets a string that describes the type of this remote flow source. */
20+
string getSourceType() { result = self.getSourceType() }
21+
}
22+
23+
/** Provides a class for modeling new sources of remote user input. */
24+
module RemoteFlowSource {
25+
/**
26+
* A data flow source of remote user input.
27+
*
28+
* Extend this class to model new APIs. If you want to refine existing API models,
29+
* extend `RemoteFlowSource` instead.
30+
*/
31+
abstract class Range extends DataFlow::Node {
32+
/** Gets a string that describes the type of this remote flow source. */
33+
abstract string getSourceType();
34+
}
35+
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
private import codeql_ruby.AST
2+
private import codeql_ruby.Concepts
3+
private import codeql_ruby.controlflow.CfgNodes
4+
private import codeql_ruby.DataFlow
5+
private import codeql_ruby.dataflow.RemoteFlowSources
6+
private import codeql_ruby.ast.internal.Module
7+
8+
private class ActionControllerBaseAccess extends ConstantReadAccess {
9+
ActionControllerBaseAccess() {
10+
this.getName() = "Base" and
11+
this.getScopeExpr().(ConstantAccess).getName() = "ActionController"
12+
}
13+
}
14+
15+
// ApplicationController extends ActionController::Base, but we
16+
// treat it separately in case the ApplicationController definition
17+
// is not in the database
18+
private class ApplicationControllerAccess extends ConstantReadAccess {
19+
ApplicationControllerAccess() { this.getName() = "ApplicationController" }
20+
}
21+
22+
/**
23+
* A `ClassDeclaration` for a class that extends `ActionController::Base`.
24+
* For example,
25+
*
26+
* ```rb
27+
* class FooController < ActionController::Base
28+
* def delete_handler
29+
* uid = params[:id]
30+
* User.delete_all("id = ?", uid)
31+
* end
32+
* end
33+
* ```
34+
*/
35+
class ActionControllerControllerClass extends ClassDeclaration {
36+
ActionControllerControllerClass() {
37+
// class FooController < ActionController::Base
38+
this.getSuperclassExpr() instanceof ActionControllerBaseAccess
39+
or
40+
// class FooController < ApplicationController
41+
this.getSuperclassExpr() instanceof ApplicationControllerAccess
42+
or
43+
// class BarController < FooController
44+
exists(ActionControllerControllerClass other |
45+
other.getModule() = resolveScopeExpr(this.getSuperclassExpr())
46+
)
47+
}
48+
}
49+
50+
/**
51+
* A call to the `params` method within the context of an
52+
* `ActionControllerControllerClass`. For example, the `params` call in:
53+
*
54+
* ```rb
55+
* class FooController < ActionController::Base
56+
* def delete_handler
57+
* uid = params[:id]
58+
* User.delete_all("id = ?", uid)
59+
* end
60+
* end
61+
* ```
62+
*/
63+
class ActionControllerParamsCall extends MethodCall {
64+
private ActionControllerControllerClass controllerClass;
65+
66+
ActionControllerParamsCall() {
67+
this.getMethodName() = "params" and
68+
this.getReceiver() instanceof Self and
69+
this.getEnclosingModule() = controllerClass
70+
}
71+
72+
ActionControllerControllerClass getControllerClass() { result = controllerClass }
73+
}
74+
75+
/**
76+
* A `RemoteFlowSource::Range` to represent accessing the Action Controller
77+
* parameters available to a controller via the `params` method.
78+
*/
79+
class ActionControllerParamsSource extends RemoteFlowSource::Range {
80+
ActionControllerParamsCall call;
81+
82+
ActionControllerParamsSource() { this.asExpr().getExpr() = call }
83+
84+
// TODO: what to use here?
85+
override string getSourceType() { result = "ActionController::Metal#params" }
86+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
actionControllerControllerClasses
2+
| ActiveRecordInjection.rb:12:1:34:3 | FooController |
3+
| ActiveRecordInjection.rb:37:1:48:3 | BarController |
4+
| ActiveRecordInjection.rb:50:1:51:3 | BazController |
5+
actionControllerParamsCalls
6+
| ActiveRecordInjection.rb:19:30:19:35 | call to params |
7+
| ActiveRecordInjection.rb:22:29:22:34 | call to params |
8+
| ActiveRecordInjection.rb:25:31:25:36 | call to params |
9+
| ActiveRecordInjection.rb:29:20:29:25 | call to params |
10+
| ActiveRecordInjection.rb:32:48:32:53 | call to params |
11+
| ActiveRecordInjection.rb:40:10:40:15 | call to params |
12+
actionControllerParamsSources
13+
| ActiveRecordInjection.rb:19:30:19:35 | call to params |
14+
| ActiveRecordInjection.rb:22:29:22:34 | call to params |
15+
| ActiveRecordInjection.rb:25:31:25:36 | call to params |
16+
| ActiveRecordInjection.rb:29:20:29:25 | call to params |
17+
| ActiveRecordInjection.rb:32:48:32:53 | call to params |
18+
| ActiveRecordInjection.rb:40:10:40:15 | call to params |
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import codeql_ruby.controlflow.CfgNodes
2+
import codeql_ruby.frameworks.ActionController
3+
4+
query predicate actionControllerControllerClasses(ActionControllerControllerClass cls) { any() }
5+
6+
query predicate actionControllerParamsCalls(ActionControllerParamsCall call) { any() }
7+
8+
query predicate actionControllerParamsSources(ActionControllerParamsSource source) { any() }

0 commit comments

Comments
 (0)