Python: Add self.request as RemoteFlowSource for aiohttp View

Just like we do for Django in
7393443f8c/python/ql/src/semmle/python/frameworks/Django.qll (L1786-L1804)
This commit is contained in:
Rasmus Wriedt Larsen
2021-06-01 17:32:56 +02:00
parent c4b618dcf5
commit c69b857662
4 changed files with 55 additions and 31 deletions

View File

@@ -10,6 +10,7 @@ private import semmle.python.dataflow.new.TaintTracking
private import semmle.python.Concepts
private import semmle.python.ApiGraphs
private import semmle.python.frameworks.internal.PoorMansFunctionResolution
private import semmle.python.frameworks.internal.SelfRefMixin
private import semmle.python.frameworks.Multidict
private import semmle.python.frameworks.Yarl
@@ -251,7 +252,7 @@ module AiohttpWebModel {
}
/** A class that we consider a aiohttp.web View class. */
abstract class AiohttpViewClass extends Class {
abstract class AiohttpViewClass extends Class, SelfRefMixin {
/** Gets a function that could handle incoming requests, if any. */
Function getARequestHandler() {
// TODO: This doesn't handle attribute assignment. Should be OK, but analysis is not as complete as with
@@ -341,16 +342,23 @@ module AiohttpWebModel {
this.getParameter() =
max(Parameter param, int i | param = requestHandler.getArg(i) | param order by i)
)
or
exists(AiohttpViewClass vc |
// TODO
none()
)
}
override string getSourceType() { result = "aiohttp.web.Request" }
}
class AiohttpViewClassRequestAttributeRead extends Request::InstanceSource,
RemoteFlowSource::Range, DataFlow::Node {
AiohttpViewClassRequestAttributeRead() {
this.(DataFlow::AttrRead).getObject() = any(AiohttpViewClass vc).getASelfRef() and
this.(DataFlow::AttrRead).getAttributeName() = "request"
}
override string getSourceType() {
result = "aiohttp.web.Request from self.request in View class"
}
}
/**
* Taint propagation for `aiohttp.web.Request`.
*

View File

@@ -12,6 +12,7 @@ private import semmle.python.ApiGraphs
private import semmle.python.frameworks.PEP249
private import semmle.python.regex
private import semmle.python.frameworks.internal.PoorMansFunctionResolution
private import semmle.python.frameworks.internal.SelfRefMixin
/**
* Provides models for the `django` PyPI package.
@@ -1388,31 +1389,7 @@ private module PrivateDjango {
// Helpers
// ---------------------------------------------------------------------------
/** Adds the `getASelfRef` member predicate when modeling a class. */
abstract private class SelfRefMixin extends Class {
/**
* Gets a reference to instances of this class, originating from a self parameter of
* a method defined on this class.
*
* Note: TODO: This doesn't take MRO into account
* Note: TODO: This doesn't take staticmethod/classmethod into account
*/
private DataFlow::LocalSourceNode getASelfRef(DataFlow::TypeTracker t) {
t.start() and
result.(DataFlow::ParameterNode).getParameter() = this.getAMethod().getArg(0)
or
exists(DataFlow::TypeTracker t2 | result = this.getASelfRef(t2).track(t2, t))
}
/**
* Gets a reference to instances of this class, originating from a self parameter of
* a method defined on this class.
*
* Note: TODO: This doesn't take MRO into account
* Note: TODO: This doesn't take staticmethod/classmethod into account
*/
DataFlow::Node getASelfRef() { this.getASelfRef(DataFlow::TypeTracker::end()).flowsTo(result) }
}
// ---------------------------------------------------------------------------
// Form and form field modeling

View File

@@ -0,0 +1,38 @@
/**
* INTERNAL: Do not use.
*
* Provides the `SelfRefMixin` class.
*/
private import python
private import semmle.python.dataflow.new.DataFlow
/**
* INTERNAL: Do not use.
*
* Adds the `getASelfRef` member predicate when modeling a class.
*/
abstract class SelfRefMixin extends Class {
/**
* Gets a reference to instances of this class, originating from a self parameter of
* a method defined on this class.
*
* Note: TODO: This doesn't take MRO into account
* Note: TODO: This doesn't take staticmethod/classmethod into account
*/
private DataFlow::LocalSourceNode getASelfRef(DataFlow::TypeTracker t) {
t.start() and
result.(DataFlow::ParameterNode).getParameter() = this.getAMethod().getArg(0)
or
exists(DataFlow::TypeTracker t2 | result = this.getASelfRef(t2).track(t2, t))
}
/**
* Gets a reference to instances of this class, originating from a self parameter of
* a method defined on this class.
*
* Note: TODO: This doesn't take MRO into account
* Note: TODO: This doesn't take staticmethod/classmethod into account
*/
DataFlow::Node getASelfRef() { this.getASelfRef(DataFlow::TypeTracker::end()).flowsTo(result) }
}

View File

@@ -196,7 +196,8 @@ async def test_taint(request: web.Request): # $ requestHandler
class TaintTestClass(web.View):
def get(self): # $ requestHandler
ensure_tainted(
self.request, # $ MISSING: tainted
self.request, # $ tainted
self.request.url # $ tainted
)