Python: Basic support for TurboGears: requests and responses.

This commit is contained in:
Mark Shannon
2019-02-19 16:52:09 +00:00
parent 681ff0f39c
commit 26c5ebde54
8 changed files with 171 additions and 4 deletions

View File

@@ -174,6 +174,14 @@ class Function extends Function_, Scope, AstNode {
Scope.super.contains(inner)
}
/** Gets a control flow node for a return value of this function */
ControlFlowNode getAReturnValueFlowNode() {
exists(Return ret |
ret.getScope() = this and
ret.getValue() = result.getNode()
)
}
}
/** A def statement. Note that FunctionDef extends Assign as a function definition binds the newly created function */

View File

@@ -160,10 +160,7 @@ class PyFunctionObject extends FunctionObject {
/** Gets a control flow node corresponding to the value of a return statement */
ControlFlowNode getAReturnedNode() {
exists(Return ret |
ret.getScope() = this.getFunction() and
result.getNode() = ret.getValue()
)
result = this.getFunction().getAReturnValueFlowNode()
}
override string descriptiveString() {

View File

@@ -4,3 +4,4 @@ import semmle.python.web.tornado.Request
import semmle.python.web.pyramid.Request
import semmle.python.web.twisted.Request
import semmle.python.web.bottle.Request
import semmle.python.web.turbogears.Request

View File

@@ -4,3 +4,4 @@ import semmle.python.web.pyramid.Response
import semmle.python.web.tornado.Response
import semmle.python.web.twisted.Response
import semmle.python.web.bottle.Response
import semmle.python.web.turbogears.Response

View File

@@ -0,0 +1,33 @@
import python
import semmle.python.security.strings.Untrusted
import TurboGears
private class ValidatedMethodParameter extends Parameter {
ValidatedMethodParameter() {
exists(string name, TurboGearsControllerMethod method |
method.getArgByName(name) = this and
method.getValidationDict().getItem(_).(KeyValuePair).getKey().(StrConst).getText() = name
)
}
}
class UnvalidatedControllerMethodParameter extends TaintSource {
UnvalidatedControllerMethodParameter() {
exists(Parameter p |
any(TurboGearsControllerMethod m | not m.getName() = "onerror").getAnArg() = p and
not p instanceof ValidatedMethodParameter and
not p.isSelf() and
p.(Name).getAFlowNode() = this
)
}
override predicate isSourceOf(TaintKind kind) {
kind instanceof UntrustedStringKind
}
}

View File

@@ -0,0 +1,38 @@
import python
import semmle.python.security.TaintTracking
import semmle.python.security.strings.Untrusted
import TurboGears
class ControllerMethodReturnValue extends TaintSink {
ControllerMethodReturnValue() {
exists(TurboGearsControllerMethod m |
m.getAReturnValueFlowNode() = this and
not m.isTemplated()
)
}
override predicate sinks(TaintKind kind) {
kind instanceof ExternalStringKind
}
}
class ControllerMethodTemplatedReturnValue extends TaintSink {
ControllerMethodTemplatedReturnValue() {
exists(TurboGearsControllerMethod m |
m.getAReturnValueFlowNode() = this and
m.isTemplated()
)
}
override predicate sinks(TaintKind kind) {
kind instanceof ExternalStringDictKind
}
}

View File

@@ -0,0 +1,59 @@
import python
import semmle.python.security.TaintTracking
private ClassObject theTurboGearsControllerClass() {
result = ModuleObject::named("tg").getAttribute("TGController")
}
ClassObject aTurboGearsControllerClass() {
result.getASuperType() = theTurboGearsControllerClass()
}
class TurboGearsControllerMethod extends Function {
ControlFlowNode decorator;
TurboGearsControllerMethod() {
aTurboGearsControllerClass().getPyClass() = this.getScope() and
decorator = this.getADecorator().getAFlowNode() and
/* Is decorated with @expose or @expose(path) */
(
decorator.(NameNode).getId() = "expose"
or
decorator.(CallNode).getFunction().(NameNode).getId() = "expose"
or
decorator.refersTo(ModuleObject::named("tg").getAttribute("expose"))
or
decorator.refersTo(_, ModuleObject::named("tg").getAttribute("expose"), _)
)
}
private ControlFlowNode templateName() {
result = decorator.(CallNode).getArg(0)
}
predicate isTemplated() {
exists(templateName())
}
string getTemplateName() {
exists(StringObject str |
templateName().refersTo(str) and
result = str.getText()
)
}
Dict getValidationDict() {
exists(Call call, Object dict |
call = this.getADecorator() and
call.getFunc().(Name).getId() = "validate" and
call.getArg(0).refersTo(dict) and
result = dict.getOrigin()
)
}
}

View File

@@ -0,0 +1,30 @@
def validate(validators):
def validator(func):
return func
def expose(*args):
if cond:
return args[0]
def with_template(func):
func
return with_template
class TGController(object):
pass
class TurboGearsContextMember(object):
"""Member of the TurboGears request context.
Provides access to turbogears context members
like request, response, template context and so on
"""
def __init__(self, name):
self.__dict__['name'] = name
def _current_obj(self):
return getattr(context, self.name)
request = TurboGearsContextMember(name="request")
response = TurboGearsContextMember(name="response")