11/**
2- * Provides a tracking configuration for reasoning about type confusion for HTTP request inputs.
2+ * Provides a tracking configuration for reasoning about type
3+ * confusion for HTTP request inputs.
4+ *
5+ * Note, for performance reasons: only import this file if
6+ * `TypeConfusionThroughParameterTampering::Configuration` is needed,
7+ * otherwise `TypeConfusionThroughParameterTamperingCustomizations`
8+ * should be imported instead.
39 */
410
511import javascript
6- import semmle.javascript.security.dataflow.RemoteFlowSources
712private import semmle.javascript.dataflow.InferredTypes
813
914module TypeConfusionThroughParameterTampering {
10- /**
11- * A data flow source for type confusion for HTTP request inputs.
12- */
13- abstract class Source extends DataFlow:: Node { }
14-
15- /**
16- * A data flow sink for type confusion for HTTP request inputs.
17- */
18- abstract class Sink extends DataFlow:: Node { }
19-
20- /**
21- * A barrier for type confusion for HTTP request inputs.
22- */
23- abstract class Barrier extends DataFlow:: Node { }
15+ import TypeConfusionThroughParameterTamperingCustomizations:: TypeConfusionThroughParameterTampering
2416
2517 /**
2618 * A taint tracking configuration for type confusion for HTTP request inputs.
@@ -38,73 +30,4 @@ module TypeConfusionThroughParameterTampering {
3830
3931 override predicate isBarrier ( DataFlow:: Node node ) { node instanceof Barrier }
4032 }
41-
42- /**
43- * An HTTP request parameter that the user controls the type of.
44- *
45- * Node.js-based HTTP servers turn request parameters into arrays if their names are repeated.
46- */
47- private class TypeTamperableRequestParameter extends Source {
48- TypeTamperableRequestParameter ( ) { this .( HTTP:: RequestInputAccess ) .isUserControlledObject ( ) }
49- }
50-
51- /**
52- * Methods calls that behave slightly different for arrays and strings receivers.
53- */
54- private class StringArrayAmbiguousMethodCall extends Sink {
55- StringArrayAmbiguousMethodCall ( ) {
56- exists ( string name , DataFlow:: MethodCallNode mc |
57- name = "concat" or
58- name = "includes" or
59- name = "indexOf" or
60- name = "lastIndexOf" or
61- name = "slice"
62- |
63- mc .calls ( this , name ) and
64- // ignore patterns that are innocent in practice
65- not exists ( EqualityTest cmp , Expr op | cmp .hasOperands ( mc .asExpr ( ) , op ) |
66- // prefix checking: `x.indexOf(prefix) === 0`
67- name = "indexOf" and
68- op .getIntValue ( ) = 0
69- or
70- // suffix checking: `x.slice(-1) === '/'`
71- name = "slice" and
72- mc .getArgument ( 0 ) .asExpr ( ) .getIntValue ( ) = - 1 and
73- op .getStringValue ( ) .length ( ) = 1
74- )
75- )
76- }
77- }
78-
79- /**
80- * An access to the `length` property of an object.
81- */
82- private class LengthAccess extends Sink {
83- LengthAccess ( ) {
84- exists ( DataFlow:: PropRead read |
85- read .accesses ( this , "length" ) and
86- // an array/string confusion cannot control an emptiness check
87- not (
88- // `if (x.length) {...}`
89- exists ( ConditionGuardNode cond | read .asExpr ( ) = cond .getTest ( ) )
90- or
91- // `x.length == 0`, `x.length > 0`
92- exists ( Comparison cmp , Expr zero |
93- zero .getIntValue ( ) = 0 and
94- cmp .hasOperands ( read .asExpr ( ) , zero )
95- )
96- or
97- // `x.length < 1`
98- exists ( RelationalComparison cmp |
99- cmp .getLesserOperand ( ) = read .asExpr ( ) and
100- cmp .getGreaterOperand ( ) .getIntValue ( ) = 1 and
101- not cmp .isInclusive ( )
102- )
103- or
104- // `!x.length`
105- exists ( LogNotExpr neg | neg .getOperand ( ) = read .asExpr ( ) )
106- )
107- )
108- }
109- }
11033}
0 commit comments