Python: Modernise werkzeug MultiDict modeling

This commit is contained in:
Rasmus Wriedt Larsen
2020-10-21 20:18:59 +02:00
parent b6bd70a5da
commit d0fdb542e5
2 changed files with 70 additions and 34 deletions

View File

@@ -317,7 +317,7 @@ private module Flask_Private {
}
private class RequestInputMultiDict extends RequestInputAccess,
Werkzeug::Datastructures::MultiDict {
Werkzeug::werkzeug::datastructures::MultiDict::InstanceSource {
RequestInputMultiDict() { attr_name in ["args", "values", "form", "files"] }
}

View File

@@ -7,40 +7,76 @@ private import experimental.dataflow.DataFlow
private import experimental.dataflow.TaintTracking
module Werkzeug {
/** Provides models for the `werkzeug` module. */
module werkzeug {
/** Provides models for the `werkzeug.datastructures` module. */
module datastructures {
/**
* Provides models for the `werkzeug.datastructures.MultiDict` class
*
* See https://werkzeug.palletsprojects.com/en/1.0.x/datastructures/#werkzeug.datastructures.MultiDict.
*/
module MultiDict {
/**
* A source of an instance of `werkzeug.datastructures.MultiDict`.
*
* This can include instantiation of the class, return value from function
* calls, or a special parameter that will be set when functions are call by external
* library.
*
* Use `MultiDict::instance()` predicate to get references to instances of `werkzeug.datastructures.MultiDict`.
*/
abstract class InstanceSource extends DataFlow::Node { }
/** Gets a reference to an instance of `werkzeug.datastructures.MultiDict`. */
private DataFlow::Node instance(DataFlow::TypeTracker t) {
t.start() and
result instanceof InstanceSource
or
exists(DataFlow::TypeTracker t2 | result = instance(t2).track(t2, t))
}
/** Gets a reference to an instance of `werkzeug.datastructures.MultiDict`. */
DataFlow::Node instance() { result = instance(DataFlow::TypeTracker::end()) }
/**
* Gets a reference to the `getlist` method on an instance of `werkzeug.datastructures.MultiDict`.
*
* See https://werkzeug.palletsprojects.com/en/1.0.x/datastructures/#werkzeug.datastructures.Headers.getlist
*/
private DataFlow::Node getlist(DataFlow::TypeTracker t) {
t.startInAttr("getlist") and
result = instance()
or
exists(DataFlow::TypeTracker t2 | result = getlist(t2).track(t2, t))
}
/**
* Gets a reference to the `getlist` method on an instance of `werkzeug.datastructures.MultiDict`.
*
* See https://werkzeug.palletsprojects.com/en/1.0.x/datastructures/#werkzeug.datastructures.Headers.getlist
*/
DataFlow::Node getlist() { result = getlist(DataFlow::TypeTracker::end()) }
}
}
}
private class MultiDictAdditionalTaintStep extends TaintTracking::AdditionalTaintStep {
override predicate step(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
// obj -> obj.getlist
exists(DataFlow::AttrRead read |
read.getObject() = nodeFrom and
nodeTo = read and
nodeTo = werkzeug::datastructures::MultiDict::getlist()
)
or
// getlist -> getlist()
nodeFrom = werkzeug::datastructures::MultiDict::getlist() and
nodeTo.asCfgNode().(CallNode).getFunction() = nodeFrom.asCfgNode()
}
}
module Datastructures {
// ---------------------------------------------------------------------- //
// MultiDict //
// ---------------------------------------------------------------------- //
/**
* A Node representing an instance of a werkzeug.datastructures.MultiDict
*
* See https://werkzeug.palletsprojects.com/en/1.0.x/datastructures/#werkzeug.datastructures.MultiDict
*/
abstract class MultiDict extends DataFlow::Node { }
private module MultiDictTracking {
private DataFlow::Node getlist(DataFlow::TypeTracker t) {
t.startInAttr("getlist") and
result instanceof MultiDict
or
exists(DataFlow::TypeTracker t2 | result = getlist(t2).track(t2, t))
}
DataFlow::Node getlist() { result = getlist(DataFlow::TypeTracker::end()) }
}
private class MultiDictAdditionalTaintStep extends TaintTracking::AdditionalTaintStep {
override predicate step(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
// obj -> obj.getlist
nodeTo.asCfgNode().(AttrNode).getObject("getlist") = nodeFrom.asCfgNode() and
nodeTo = MultiDictTracking::getlist()
or
// getlist -> getlist()
nodeFrom = MultiDictTracking::getlist() and
nodeTo.asCfgNode().(CallNode).getFunction() = nodeFrom.asCfgNode()
}
}
// ---------------------------------------------------------------------- //
// FileStorage //
// ---------------------------------------------------------------------- //