Skip to content

Commit 3b7d741

Browse files
committed
Put CQL query-relevant definitions in a query library
1 parent 439ad43 commit 3b7d741

File tree

3 files changed

+81
-79
lines changed

3 files changed

+81
-79
lines changed
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import javascript
2+
import semmle.javascript.security.dataflow.SqlInjectionCustomizations
3+
import advanced_security.javascript.frameworks.cap.CQL
4+
import advanced_security.javascript.frameworks.cap.RemoteFlowSources
5+
6+
/**
7+
* A possibly tainted clause
8+
* any clause with a string concatenation in it
9+
* regardless of where that operand came from
10+
*/
11+
class TaintedClause instanceof CqlClause {
12+
TaintedClause() { exists(StringConcatenation::getAnOperand(this.getArgument().flow())) }
13+
14+
string toString() { result = super.toString() }
15+
16+
Expr getArgument() { result = super.getArgument() }
17+
18+
Expr asExpr() { result = super.asExpr() }
19+
}
20+
21+
/**
22+
* Call to`cds.db.run`
23+
* or
24+
* an await surrounding a sql statement
25+
*/
26+
class CQLSink extends DataFlow::Node {
27+
CQLSink() {
28+
this = any(CdsFacade cds).getMember("db").getMember("run").getACall().getAnArgument()
29+
or
30+
exists(AwaitExpr a, CqlClause clause |
31+
a.getAChildExpr() = clause.asExpr() and this.asExpr() = clause.asExpr()
32+
)
33+
}
34+
}
35+
36+
/**
37+
* a more heurisitic based taint step
38+
* captures one of the alternative ways to construct query strings:
39+
* `cds.parse.cql(`string`+userInput)`
40+
* and considers them tainted if they've been concatenated against
41+
* in any manner
42+
*/
43+
class ParseCQLTaintedClause extends CallNode {
44+
ParseCQLTaintedClause() {
45+
this = any(CdsFacade cds).getMember("parse").getMember("cql").getACall() and
46+
exists(DataFlow::Node n |
47+
n = StringConcatenation::getAnOperand(this.getAnArgument()) and
48+
//omit the fact that the arg of cds.parse.cql (`SELECT * from Foo`)
49+
//is technically a string concat
50+
not n.asExpr() instanceof TemplateElement
51+
)
52+
}
53+
}
54+
55+
class CqlIConfiguration extends TaintTracking::Configuration {
56+
CqlIConfiguration() { this = "CqlInjection" }
57+
58+
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
59+
60+
override predicate isSink(DataFlow::Node sink) { sink instanceof CQLSink }
61+
62+
override predicate isSanitizer(DataFlow::Node node) {
63+
super.isSanitizer(node) or
64+
node instanceof SqlInjection::Sanitizer
65+
}
66+
67+
override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) {
68+
//string concatenation in a clause arg taints the clause
69+
exists(TaintedClause clause |
70+
clause.getArgument() = pred.asExpr() and
71+
clause.asExpr() = succ.asExpr()
72+
)
73+
or
74+
//less precise, any concat in the alternative sql stmt construction techniques
75+
exists(ParseCQLTaintedClause parse |
76+
parse.getAnArgument() = pred and
77+
parse = succ
78+
)
79+
}
80+
}

javascript/frameworks/cap/lib/advanced_security/javascript/frameworks/cap/CQL.qll

Lines changed: 0 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -350,52 +350,3 @@ class CqlDeleteClause extends CqlClause {
350350
result.asDotExpr().getPropertyName() = "from"
351351
}
352352
}
353-
354-
/**
355-
* A possibly tainted clause
356-
* any clause with a string concatenation in it
357-
* regardless of where that operand came from
358-
*/
359-
class TaintedClause instanceof CqlClause {
360-
TaintedClause() { exists(StringConcatenation::getAnOperand(this.getArgument().flow())) }
361-
362-
string toString() { result = super.toString() }
363-
364-
Expr getArgument() { result = super.getArgument() }
365-
366-
Expr asExpr() { result = super.asExpr() }
367-
}
368-
369-
/**
370-
* Call to`cds.db.run`
371-
* or
372-
* an await surrounding a sql statement
373-
*/
374-
class CQLSink extends DataFlow::Node {
375-
CQLSink() {
376-
this = any(CdsFacade cds).getMember("db").getMember("run").getACall().getAnArgument()
377-
or
378-
exists(AwaitExpr a, CqlClause clause |
379-
a.getAChildExpr() = clause.asExpr() and this.asExpr() = clause.asExpr()
380-
)
381-
}
382-
}
383-
384-
/**
385-
* a more heurisitic based taint step
386-
* captures one of the alternative ways to construct query strings:
387-
* `cds.parse.cql(`string`+userInput)`
388-
* and considers them tainted if they've been concatenated against
389-
* in any manner
390-
*/
391-
class ParseCQLTaintedClause extends CallNode {
392-
ParseCQLTaintedClause() {
393-
this = any(CdsFacade cds).getMember("parse").getMember("cql").getACall() and
394-
exists(DataFlow::Node n |
395-
n = StringConcatenation::getAnOperand(this.getAnArgument()) and
396-
//omit the fact that the arg of cds.parse.cql (`SELECT * from Foo`)
397-
//is technically a string concat
398-
not n.asExpr() instanceof TemplateElement
399-
)
400-
}
401-
}

javascript/frameworks/cap/src/cqlinjection/CqlInjection.ql

Lines changed: 1 addition & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -12,36 +12,7 @@
1212

1313
import javascript
1414
import DataFlow::PathGraph
15-
import semmle.javascript.security.dataflow.SqlInjectionCustomizations::SqlInjection
16-
import advanced_security.javascript.frameworks.cap.CQL
17-
import advanced_security.javascript.frameworks.cap.RemoteFlowSources
18-
19-
class CqlIConfiguration extends TaintTracking::Configuration {
20-
CqlIConfiguration() { this = "CqlInjection" }
21-
22-
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
23-
24-
override predicate isSink(DataFlow::Node sink) { sink instanceof CQLSink }
25-
26-
override predicate isSanitizer(DataFlow::Node node) {
27-
super.isSanitizer(node) or
28-
node instanceof Sanitizer
29-
}
30-
31-
override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) {
32-
//string concatenation in a clause arg taints the clause
33-
exists(TaintedClause clause |
34-
clause.getArgument() = pred.asExpr() and
35-
clause.asExpr() = succ.asExpr()
36-
)
37-
or
38-
//less precise, any concat in the alternative sql stmt construction techniques
39-
exists(ParseCQLTaintedClause parse |
40-
parse.getAnArgument() = pred and
41-
parse = succ
42-
)
43-
}
44-
}
15+
import advanced_security.javascript.frameworks.cap.CAPCqlInjectionQuery
4516

4617
from CqlIConfiguration sql, DataFlow::PathNode source, DataFlow::PathNode sink
4718
where sql.hasFlowPath(source, sink)

0 commit comments

Comments
 (0)