Python: Update taint-tracking to use new points-to API.

This commit is contained in:
Mark Shannon
2019-04-05 10:40:53 +01:00
parent 3c30480845
commit 782311f805
5 changed files with 56 additions and 42 deletions

View File

@@ -94,6 +94,10 @@ class ModuleValue extends Value {
result = this.(ModuleObjectInternal).getName()
}
Module getScope() {
result = this.(ModuleObjectInternal).getSourceModule()
}
}
module Module {
@@ -128,6 +132,10 @@ class CallableValue extends Value {
none()
}
Function getScope() {
result = this.(PythonFunctionObjectInternal).getScope()
}
}
class ClassValue extends Value {

View File

@@ -133,12 +133,17 @@ abstract class TaintKind extends string {
)
}
/** DEPRECATED -- Use getType() instead */
ClassObject getClass() {
none()
}
/** Gets the class of this kind of taint.
* For example, if this were a kind of string taint
* the `result` would be `theStrType()`.
*/
ClassObject getClass() {
none()
ClassValue getType() {
result.getSource() = this.getClass()
}
/** Gets the boolean values (may be one, neither, or both) that
@@ -194,7 +199,7 @@ class SequenceKind extends CollectionKind {
mod.getOp() instanceof Mod and
mod.getAnOperand() = fromnode and
result = this.getItem() and
result.getClass() = theStrType()
result.getType() = Value::named("str")
)
}
@@ -279,7 +284,7 @@ module DictKind {
predicate flowStep(ControlFlowNode fromnode, ControlFlowNode tonode) {
TaintFlowImplementation::copyCall(fromnode, tonode)
or
tonode.(CallNode).getFunction().refersTo(theDictType()) and
tonode.(CallNode).getFunction().pointsTo(Value::named("dict")) and
tonode.(CallNode).getArg(0) = fromnode
}
@@ -947,8 +952,8 @@ library module TaintFlowImplementation {
pragma [noinline]
private predicate import_flow(TaintedNode fromnode, ImportExprNode tonode, CallContext tocontext, string name) {
exists(ModuleObject mod |
tonode.refersTo(mod) and
exists(ModuleValue mod |
tonode.pointsTo(mod) and
module_attribute_tainted(mod, name, fromnode) and
tocontext.appliesTo(tonode)
)
@@ -965,9 +970,9 @@ library module TaintFlowImplementation {
pragma [noinline]
predicate from_import_step(TaintedNode fromnode, TrackedValue totaint, CallContext tocontext, ControlFlowNode tonode) {
exists(string name, ImportExprNode fmod, ModuleObject mod |
exists(string name, ImportExprNode fmod, ModuleValue mod |
fmod = tonode.(ImportMemberNode).getModule(name) and
fmod.refersTo(mod) and
fmod.pointsTo(mod) and
tocontext.appliesTo(tonode) and
module_attribute_tainted(mod, name, fromnode) and
totaint = fromnode.getTrackedValue()
@@ -977,7 +982,7 @@ library module TaintFlowImplementation {
pragma [noinline]
predicate getattr_step(TaintedNode fromnode, TrackedValue totaint, CallContext tocontext, CallNode tonode) {
exists(ControlFlowNode arg, string name |
tonode.getFunction().refersTo(Object::builtin("getattr")) and
tonode.getFunction().pointsTo(Value::named("getattr")) and
arg = tonode.getArg(0) and
name = tonode.getArg(1).getNode().(StrConst).getText() and
arg = fromnode.getNode() and
@@ -1017,11 +1022,11 @@ library module TaintFlowImplementation {
)
}
predicate module_attribute_tainted(ModuleObject m, string name, TaintedNode origin) {
predicate module_attribute_tainted(ModuleValue m, string name, TaintedNode origin) {
exists(EssaVariable var, CallContext c |
var.getName() = name and
BaseFlow::reaches_exit(var) and
var.getScope() = m.getModule() and
var.getScope() = m.getScope() and
tainted_var(var, c, origin) and
c = TTop()
)
@@ -1062,9 +1067,9 @@ library module TaintFlowImplementation {
}
predicate self_init_end_transfer(EssaVariable self, CallContext callee, CallNode call, CallContext caller) {
exists(ClassObject cls, Function init |
PointsTo::instantiation(call, _, cls) and
init = cls.lookupAttribute("__init__").(FunctionObject).getFunction() and
exists(ClassValue cls, Function init |
call.getFunction().pointsTo(cls) and
init = cls.attr("__init__").(CallableValue).getScope() and
self.getSourceVariable().(Variable).isSelf() and self.getScope() = init
|
callee = caller.getCallee(call)
@@ -1198,10 +1203,10 @@ library module TaintFlowImplementation {
predicate parameter_step(CallContext caller, ControlFlowNode argument, CallContext callee, NameNode param) {
exists(ParameterDefinition def |
def.getDefiningNode() = param and
exists(FunctionObject func, CallNode call |
exists(int n | argument = func.getArgumentForCall(call, n) and param.getNode() = func.getFunction().getArg(n))
exists(CallableValue func, CallNode call |
exists(int n | argument = func.getArgumentForCall(call, n) and param.getNode() = func.getScope().getArg(n))
or
exists(string name | argument = func.getNamedArgumentForCall(call, name) and param.getNode() = func.getFunction().getArgByName(name))
exists(string name | argument = func.getNamedArgumentForCall(call, name) and param.getNode() = func.getScope().getArgByName(name))
or
class_initializer_argument(_, _, call, func, argument, param)
|
@@ -1211,11 +1216,11 @@ library module TaintFlowImplementation {
}
pragma [noinline]
predicate class_initializer_argument(ClassObject cls, int n, CallNode call, FunctionObject func, ControlFlowNode argument, NameNode param) {
PointsTo::instantiation(call, _, cls) and
cls.lookupAttribute("__init__") = func and
predicate class_initializer_argument(ClassValue cls, int n, CallNode call, CallableValue func, ControlFlowNode argument, NameNode param) {
call.getFunction().pointsTo(cls) and
cls.attr("__init__") = func and
call.getArg(n) = argument and
param.getNode() = func.getFunction().getArg(n+1)
param.getNode() = func.getScope().getArg(n+1)
}
pragma [noinline]
@@ -1257,15 +1262,15 @@ library module TaintFlowImplementation {
not Filters::isinstance(test.getTest(), _, var.getSourceVariable().getAUse()) and
not boolean_filter(test.getTest(), var.getSourceVariable().getAUse())
or
exists(ControlFlowNode c, ClassObject cls |
exists(ControlFlowNode c, ClassValue cls |
Filters::isinstance(test.getTest(), c, var.getSourceVariable().getAUse())
and c.refersTo(cls)
and c.pointsTo(cls)
|
test.getSense() = true and not exists(kind.getClass())
or
test.getSense() = true and kind.getClass().getAnImproperSuperType() = cls
test.getSense() = true and kind.getClass().getASuperType() = cls
or
test.getSense() = false and not kind.getClass().getAnImproperSuperType() = cls
test.getSense() = false and not kind.getType().getASuperType() = cls
)
or
test.getSense() = test_evaluates(test.getTest(), var.getSourceVariable().getAUse(), kind)
@@ -1311,8 +1316,9 @@ library module TaintFlowImplementation {
pragma [noinline]
predicate tainted_import_star(ImportStarRefinement def, CallContext context, TaintedNode origin) {
exists(ModuleObject mod, string name |
PointsTo::Flow::module_and_name_for_import_star(mod, name, def, _) |
exists(ModuleValue mod, string name |
PointsTo::pointsTo(def.getDefiningNode().(ImportStarNode).getModule(), _, mod, _) and
name = def.getSourceVariable().getName() |
if mod.exports(name) then (
/* Attribute from imported module */
module_attribute_tainted(mod, name, origin) and
@@ -1362,7 +1368,7 @@ library module TaintFlowImplementation {
tonode.getArg(0) = fromnode
)
or
tonode.getFunction().refersTo(Object::builtin("reversed")) and
tonode.getFunction().pointsTo(Value::named("reversed")) and
tonode.getArg(0) = fromnode
}
@@ -1501,11 +1507,11 @@ class CallContext extends TCallContext {
f.getFunction() = s and f.getACall() = call
)
or
exists(ClassObject cls,CallNode call |
exists(ClassValue cls,CallNode call |
this = TCalleeContext(call, _, _) and
PointsTo::instantiation(call, _, cls) and
s = cls.lookupAttribute("__init__").(FunctionObject).getFunction() and
call.getFunction().refersTo(cls)
call.getFunction().pointsTo(cls) and
s = cls.attr("__init__").(CallableValue).getScope() and
call.getFunction().pointsTo(cls)
)
}
@@ -1625,7 +1631,7 @@ pragma [noinline]
private predicate dict_construct(ControlFlowNode itemnode, ControlFlowNode dictnode) {
dictnode.(DictNode).getAValue() = itemnode
or
dictnode.(CallNode).getFunction().refersTo(theDictType()) and
dictnode.(CallNode).getFunction().pointsTo(Value::named("dict")) and
dictnode.(CallNode).getArgByName(_) = itemnode
}
@@ -1648,11 +1654,11 @@ private predicate sequence_call(ControlFlowNode fromnode, CallNode tonode) {
tonode.getArg(0) = fromnode and
exists(ControlFlowNode cls |
cls = tonode.getFunction() |
cls.refersTo(theListType())
cls.pointsTo(Value::named("list"))
or
cls.refersTo(theTupleType())
cls.pointsTo(Value::named("tuple"))
or
cls.refersTo(theSetType())
cls.pointsTo(Value::named("set"))
)
}

View File

@@ -27,8 +27,8 @@ abstract class StringKind extends TaintKind {
result = this and copy_call(fromnode, tonode)
}
override ClassObject getClass() {
result = theStrType() or result = theUnicodeType()
override ClassValue getType() {
result = Value::named("bytes") or result = Value::named("str") or result = Value::named("unicode")
}
}

View File

@@ -11,8 +11,8 @@ class PyramidRequest extends BaseWebobRequest {
this = "pyramid.request"
}
override ClassObject getClass() {
result = ModuleObject::named("pyramid.request").attr("Request")
override ClassValue getType() {
result = Value::named("pyramid.request.Request")
}
}

View File

@@ -44,8 +44,8 @@ class WebobRequest extends BaseWebobRequest {
this = "webob.Request"
}
override ClassObject getClass() {
result = ModuleObject::named("webob.request").attr("Request")
override ClassValue getType() {
result = Value::named("webob.request.Request")
}
}