Skip to content

Commit

Permalink
Add instance taint steps for requests
Browse files Browse the repository at this point in the history
  • Loading branch information
joefarebrother committed Apr 22, 2024
1 parent 88e3227 commit f85ee38
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 3 deletions.
44 changes: 44 additions & 0 deletions python/ql/lib/semmle/python/frameworks/Pyramid.qll
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ private import semmle.python.Concepts
private import semmle.python.ApiGraphs
private import semmle.python.dataflow.new.FlowSummary
private import semmle.python.frameworks.internal.PoorMansFunctionResolution
private import semmle.python.frameworks.internal.InstanceTaintStepsHelper
private import semmle.python.frameworks.data.ModelsAsData

/**
Expand Down Expand Up @@ -84,4 +85,47 @@ module Pyramid {
DataFlow::Node getViewArg() { result = [this.getArg(0), this.getArgByName("view")] }

Check warning on line 85 in python/ql/lib/semmle/python/frameworks/Pyramid.qll

View workflow job for this annotation

GitHub Actions / qldoc

Missing QLdoc for member-predicate Pyramid::Pyramid::Configurator::AddViewCall::getViewArg/0
}
}

module Request {

Check warning on line 89 in python/ql/lib/semmle/python/frameworks/Pyramid.qll

View workflow job for this annotation

GitHub Actions / qldoc

Missing QLdoc for module Pyramid::Pyramid::Request
abstract class InstanceSource extends DataFlow::LocalSourceNode { }

Check warning on line 90 in python/ql/lib/semmle/python/frameworks/Pyramid.qll

View workflow job for this annotation

GitHub Actions / qldoc

Missing QLdoc for class Pyramid::Pyramid::Request::InstanceSource

/** Gets a reference to an instance of `pyramid.request.Request`. */
private DataFlow::TypeTrackingNode 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 `pyramid.request.Request`. */
DataFlow::Node instance() { instance(DataFlow::TypeTracker::end()).flowsTo(result) }

private class RequestParameter extends InstanceSource, DataFlow::ParameterNode {
RequestParameter() { this.getParameter() = any(View::ViewCallable vc).getRequestParameter() }
}

private class InstanceTaintSteps extends InstanceTaintStepsHelper {
InstanceTaintSteps() { this = "pyramid.request.Request" }

override DataFlow::Node getInstance() { result = instance() }

override string getAttributeName() {
result in [
"accept", "accept_charset", "accept_encoding", "accept_language", "application_url",
"as_bytes", "authorization", "body", "body_file", "body_file_raw", "body_file_seekable",
"cache_control", "client_addr", "content_type", "cookies", "domain", "headers", "host",
"host_port", "host_url", "GET", "if_match", "if_none_match", "if_range",
"if_none_match", "json", "json_body", "params", "path", "path_info", "path_qs",
"path_url", "POST", "pragma", "query_string", "range", "referer", "referrer", "text",
"url", "urlargs", "urlvars", "user_agent"
]
}

override string getMethodName() {
result in ["as_bytes", "copy", "copy_body", "copy_get", "path_info_peek", "path_info_pop"]
}

override string getAsyncMethodName() { none() }
}
}
}
63 changes: 60 additions & 3 deletions python/ql/test/library-tests/frameworks/pyramid/pyramid_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,66 @@
@view_config(route_name="test1")
def test1(request):
ensure_tainted(
request, # $ tainted
request.body, # $ MISSING:tainted
request.GET['a'] # $ MISSING:tainted
request, # $ tainted

request.accept, # $ tainted
request.accept_charset, # $ tainted
request.accept_encoding, # $ tainted
request.accept_language, # $ tainted
request.authorization, # $ tainted
request.cache_control, # $ tainted
request.client_addr, # $ tainted
request.content_type, # $ tainted
request.domain, # $ tainted
request.host, # $ tainted
request.host_port, # $ tainted
request.host_url, # $ tainted
request.if_match, # $ tainted
request.if_none_match, # $ tainted
request.if_range, # $ tainted
request.pragma, # $ tainted
request.range, # $ tainted
request.referer, # $ tainted
request.referrer, # $ tainted
request.user_agent, # $ tainted

request.as_bytes, # $ tainted

request.body, # $ tainted
request.body_file, # $ tainted
request.body_file_raw, # $ tainted
request.body_file_seekable,# $ tainted
request.body_file.read(), # $ MISSING:tainted

request.json, # $ tainted
request.json_body, # $ tainted
request.json['a']['b'][0]['c'], # $ tainted

request.text, # $ tainted

request.path, # $ tainted
request.path_info, # $ tainted
request.path_info_peek(), # $ tainted
request.path_info_pop(), # $ tainted
request.path_qs, # $ tainted
request.path_url, # $ tainted
request.query_string, # $ tainted

request.url, # $ tainted
request.urlargs, # $ tainted
request.urlvars, # $ tainted

request.GET['a'], # $ tainted
request.POST['b'], # $ tainted
request.cookies['c'], # $ tainted
request.params['d'], # $ tainted
request.headers['X-My-Header'], # $ tainted
request.GET.values(), # $ tainted

request.copy(), # $ tainted
request.copy_body(), # $ tainted
request.copy_get(), # $ tainted
request.copy().GET['a'] # $ MISSING:tainted
)

def test2(request):
Expand Down

0 comments on commit f85ee38

Please sign in to comment.