mirror of
https://github.com/hohn/codeql-javascript-multiflow.git
synced 2025-12-16 03:53:04 +01:00
Add new example to illustrate taint propagation with def-use dataflow
This commit is contained in:
committed by
=Michael Hohn
parent
c1962230c2
commit
8cdb8ef0dd
@@ -239,7 +239,7 @@
|
|||||||
codeql database create --language=javascript -s . -j 8 -v $DB
|
codeql database create --language=javascript -s . -j 8 -v $DB
|
||||||
|
|
||||||
# Check it
|
# Check it
|
||||||
unzip -v js-sqli-db-*/src.zip |grep add
|
unzip -v $DB/src.zip |egrep '(add|sample)'
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
|
||||||
12. add the database to the editor. To do this there is a widget on the left
|
12. add the database to the editor. To do this there is a widget on the left
|
||||||
|
|||||||
@@ -2,10 +2,6 @@
|
|||||||
"folders": [
|
"folders": [
|
||||||
{
|
{
|
||||||
"path": "."
|
"path": "."
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "[js-sqli-db-c860686 source archive]",
|
|
||||||
"uri": "codeql-zip-archive://0-72/Users/hohn/local/codeql-javascript-multiflow/js-sqli-db-c860686/src.zip"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"settings": {
|
"settings": {
|
||||||
|
|||||||
23
sample-utility-0.js
Normal file
23
sample-utility-0.js
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
var SampleUtility = function(){};
|
||||||
|
SampleUtility.prototype = Object.extendsObject(Processor, {
|
||||||
|
|
||||||
|
setUserStatus: function() {
|
||||||
|
var value = this.getParameter('value');
|
||||||
|
|
||||||
|
var ua = new GR('users');
|
||||||
|
ua.query();
|
||||||
|
|
||||||
|
if(!ua.hasNext()){
|
||||||
|
ua.initialize();
|
||||||
|
ua.setValue('status',value);
|
||||||
|
ua.insert();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ua.next();
|
||||||
|
ua.setValue('status',value);
|
||||||
|
ua.update();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
type: 'SampleUtility'
|
||||||
|
});
|
||||||
17
sample-utility-1.js
Normal file
17
sample-utility-1.js
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
var SampleUtility = function() {
|
||||||
|
var value = this.getParameter('value');
|
||||||
|
|
||||||
|
var ua = new GR('users');
|
||||||
|
ua.query();
|
||||||
|
|
||||||
|
if(!ua.hasNext()){
|
||||||
|
ua.initialize();
|
||||||
|
ua.setValue('status',value);
|
||||||
|
ua.insert();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ua.next();
|
||||||
|
ua.setValue('status',value);
|
||||||
|
ua.update();
|
||||||
|
}
|
||||||
|
}
|
||||||
85
session/session1.ql
Normal file
85
session/session1.ql
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
/**
|
||||||
|
* @kind path-problem
|
||||||
|
* @problem.severity warning
|
||||||
|
* @id javascript/example/multiflow
|
||||||
|
*/
|
||||||
|
|
||||||
|
import javascript
|
||||||
|
// XX: debug flow query
|
||||||
|
// import semmle.javascript.explore.ForwardDataFlow
|
||||||
|
import DataFlow::PathGraph
|
||||||
|
|
||||||
|
// Flow to consider:
|
||||||
|
// var value = this.getParameter('value'); //: source 1
|
||||||
|
// var ua = new GR('status'); //: source 2
|
||||||
|
// ua.setValue('status',value); //: taint step
|
||||||
|
// ua.update(); //: sink (if from source 2)
|
||||||
|
// var value = this.getParameter('value'); //: source 1
|
||||||
|
|
||||||
|
class ParameterSource extends CallExpr {
|
||||||
|
ParameterSource() {
|
||||||
|
exists(Expr inst |
|
||||||
|
this.getCalleeName() = "getParameter" and
|
||||||
|
(this.getReceiver().(ThisExpr) = inst or this.getReceiver().(Identifier) = inst)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ua.setValue('status',value); //: taint step
|
||||||
|
predicate setValueTaintStep(DataFlow::Node pred, DataFlow::Node succ) {
|
||||||
|
exists(DotExpr temp, MethodCallExpr mce, VarAccess gr, VarAccess postgr|
|
||||||
|
temp.getPropertyName() = "setValue" and
|
||||||
|
mce.getReceiver() = temp.getBase() and
|
||||||
|
gr = mce.getReceiver() and
|
||||||
|
pred.asExpr() = mce.getArgument(1) and
|
||||||
|
// Taint all accesses after setValue call.
|
||||||
|
// Trying data flow, this would be:
|
||||||
|
// succ = gr.flow().getASuccessor+() and
|
||||||
|
//
|
||||||
|
// Using control flow:
|
||||||
|
gr.getASuccessor+() = postgr and
|
||||||
|
succ.asExpr() = postgr
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
VarRef methodCalled(string name) {
|
||||||
|
exists(DotExpr temp |
|
||||||
|
temp.getPropertyName() = name and
|
||||||
|
result = temp.getBase()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ua.update(); //: sink (if from source 2)
|
||||||
|
DotExpr updateExpression() { result.getPropertyName() = "update" }
|
||||||
|
|
||||||
|
VarRef recordUpdate() { result = updateExpression().getBase() }
|
||||||
|
|
||||||
|
// var ua = new GR('status'); //: source 2
|
||||||
|
class GR extends NewExpr {
|
||||||
|
GR() { this.getCalleeName() = "GR" }
|
||||||
|
}
|
||||||
|
|
||||||
|
class FromRequestToGrUpdate extends TaintTracking::Configuration {
|
||||||
|
FromRequestToGrUpdate() { this = "FromRequestToGrUpdate" }
|
||||||
|
|
||||||
|
override predicate isSource(DataFlow::Node source) {
|
||||||
|
exists(ParameterSource getParameter | source.asExpr() = getParameter)
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) {
|
||||||
|
setValueTaintStep(pred, succ)
|
||||||
|
}
|
||||||
|
|
||||||
|
override predicate isSink(DataFlow::Node sink) {
|
||||||
|
exists(VarRef grUpdate |
|
||||||
|
sink.asExpr() = recordUpdate() and
|
||||||
|
grUpdate = sink.asExpr() and
|
||||||
|
grUpdate.getName() = "ua"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
from FromRequestToGrUpdate dataflow, DataFlow::PathNode source, DataFlow::PathNode sink
|
||||||
|
where dataflow.hasFlowPath(source, sink)
|
||||||
|
select sink, source, sink, "Data flow from $@ to $@.", source, source.toString(), sink, sink.toString()
|
||||||
Reference in New Issue
Block a user