Add instance taint steps for requests

This commit is contained in:
Joe Farebrother
2024-04-22 16:03:39 +01:00
parent 88e3227ed0
commit f85ee38e04
2 changed files with 104 additions and 3 deletions

View File

@@ -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
/**
@@ -84,4 +85,47 @@ module Pyramid {
DataFlow::Node getViewArg() { result = [this.getArg(0), this.getArgByName("view")] }
}
}
module Request {
abstract class InstanceSource extends DataFlow::LocalSourceNode { }
/** 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() }
}
}
}

View File

@@ -4,9 +4,66 @@ from pyramid.config import Configurator
@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):