11/**
22 * @name Weak or direct parameter references are used
33 * @description Directly checking request parameters without following a strong params pattern can lead to unintentional avenues for injection attacks.
4- * @kind problem
4+ * @kind path- problem
55 * @problem.severity error
66 * @security-severity 5.0
77 * @precision low
1010 */
1111
1212import ruby
13+ import codeql.ruby.DataFlow
14+ import codeql.ruby.TaintTracking
15+ import DataFlow:: PathGraph
1316
14- class WeakParams extends AstNode {
17+ class WeakParams extends Expr {
1518 WeakParams ( ) {
16- this instanceof UnspecificParamsMethod or
19+ allParamsAccess ( this ) or
1720 this instanceof ParamsReference
1821 }
1922}
@@ -26,27 +29,51 @@ class StrongParamsMethod extends Method {
2629 StrongParamsMethod ( ) { this .getName ( ) .regexpMatch ( ".*_params" ) }
2730}
2831
29- class UnspecificParamsMethod extends MethodCall {
30- UnspecificParamsMethod ( ) {
31- (
32- this .getMethodName ( ) = "expose_all" or
33- this .getMethodName ( ) = "original_hash" or
34- this .getMethodName ( ) = "path_parametes" or
35- this .getMethodName ( ) = "query_parameters" or
36- this .getMethodName ( ) = "request_parameters" or
37- this .getMethodName ( ) = "GET" or
38- this .getMethodName ( ) = "POST"
39- )
40- }
32+ predicate allParamsAccess ( MethodCall call ) {
33+ call .getMethodName ( ) = "expose_all" or
34+ call .getMethodName ( ) = "original_hash" or
35+ call .getMethodName ( ) = "path_parametes" or
36+ call .getMethodName ( ) = "query_parameters" or
37+ call .getMethodName ( ) = "request_parameters" or
38+ call .getMethodName ( ) = "GET" or
39+ call .getMethodName ( ) = "POST"
4140}
4241
4342class ParamsReference extends ElementReference {
4443 ParamsReference ( ) { this .getAChild ( ) .toString ( ) = "params" }
4544}
4645
47- from WeakParams params
48- where
49- not params .getEnclosingMethod ( ) instanceof StrongParamsMethod and
50- params .getEnclosingModule ( ) instanceof ControllerClass
51- select params ,
52- "By exposing all keys in request parameters or by blindy accessing them, unintended parameters could be used and lead to mass-assignment or have other unexpected side-effects."
46+ class ModelClass extends ModuleBase {
47+ ModelClass ( ) {
48+ this .getModule ( ) .getSuperClass + ( ) .toString ( ) = "ViewModel" or
49+ this .getModule ( ) .getSuperClass + ( ) .getAnIncludedModule ( ) .toString ( ) = "ActionModel::Model"
50+ }
51+ }
52+
53+ class ModelClassMethodArgument extends DataFlow:: Node {
54+ private DataFlow:: CallNode call ;
55+
56+ ModelClassMethodArgument ( ) {
57+ this = call .getArgument ( _) and
58+ call .getExprNode ( ) .getNode ( ) .getParent + ( ) instanceof ModelClass
59+ }
60+ }
61+
62+ class Configuration extends TaintTracking:: Configuration {
63+ Configuration ( ) { this = "Configuration" }
64+
65+ override predicate isSource ( DataFlow:: Node node ) { node .asExpr ( ) .getNode ( ) instanceof WeakParams }
66+
67+ // the sink is an instance of a Model class that receives a method call
68+ override predicate isSink ( DataFlow:: Node node ) { node instanceof ModelClassMethodArgument }
69+ }
70+
71+ from Configuration config , DataFlow:: PathNode source , DataFlow:: PathNode sink
72+ where config .hasFlowPath ( source , sink )
73+ select sink .getNode ( ) .( ModelClassMethodArgument ) , source , sink , "This is bad"
74+ // from WeakParams params
75+ // where
76+ // not params.getEnclosingMethod() instanceof StrongParamsMethod and
77+ // params.getEnclosingModule() instanceof ControllerClass
78+ // select params,
79+ // "By exposing all keys in request parameters or by blindy accessing them, unintended parameters could be used and lead to mass-assignment or have other unexpected side-effects."
0 commit comments