delete old deprecations

This commit is contained in:
erik-krogh
2023-06-12 11:33:17 +02:00
parent 1d65284011
commit ae8bf5ed3c
176 changed files with 0 additions and 5913 deletions

View File

@@ -1,103 +0,0 @@
/**
* Provides classes and predicates for tracking exceptions and information
* associated with exceptions.
*/
import python
import semmle.python.dataflow.TaintTracking
import semmle.python.security.strings.Basic
deprecated private Value traceback_function(string name) {
result = Module::named("traceback").attr(name)
}
/**
* This represents information relating to an exception, for instance the
* message, arguments or parts of the exception traceback.
*/
deprecated class ExceptionInfo extends StringKind {
ExceptionInfo() { this = "exception.info" }
override string repr() { result = "exception info" }
}
/**
* A class representing sources of information about
* execution state exposed in tracebacks and the like.
*/
abstract deprecated class ErrorInfoSource extends TaintSource { }
/**
* This kind represents exceptions themselves.
*/
deprecated class ExceptionKind extends TaintKind {
ExceptionKind() { this = "exception.kind" }
override string repr() { result = "exception" }
override TaintKind getTaintOfAttribute(string name) {
name = "args" and result instanceof ExceptionInfoSequence
or
name = "message" and result instanceof ExceptionInfo
}
}
/**
* A source of exception objects, either explicitly created, or captured by an
* `except` statement.
*/
deprecated class ExceptionSource extends ErrorInfoSource {
ExceptionSource() {
exists(ClassValue cls |
cls.getASuperType() = ClassValue::baseException() and
this.(ControlFlowNode).pointsTo().getClass() = cls
)
or
this = any(ExceptStmt s).getName().getAFlowNode()
}
override string toString() { result = "exception.source" }
override predicate isSourceOf(TaintKind kind) { kind instanceof ExceptionKind }
}
/**
* Represents a sequence of pieces of information relating to an exception,
* for instance the contents of the `args` attribute, or the stack trace.
*/
deprecated class ExceptionInfoSequence extends SequenceKind {
ExceptionInfoSequence() { this.getItem() instanceof ExceptionInfo }
}
/**
* Represents calls to functions in the `traceback` module that return
* sequences of exception information.
*/
deprecated class CallToTracebackFunction extends ErrorInfoSource {
CallToTracebackFunction() {
exists(string name |
name in [
"extract_tb", "extract_stack", "format_list", "format_exception_only", "format_exception",
"format_tb", "format_stack"
]
|
this = traceback_function(name).getACall()
)
}
override string toString() { result = "exception.info.sequence.source" }
override predicate isSourceOf(TaintKind kind) { kind instanceof ExceptionInfoSequence }
}
/**
* Represents calls to functions in the `traceback` module that return a single
* string of information about an exception.
*/
deprecated class FormattedTracebackSource extends ErrorInfoSource {
FormattedTracebackSource() { this = traceback_function("format_exc").getACall() }
override string toString() { result = "exception.info.source" }
override predicate isSourceOf(TaintKind kind) { kind instanceof ExceptionInfo }
}

View File

@@ -1,16 +0,0 @@
import semmle.python.dataflow.Implementation
deprecated module TaintTrackingPaths {
predicate edge(TaintTrackingNode src, TaintTrackingNode dest, string label) {
exists(TaintTrackingNode source, TaintTrackingNode sink |
source.getConfiguration().hasFlowPath(source, sink) and
source.getASuccessor*() = src and
src.getASuccessor(label) = dest and
dest.getASuccessor*() = sink
)
}
}
deprecated query predicate edges(TaintTrackingNode fromnode, TaintTrackingNode tonode) {
TaintTrackingPaths::edge(fromnode, tonode, _)
}

View File

@@ -1,263 +0,0 @@
/**
* Provides class and predicates to track external data that
* may represent malicious OS commands.
*
* This module is intended to be imported into a taint-tracking query
* to extend `TaintKind` and `TaintSink`.
*/
import python
import semmle.python.dataflow.TaintTracking
import semmle.python.security.strings.Untrusted
/** Abstract taint sink that is potentially vulnerable to malicious shell commands. */
abstract deprecated class CommandSink extends TaintSink { }
deprecated private ModuleObject osOrPopenModule() { result.getName() = ["os", "popen2"] }
deprecated private Object makeOsCall() {
exists(string name | result = ModuleObject::named("subprocess").attr(name) |
name = ["Popen", "call", "check_call", "check_output", "run"]
)
}
/**Special case for first element in sequence. */
deprecated class FirstElementKind extends TaintKind {
FirstElementKind() { this = "sequence[" + any(ExternalStringKind key) + "][0]" }
override string repr() { result = "first item in sequence of " + this.getItem().repr() }
/** Gets the taint kind for item in this sequence. */
ExternalStringKind getItem() { this = "sequence[" + result + "][0]" }
}
deprecated class FirstElementFlow extends DataFlowExtension::DataFlowNode {
FirstElementFlow() { this = any(SequenceNode s).getElement(0) }
override ControlFlowNode getASuccessorNode(TaintKind fromkind, TaintKind tokind) {
result.(SequenceNode).getElement(0) = this and tokind.(FirstElementKind).getItem() = fromkind
}
}
/**
* A taint sink that is potentially vulnerable to malicious shell commands.
* The `vuln` in `subprocess.call(shell=vuln)` and similar calls.
*/
deprecated class ShellCommand extends CommandSink {
override string toString() { result = "shell command" }
ShellCommand() {
exists(CallNode call, Object istrue |
call.getFunction().refersTo(makeOsCall()) and
call.getAnArg() = this and
call.getArgByName("shell").refersTo(istrue) and
istrue.booleanValue() = true
)
or
exists(CallNode call, string name |
call.getAnArg() = this and
call.getFunction().refersTo(osOrPopenModule().attr(name))
|
name = ["system", "popen"] or
name.matches("popen_")
)
or
exists(CallNode call |
call.getAnArg() = this and
call.getFunction().refersTo(ModuleObject::named("commands"))
)
}
override predicate sinks(TaintKind kind) {
/* Tainted string command */
kind instanceof ExternalStringKind
or
/* List (or tuple) containing a tainted string command */
kind instanceof ExternalStringSequenceKind
}
}
/**
* A taint sink that is potentially vulnerable to malicious shell commands.
* The `vuln` in `subprocess.call(vuln, ...)` and similar calls.
*/
deprecated class OsCommandFirstArgument extends CommandSink {
override string toString() { result = "OS command first argument" }
OsCommandFirstArgument() {
not this instanceof ShellCommand and
exists(CallNode call |
call.getFunction().refersTo(makeOsCall()) and
call.getArg(0) = this
)
}
override predicate sinks(TaintKind kind) {
/* Tainted string command */
kind instanceof ExternalStringKind
or
/* List (or tuple) whose first element is tainted */
kind instanceof FirstElementKind
}
}
// -------------------------------------------------------------------------- //
// Modeling of the 'invoke' package and 'fabric' package (v 2.x)
//
// Since fabric build so closely upon invoke, we model them together to avoid
// duplication
// -------------------------------------------------------------------------- //
/**
* A taint sink that is potentially vulnerable to malicious shell commands.
* The `vuln` in `invoke.run(vuln, ...)` and similar calls.
*/
deprecated class InvokeRun extends CommandSink {
InvokeRun() {
this = Value::named("invoke.run").(FunctionValue).getArgumentForCall(_, 0)
or
this = Value::named("invoke.sudo").(FunctionValue).getArgumentForCall(_, 0)
}
override string toString() { result = "InvokeRun" }
override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind }
}
/**
* Internal TaintKind to track the invoke.Context instance passed to functions
* marked with @invoke.task
*/
deprecated private class InvokeContextArg extends TaintKind {
InvokeContextArg() { this = "InvokeContextArg" }
}
/** Internal TaintSource to track the context passed to functions marked with @invoke.task */
deprecated private class InvokeContextArgSource extends TaintSource {
InvokeContextArgSource() {
exists(Function f, Expr decorator |
count(f.getADecorator()) = 1 and
(
decorator = f.getADecorator() and not decorator instanceof Call
or
decorator = f.getADecorator().(Call).getFunc()
) and
(
decorator.pointsTo(Value::named("invoke.task"))
or
decorator.pointsTo(Value::named("fabric.task"))
)
|
this.(ControlFlowNode).getNode() = f.getArg(0)
)
}
override predicate isSourceOf(TaintKind kind) { kind instanceof InvokeContextArg }
}
/**
* A taint sink that is potentially vulnerable to malicious shell commands.
* The `vuln` in `invoke.Context().run(vuln, ...)` and similar calls.
*/
deprecated class InvokeContextRun extends CommandSink {
InvokeContextRun() {
exists(CallNode call |
any(InvokeContextArg k).taints(call.getFunction().(AttrNode).getObject("run"))
or
call = Value::named("invoke.Context").(ClassValue).lookup("run").getACall()
or
// fabric.connection.Connection is a subtype of invoke.context.Context
// since fabric.Connection.run has a decorator, it doesn't work with FunctionValue :|
// and `Value::named("fabric.Connection").(ClassValue).lookup("run").getACall()` returned no results,
// so here is the hacky solution that works :\
call.getFunction().(AttrNode).getObject("run").pointsTo().getClass() =
Value::named("fabric.Connection")
|
this = call.getArg(0)
or
this = call.getArgByName("command")
)
}
override string toString() { result = "InvokeContextRun" }
override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind }
}
/**
* A taint sink that is potentially vulnerable to malicious shell commands.
* The `vuln` in `fabric.Group().run(vuln, ...)` and similar calls.
*/
deprecated class FabricGroupRun extends CommandSink {
FabricGroupRun() {
exists(ClassValue cls |
cls.getASuperType() = Value::named("fabric.Group") and
this = cls.lookup("run").(FunctionValue).getArgumentForCall(_, 1)
)
}
override string toString() { result = "FabricGroupRun" }
override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind }
}
// -------------------------------------------------------------------------- //
// Modeling of the 'invoke' package and 'fabric' package (v 1.x)
// -------------------------------------------------------------------------- //
deprecated class FabricV1Commands extends CommandSink {
FabricV1Commands() {
// since `run` and `sudo` are decorated, we can't use FunctionValue's :(
exists(CallNode call |
call = Value::named("fabric.api.local").getACall()
or
call = Value::named("fabric.api.run").getACall()
or
call = Value::named("fabric.api.sudo").getACall()
|
this = call.getArg(0)
or
this = call.getArgByName("command")
)
}
override string toString() { result = "FabricV1Commands" }
override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind }
}
/**
* An extension that propagates taint from the arguments of `fabric.api.execute(func, arg0, arg1, ...)`
* to the parameters of `func`, since this will call `func(arg0, arg1, ...)`.
*/
deprecated class FabricExecuteExtension extends DataFlowExtension::DataFlowNode {
CallNode call;
FabricExecuteExtension() {
call = Value::named("fabric.api.execute").getACall() and
(
this = call.getArg(any(int i | i > 0))
or
this = call.getArgByName(any(string s | not s = "task"))
)
}
override ControlFlowNode getASuccessorNode(TaintKind fromkind, TaintKind tokind) {
tokind = fromkind and
exists(CallableValue func |
(
call.getArg(0).pointsTo(func)
or
call.getArgByName("task").pointsTo(func)
) and
exists(int i |
// execute(func, arg0, arg1) => func(arg0, arg1)
this = call.getArg(i) and
result = func.getParameter(i - 1)
)
or
exists(string name |
this = call.getArgByName(name) and
result = func.getParameterByName(name)
)
)
}
}

View File

@@ -1,83 +0,0 @@
/**
* Provides class and predicates to track external data that
* may represent malicious SQL queries or parts of queries.
*
* This module is intended to be imported into a taint-tracking query
* to extend `TaintKind` and `TaintSink`.
*/
import python
import semmle.python.dataflow.TaintTracking
import semmle.python.security.strings.Untrusted
import semmle.python.security.SQL
deprecated private StringObject first_part(ControlFlowNode command) {
command.(BinaryExprNode).getOp() instanceof Add and
command.(BinaryExprNode).getLeft().refersTo(result)
or
exists(CallNode call, SequenceObject seq | call = command |
call = theStrType().lookupAttribute("join") and
call.getArg(0).refersTo(seq) and
seq.getInferredElement(0) = result
)
or
command.(BinaryExprNode).getOp() instanceof Mod and
command.getNode().(StrConst).getLiteralObject() = result
}
/** Holds if `command` appears to be a SQL command string of which `inject` is a part. */
deprecated predicate probable_sql_command(ControlFlowNode command, ControlFlowNode inject) {
exists(string prefix |
inject = command.getAChild*() and
first_part(command).getText().regexpMatch(" *" + prefix + ".*")
|
prefix = "CREATE" or prefix = "SELECT"
)
}
/**
* A taint kind representing a DB cursor.
* This will be overridden to provide specific kinds of DB cursor.
*/
abstract deprecated class DbCursor extends TaintKind {
bindingset[this]
DbCursor() { any() }
string getExecuteMethodName() { result = "execute" }
}
/**
* A part of a string that appears to be a SQL command and is thus
* vulnerable to malicious input.
*/
deprecated class SimpleSqlStringInjection extends SqlInjectionSink {
override string toString() { result = "simple SQL string injection" }
SimpleSqlStringInjection() { probable_sql_command(_, this) }
override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind }
}
/**
* A taint source representing sources of DB connections.
* This will be overridden to provide specific kinds of DB connection sources.
*/
abstract deprecated class DbConnectionSource extends TaintSource { }
/**
* A taint sink that is vulnerable to malicious SQL queries.
* The `vuln` in `db.connection.execute(vuln)` and similar.
*/
deprecated class DbConnectionExecuteArgument extends SqlInjectionSink {
override string toString() { result = "db.connection.execute" }
DbConnectionExecuteArgument() {
exists(CallNode call, DbCursor cursor, string name |
cursor.taints(call.getFunction().(AttrNode).getObject(name)) and
cursor.getExecuteMethodName() = name and
call.getArg(0) = this
)
}
override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind }
}

View File

@@ -1,124 +0,0 @@
import python
private import Common
import semmle.python.dataflow.TaintTracking
/** An extensible kind of taint representing any kind of string. */
abstract deprecated class StringKind extends TaintKind {
bindingset[this]
StringKind() { this = this }
override TaintKind getTaintOfMethodResult(string name) {
name in [
"capitalize", "casefold", "center", "expandtabs", "format", "format_map", "ljust", "lstrip",
"lower", "replace", "rjust", "rstrip", "strip", "swapcase", "title", "upper", "zfill",
/* encode/decode is technically not correct, but close enough */
"encode", "decode"
] and
result = this
or
name in ["partition", "rpartition", "rsplit", "split", "splitlines"] and
result.(SequenceKind).getItem() = this
}
override TaintKind getTaintForFlowStep(ControlFlowNode fromnode, ControlFlowNode tonode) {
result = this and
(
slice(fromnode, tonode) or
tonode.(BinaryExprNode).getAnOperand() = fromnode or
os_path_join(fromnode, tonode) or
str_format(fromnode, tonode) or
encode_decode(fromnode, tonode) or
to_str(fromnode, tonode) or
f_string(fromnode, tonode)
)
or
result = this and copy_call(fromnode, tonode)
}
override ClassValue getType() {
result = Value::named("bytes") or
result = Value::named("str") or
result = Value::named("unicode")
}
}
deprecated private class StringEqualitySanitizer extends Sanitizer {
StringEqualitySanitizer() { this = "string equality sanitizer" }
/* The test `if untrusted == "KNOWN_VALUE":` sanitizes `untrusted` on its `true` edge. */
override predicate sanitizingEdge(TaintKind taint, PyEdgeRefinement test) {
taint instanceof StringKind and
exists(ControlFlowNode const, Cmpop op | const.getNode() instanceof StrConst |
(
test.getTest().(CompareNode).operands(const, op, _)
or
test.getTest().(CompareNode).operands(_, op, const)
) and
(
op instanceof Eq and test.getSense() = true
or
op instanceof NotEq and test.getSense() = false
)
)
}
}
/** tonode = ....format(fromnode) */
deprecated private predicate str_format(ControlFlowNode fromnode, CallNode tonode) {
tonode.getFunction().(AttrNode).getName() = "format" and
tonode.getAnArg() = fromnode
}
/** tonode = codec.[en|de]code(fromnode) */
deprecated private predicate encode_decode(ControlFlowNode fromnode, CallNode tonode) {
exists(FunctionObject func, string name |
not func.getFunction().isMethod() and
func.getACall() = tonode and
tonode.getAnArg() = fromnode and
func.getName() = name
|
name = "encode" or
name = "decode" or
name = "decodestring"
)
}
/** tonode = str(fromnode) */
deprecated private predicate to_str(ControlFlowNode fromnode, CallNode tonode) {
tonode.getAnArg() = fromnode and
(
tonode = ClassValue::bytes().getACall()
or
tonode = ClassValue::unicode().getACall()
)
}
/** tonode = fromnode[:] */
deprecated private predicate slice(ControlFlowNode fromnode, SubscriptNode tonode) {
exists(Slice all |
all = tonode.getIndex().getNode() and
not exists(all.getStart()) and
not exists(all.getStop()) and
tonode.getObject() = fromnode
)
}
/** tonode = os.path.join(..., fromnode, ...) */
deprecated private predicate os_path_join(ControlFlowNode fromnode, CallNode tonode) {
tonode = Value::named("os.path.join").getACall() and
tonode.getAnArg() = fromnode
}
/** tonode = f"... {fromnode} ..." */
deprecated private predicate f_string(ControlFlowNode fromnode, ControlFlowNode tonode) {
tonode.getNode().(Fstring).getAValue() = fromnode.getNode()
}
/**
* A kind of "taint", representing a dictionary mapping str->"taint"
*
* DEPRECATED: Use `ExternalStringDictKind` instead.
*/
deprecated class StringDictKind extends DictKind {
StringDictKind() { this.getValue() instanceof StringKind }
}

View File

@@ -1,14 +0,0 @@
import python
/** A call that returns a copy (or similar) of the argument */
deprecated predicate copy_call(ControlFlowNode fromnode, CallNode tonode) {
tonode.getFunction().(AttrNode).getObject("copy") = fromnode
or
exists(ModuleValue copy, string name | name = "copy" or name = "deepcopy" |
copy.attr(name).(FunctionValue).getACall() = tonode and
tonode.getArg(0) = fromnode
)
or
tonode.getFunction().pointsTo(Value::named("reversed")) and
tonode.getArg(0) = fromnode
}

View File

@@ -1,318 +0,0 @@
import python
import Basic
private import Common
/**
* An extensible kind of taint representing an externally controlled string.
*/
abstract deprecated class ExternalStringKind extends StringKind {
bindingset[this]
ExternalStringKind() { this = this }
override TaintKind getTaintForFlowStep(ControlFlowNode fromnode, ControlFlowNode tonode) {
result = StringKind.super.getTaintForFlowStep(fromnode, tonode)
or
tonode.(SequenceNode).getElement(_) = fromnode and
result.(ExternalStringSequenceKind).getItem() = this
or
json_load(fromnode, tonode) and result.(ExternalJsonKind).getValue() = this
or
tonode.(DictNode).getAValue() = fromnode and result.(ExternalStringDictKind).getValue() = this
or
urlsplit(fromnode, tonode) and result.(ExternalUrlSplitResult).getItem() = this
or
urlparse(fromnode, tonode) and result.(ExternalUrlParseResult).getItem() = this
or
parse_qs(fromnode, tonode) and result.(ExternalStringDictKind).getValue() = this
or
parse_qsl(fromnode, tonode) and result.(SequenceKind).getItem().(SequenceKind).getItem() = this
}
}
/** A kind of "taint", representing a sequence, with a "taint" member */
deprecated class ExternalStringSequenceKind extends SequenceKind {
ExternalStringSequenceKind() { this.getItem() instanceof ExternalStringKind }
}
/**
* An hierarchical dictionary or list where the entire structure is externally controlled
* This is typically a parsed JSON object.
*/
deprecated class ExternalJsonKind extends TaintKind {
ExternalJsonKind() { this = "json[" + any(ExternalStringKind key) + "]" }
/** Gets the taint kind for item in this sequence */
TaintKind getValue() {
this = "json[" + result + "]"
or
result = this
}
override TaintKind getTaintForFlowStep(ControlFlowNode fromnode, ControlFlowNode tonode) {
this.taints(fromnode) and
json_subscript_taint(tonode, fromnode, this, result)
or
result = this and copy_call(fromnode, tonode)
}
override TaintKind getTaintOfMethodResult(string name) {
name = "get" and result = this.getValue()
}
}
/** A kind of "taint", representing a dictionary mapping keys to tainted strings. */
deprecated class ExternalStringDictKind extends DictKind {
ExternalStringDictKind() { this.getValue() instanceof ExternalStringKind }
}
/**
* A kind of "taint", representing a dictionary mapping keys to sequences of
* tainted strings.
*/
deprecated class ExternalStringSequenceDictKind extends DictKind {
ExternalStringSequenceDictKind() { this.getValue() instanceof ExternalStringSequenceKind }
}
/** TaintKind for the result of `urlsplit(tainted_string)` */
deprecated class ExternalUrlSplitResult extends ExternalStringSequenceKind {
// https://docs.python.org/3/library/urllib.parse.html#urllib.parse.urlsplit
override TaintKind getTaintOfAttribute(string name) {
result = super.getTaintOfAttribute(name)
or
name in [
// namedtuple field names
"scheme", "netloc", "path", "query", "fragment",
// class methods
"password", "username", "hostname",
] and
result instanceof ExternalStringKind
}
override TaintKind getTaintOfMethodResult(string name) {
result = super.getTaintOfMethodResult(name)
or
name = "geturl" and
result instanceof ExternalStringKind
}
}
/** TaintKind for the result of `urlparse(tainted_string)` */
deprecated class ExternalUrlParseResult extends ExternalStringSequenceKind {
// https://docs.python.org/3/library/urllib.parse.html#urllib.parse.urlparse
override TaintKind getTaintOfAttribute(string name) {
result = super.getTaintOfAttribute(name)
or
name in [
// namedtuple field names
"scheme", "netloc", "path", "params", "query", "fragment",
// class methods
"username", "password", "hostname",
] and
result instanceof ExternalStringKind
}
override TaintKind getTaintOfMethodResult(string name) {
result = super.getTaintOfMethodResult(name)
or
name = "geturl" and
result instanceof ExternalStringKind
}
}
/* Helper for getTaintForStep() */
pragma[noinline]
deprecated private predicate json_subscript_taint(
SubscriptNode sub, ControlFlowNode obj, ExternalJsonKind seq, TaintKind key
) {
sub.isLoad() and
sub.getObject() = obj and
key = seq.getValue()
}
deprecated private predicate json_load(ControlFlowNode fromnode, CallNode tonode) {
tonode = Value::named("json.loads").getACall() and
tonode.getArg(0) = fromnode
}
deprecated private predicate urlsplit(ControlFlowNode fromnode, CallNode tonode) {
// This could be implemented as `exists(FunctionValue` without the explicit six part,
// but then our tests will need to import +100 modules, so for now this slightly
// altered version gets to live on.
exists(Value urlsplit |
(
urlsplit = Value::named("six.moves.urllib.parse.urlsplit")
or
// Python 2
urlsplit = Value::named("urlparse.urlsplit")
or
// Python 3
urlsplit = Value::named("urllib.parse.urlsplit")
) and
tonode = urlsplit.getACall() and
tonode.getArg(0) = fromnode
)
}
deprecated private predicate urlparse(ControlFlowNode fromnode, CallNode tonode) {
// This could be implemented as `exists(FunctionValue` without the explicit six part,
// but then our tests will need to import +100 modules, so for now this slightly
// altered version gets to live on.
exists(Value urlparse |
(
urlparse = Value::named("six.moves.urllib.parse.urlparse")
or
// Python 2
urlparse = Value::named("urlparse.urlparse")
or
// Python 3
urlparse = Value::named("urllib.parse.urlparse")
) and
tonode = urlparse.getACall() and
tonode.getArg(0) = fromnode
)
}
deprecated private predicate parse_qs(ControlFlowNode fromnode, CallNode tonode) {
// This could be implemented as `exists(FunctionValue` without the explicit six part,
// but then our tests will need to import +100 modules, so for now this slightly
// altered version gets to live on.
exists(Value parse_qs |
(
parse_qs = Value::named("six.moves.urllib.parse.parse_qs")
or
// Python 2
parse_qs = Value::named("urlparse.parse_qs")
or
// Python 2 deprecated version of `urlparse.parse_qs`
parse_qs = Value::named("cgi.parse_qs")
or
// Python 3
parse_qs = Value::named("urllib.parse.parse_qs")
) and
tonode = parse_qs.getACall() and
(
tonode.getArg(0) = fromnode
or
tonode.getArgByName("qs") = fromnode
)
)
}
deprecated private predicate parse_qsl(ControlFlowNode fromnode, CallNode tonode) {
// This could be implemented as `exists(FunctionValue` without the explicit six part,
// but then our tests will need to import +100 modules, so for now this slightly
// altered version gets to live on.
exists(Value parse_qsl |
(
parse_qsl = Value::named("six.moves.urllib.parse.parse_qsl")
or
// Python 2
parse_qsl = Value::named("urlparse.parse_qsl")
or
// Python 2 deprecated version of `urlparse.parse_qsl`
parse_qsl = Value::named("cgi.parse_qsl")
or
// Python 3
parse_qsl = Value::named("urllib.parse.parse_qsl")
) and
tonode = parse_qsl.getACall() and
(
tonode.getArg(0) = fromnode
or
tonode.getArgByName("qs") = fromnode
)
)
}
/** A kind of "taint", representing an open file-like object from an external source. */
deprecated class ExternalFileObject extends TaintKind {
ExternalStringKind valueKind;
ExternalFileObject() { this = "file[" + valueKind + "]" }
/** Gets the taint kind for the contents of this file */
TaintKind getValue() { result = valueKind }
override TaintKind getTaintOfMethodResult(string name) {
name in ["read", "readline"] and result = this.getValue()
or
name = "readlines" and result.(SequenceKind).getItem() = this.getValue()
}
override TaintKind getTaintForIteration() { result = this.getValue() }
}
/**
* Temporary sanitizer for the tainted result from `urlsplit` and `urlparse`. Can be used to reduce FPs until
* we have better support for namedtuples.
*
* Will clear **all** taint on a test of the kind. That is, on the true edge of any matching test,
* all fields/indexes will be cleared of taint.
*
* Handles:
* - `if splitres.netloc == "KNOWN_VALUE"`
* - `if splitres[0] == "KNOWN_VALUE"`
*/
deprecated class UrlsplitUrlparseTempSanitizer extends Sanitizer {
// TODO: remove this once we have better support for named tuples
UrlsplitUrlparseTempSanitizer() { this = "UrlsplitUrlparseTempSanitizer" }
override predicate sanitizingEdge(TaintKind taint, PyEdgeRefinement test) {
(
taint instanceof ExternalUrlSplitResult
or
taint instanceof ExternalUrlParseResult
) and
exists(ControlFlowNode full_use |
full_use.(SubscriptNode).getObject() = test.getInput().getAUse()
or
full_use.(AttrNode).getObject() = test.getInput().getAUse()
|
this.clears_taint(full_use, test.getTest(), test.getSense())
)
}
private predicate clears_taint(ControlFlowNode tainted, ControlFlowNode test, boolean sense) {
this.test_equality_with_const(test, tainted, sense)
or
this.test_in_const_seq(test, tainted, sense)
or
test.(UnaryExprNode).getNode().getOp() instanceof Not and
exists(ControlFlowNode nested_test |
nested_test = test.(UnaryExprNode).getOperand() and
this.clears_taint(tainted, nested_test, sense.booleanNot())
)
}
/** holds for `== "KNOWN_VALUE"` on `true` edge, and `!= "KNOWN_VALUE"` on `false` edge */
private predicate test_equality_with_const(CompareNode cmp, ControlFlowNode tainted, boolean sense) {
exists(ControlFlowNode const, Cmpop op | const.getNode() instanceof StrConst |
(
cmp.operands(const, op, tainted)
or
cmp.operands(tainted, op, const)
) and
(
op instanceof Eq and sense = true
or
op instanceof NotEq and sense = false
)
)
}
/** holds for `in ["KNOWN_VALUE", ...]` on `true` edge, and `not in ["KNOWN_VALUE", ...]` on `false` edge */
private predicate test_in_const_seq(CompareNode cmp, ControlFlowNode tainted, boolean sense) {
exists(SequenceNode const_seq, Cmpop op |
forall(ControlFlowNode elem | elem = const_seq.getAnElement() |
elem.getNode() instanceof StrConst
)
|
cmp.operands(tainted, op, const_seq) and
(
op instanceof In and sense = true
or
op instanceof NotIn and sense = false
)
)
}
}

View File

@@ -1,10 +0,0 @@
import python
import External
/**
* A kind of taint representing an externally controlled string.
* This class is a simple sub-class of `ExternalStringKind`.
*/
deprecated class UntrustedStringKind extends ExternalStringKind {
UntrustedStringKind() { this = "externally controlled string" }
}

View File

@@ -1,2 +0,0 @@
import semmle.python.web.client.StdLib
import semmle.python.web.client.Requests

View File

@@ -1,119 +0,0 @@
import python
import semmle.python.dataflow.Implementation
import semmle.python.security.strings.External
import HttpConstants
/** Generic taint source from a http request */
abstract deprecated class HttpRequestTaintSource extends TaintSource { }
/**
* Taint kind representing the WSGI environment.
* As specified in PEP 3333. https://www.python.org/dev/peps/pep-3333/#environ-variables
*/
deprecated class WsgiEnvironment extends TaintKind {
WsgiEnvironment() { this = "wsgi.environment" }
override TaintKind getTaintForFlowStep(ControlFlowNode fromnode, ControlFlowNode tonode) {
result = this and Implementation::copyCall(fromnode, tonode)
or
result = this and
tonode.(CallNode).getFunction().pointsTo(ClassValue::dict()) and
tonode.(CallNode).getArg(0) = fromnode
or
exists(Value key, string text |
tonode.(CallNode).getFunction().(AttrNode).getObject("get") = fromnode and
tonode.(CallNode).getArg(0).pointsTo(key)
or
tonode.(SubscriptNode).getObject() = fromnode and
tonode.isLoad() and
tonode.(SubscriptNode).getIndex().pointsTo(key)
|
key = Value::forString(text) and
result instanceof ExternalStringKind and
(
text = "QUERY_STRING" or
text = "PATH_INFO" or
text.matches("HTTP\\_%")
)
)
}
}
/**
* A standard morsel object from a HTTP request, a value in a cookie,
* typically an instance of `http.cookies.Morsel`
*/
deprecated class UntrustedMorsel extends TaintKind {
UntrustedMorsel() { this = "http.Morsel" }
override TaintKind getTaintOfAttribute(string name) {
result instanceof ExternalStringKind and
name = "value"
}
}
/** A standard cookie object from a HTTP request, typically an instance of `http.cookies.SimpleCookie` */
deprecated class UntrustedCookie extends TaintKind {
UntrustedCookie() { this = "http.Cookie" }
override TaintKind getTaintForFlowStep(ControlFlowNode fromnode, ControlFlowNode tonode) {
tonode.(SubscriptNode).getObject() = fromnode and
result instanceof UntrustedMorsel
}
}
abstract deprecated class CookieOperation extends @py_flow_node {
/** Gets a textual representation of this element. */
abstract string toString();
abstract ControlFlowNode getKey();
abstract ControlFlowNode getValue();
}
abstract deprecated class CookieGet extends CookieOperation { }
abstract deprecated class CookieSet extends CookieOperation { }
/** Generic taint sink in a http response */
abstract deprecated class HttpResponseTaintSink extends TaintSink {
override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind }
}
abstract deprecated class HttpRedirectTaintSink extends TaintSink {
override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind }
}
deprecated module Client {
// TODO: user-input in other than URL:
// - `data`, `json` for `requests.post`
// - `body` for `HTTPConnection.request`
// - headers?
// TODO: Add more library support
// - urllib3 https://github.com/urllib3/urllib3
// - httpx https://github.com/encode/httpx
/**
* An outgoing http request
*
* For example:
* conn = HTTPConnection('example.com')
* conn.request('GET', '/path')
*/
abstract class HttpRequest extends ControlFlowNode {
/**
* Get any ControlFlowNode that is used to construct the final URL.
*
* In the HTTPConnection example, there is a result for both `'example.com'` and for `'/path'`.
*/
abstract ControlFlowNode getAUrlPart();
abstract string getMethodUpper();
}
/** Taint sink for the URL-part of an outgoing http request */
class HttpRequestUrlTaintSink extends TaintSink {
HttpRequestUrlTaintSink() { this = any(HttpRequest r).getAUrlPart() }
override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind }
}
}

View File

@@ -1,7 +0,0 @@
/** Gets an HTTP verb, in upper case */
deprecated string httpVerb() {
result in ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS", "HEAD"]
}
/** Gets an HTTP verb, in lower case */
deprecated string httpVerbLower() { result = httpVerb().toLowerCase() }

View File

@@ -1,7 +0,0 @@
import python
import semmle.python.security.strings.Basic
import semmle.python.web.django.Redirect
import semmle.python.web.flask.Redirect
import semmle.python.web.tornado.Redirect
import semmle.python.web.pyramid.Redirect
import semmle.python.web.bottle.Redirect

View File

@@ -1,10 +0,0 @@
import semmle.python.web.django.Request
import semmle.python.web.flask.Request
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
import semmle.python.web.falcon.Request
import semmle.python.web.cherrypy.Request
import semmle.python.web.stdlib.Request

View File

@@ -1,10 +0,0 @@
import semmle.python.web.django.Response
import semmle.python.web.flask.Response
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
import semmle.python.web.falcon.Response
import semmle.python.web.cherrypy.Response
import semmle.python.web.stdlib.Response

View File

@@ -1,46 +0,0 @@
import python
import semmle.python.web.Http
import semmle.python.types.Extensions
/** Gets the bottle module */
deprecated ModuleValue theBottleModule() { result = Module::named("bottle") }
/** Gets the bottle.Bottle class */
deprecated ClassValue theBottleClass() { result = theBottleModule().attr("Bottle") }
/**
* Holds if `route` is routed to `func`
* by decorating `func` with `app.route(route)` or `route(route)`
*/
deprecated predicate bottle_route(CallNode route_call, ControlFlowNode route, Function func) {
exists(CallNode decorator_call, string name |
route_call.getFunction().(AttrNode).getObject(name).pointsTo().getClass() = theBottleClass() or
route_call.getFunction().pointsTo(theBottleModule().attr(name))
|
(name = "route" or name = httpVerbLower()) and
decorator_call.getFunction() = route_call and
route_call.getArg(0) = route and
decorator_call.getArg(0).getNode().(FunctionExpr).getInnerScope() = func
)
}
deprecated class BottleRoute extends ControlFlowNode {
BottleRoute() { bottle_route(this, _, _) }
string getUrl() {
exists(StrConst url |
bottle_route(this, url.getAFlowNode(), _) and
result = url.getText()
)
}
Function getFunction() { bottle_route(this, _, result) }
Parameter getANamedArgument() {
exists(string name, Function func |
func = this.getFunction() and
func.getArgByName(name) = result and
this.getUrl().matches("%<" + name + ">%")
)
}
}

View File

@@ -1,28 +0,0 @@
/**
* Provides class representing the `bottle.redirect` function.
* This module is intended to be imported into a taint-tracking query
* to extend `TaintSink`.
*/
import python
import semmle.python.dataflow.TaintTracking
import semmle.python.security.strings.Basic
import semmle.python.web.bottle.General
deprecated FunctionValue bottle_redirect() { result = theBottleModule().attr("redirect") }
/**
* An argument to the `bottle.redirect` function.
*/
deprecated class BottleRedirect extends TaintSink {
override string toString() { result = "bottle.redirect" }
BottleRedirect() {
exists(CallNode call |
bottle_redirect().getACall() = call and
this = call.getAnArg()
)
}
override predicate sinks(TaintKind kind) { kind instanceof StringKind }
}

View File

@@ -1,80 +0,0 @@
import python
import semmle.python.dataflow.TaintTracking
import semmle.python.security.strings.External
import semmle.python.web.Http
import semmle.python.web.bottle.General
deprecated private Value theBottleRequestObject() { result = theBottleModule().attr("request") }
deprecated class BottleRequestKind extends TaintKind {
BottleRequestKind() { this = "bottle.request" }
override TaintKind getTaintOfAttribute(string name) {
result instanceof BottleFormsDict and
(name = "cookies" or name = "query" or name = "form")
or
result instanceof ExternalStringKind and
(name = "query_string" or name = "url_args")
or
result.(DictKind).getValue() instanceof FileUpload and
name = "files"
}
}
deprecated private class RequestSource extends HttpRequestTaintSource {
RequestSource() { this.(ControlFlowNode).pointsTo(theBottleRequestObject()) }
override predicate isSourceOf(TaintKind kind) { kind instanceof BottleRequestKind }
}
deprecated class BottleFormsDict extends TaintKind {
BottleFormsDict() { this = "bottle.FormsDict" }
override TaintKind getTaintForFlowStep(ControlFlowNode fromnode, ControlFlowNode tonode) {
/* Cannot use `getTaintOfAttribute(name)` as it wouldn't bind `name` */
exists(string name |
fromnode = tonode.(AttrNode).getObject(name) and
result instanceof ExternalStringKind
|
name != "get" and name != "getunicode" and name != "getall"
)
}
override TaintKind getTaintOfMethodResult(string name) {
(name = "get" or name = "getunicode") and
result instanceof ExternalStringKind
or
name = "getall" and result.(SequenceKind).getItem() instanceof ExternalStringKind
}
}
deprecated class FileUpload extends TaintKind {
FileUpload() { this = "bottle.FileUpload" }
override TaintKind getTaintOfAttribute(string name) {
name = "filename" and result instanceof ExternalStringKind
or
name = "raw_filename" and result instanceof ExternalStringKind
or
name = "file" and result instanceof UntrustedFile
}
}
deprecated class UntrustedFile extends TaintKind {
UntrustedFile() { this = "Untrusted file" }
}
//
// TO DO.. File uploads -- Should check about file uploads for other frameworks as well.
// Move UntrustedFile to shared location
//
/** A parameter to a bottle request handler function */
deprecated class BottleRequestParameter extends HttpRequestTaintSource {
BottleRequestParameter() {
exists(BottleRoute route | route.getANamedArgument() = this.(ControlFlowNode).getNode())
}
override predicate isSourceOf(TaintKind kind) { kind instanceof ExternalStringKind }
override string toString() { result = "bottle handler function argument" }
}

View File

@@ -1,52 +0,0 @@
import python
import semmle.python.dataflow.TaintTracking
import semmle.python.security.strings.Untrusted
import semmle.python.web.Http
import semmle.python.web.bottle.General
/**
* A bottle.Response object
* This isn't really a "taint", but we use the value tracking machinery to
* track the flow of response objects.
*/
deprecated class BottleResponse extends TaintKind {
BottleResponse() { this = "bottle.response" }
}
deprecated private Value theBottleResponseObject() { result = theBottleModule().attr("response") }
deprecated class BottleResponseBodyAssignment extends HttpResponseTaintSink {
BottleResponseBodyAssignment() {
exists(DefinitionNode lhs |
lhs.getValue() = this and
lhs.(AttrNode).getObject("body").pointsTo(theBottleResponseObject())
)
}
override predicate sinks(TaintKind kind) { kind instanceof StringKind }
}
deprecated class BottleHandlerFunctionResult extends HttpResponseTaintSink {
BottleHandlerFunctionResult() {
exists(BottleRoute route, Return ret |
ret.getScope() = route.getFunction() and
ret.getValue().getAFlowNode() = this
)
}
override predicate sinks(TaintKind kind) { kind instanceof StringKind }
override string toString() { result = "bottle handler function result" }
}
deprecated class BottleCookieSet extends CookieSet, CallNode {
BottleCookieSet() {
any(BottleResponse r).taints(this.getFunction().(AttrNode).getObject("set_cookie"))
}
override string toString() { result = CallNode.super.toString() }
override ControlFlowNode getKey() { result = this.getArg(0) }
override ControlFlowNode getValue() { result = this.getArg(1) }
}

View File

@@ -1,44 +0,0 @@
import python
import semmle.python.web.Http
deprecated module CherryPy {
FunctionValue expose() { result = Value::named("cherrypy.expose") }
}
deprecated class CherryPyExposedFunction extends Function {
CherryPyExposedFunction() {
this.getADecorator().pointsTo(CherryPy::expose())
or
this.getADecorator().(Call).getFunc().pointsTo(CherryPy::expose())
}
}
deprecated class CherryPyRoute extends CallNode {
CherryPyRoute() {
/* cherrypy.quickstart(root, script_name, config) */
Value::named("cherrypy.quickstart").(FunctionValue).getACall() = this
or
/* cherrypy.tree.mount(root, script_name, config) */
this.getFunction().(AttrNode).getObject("mount").pointsTo(Value::named("cherrypy.tree"))
}
ClassValue getAppClass() {
this.getArg(0).pointsTo().getClass() = result
or
this.getArgByName("root").pointsTo().getClass() = result
}
string getPath() {
exists(Value path | path = Value::forString(result) |
this.getArg(1).pointsTo(path)
or
this.getArgByName("script_name").pointsTo(path)
)
}
ClassValue getConfig() {
this.getArg(2).pointsTo().getClass() = result
or
this.getArgByName("config").pointsTo().getClass() = result
}
}

View File

@@ -1,41 +0,0 @@
import python
import semmle.python.dataflow.TaintTracking
import semmle.python.security.strings.Basic
import semmle.python.web.Http
import semmle.python.web.cherrypy.General
/** The cherrypy.request local-proxy object */
deprecated class CherryPyRequest extends TaintKind {
CherryPyRequest() { this = "cherrypy.request" }
override TaintKind getTaintOfAttribute(string name) {
name = "params" and result instanceof ExternalStringDictKind
or
name = "cookie" and result instanceof UntrustedCookie
}
override TaintKind getTaintOfMethodResult(string name) {
name in ["getHeader", "getCookie", "getUser", "getPassword"] and
result instanceof ExternalStringKind
}
}
deprecated class CherryPyExposedFunctionParameter extends HttpRequestTaintSource {
CherryPyExposedFunctionParameter() {
exists(Parameter p |
p = any(CherryPyExposedFunction f).getAnArg() and
not p.isSelf() and
p.asName().getAFlowNode() = this
)
}
override string toString() { result = "CherryPy handler function parameter" }
override predicate isSourceOf(TaintKind kind) { kind instanceof ExternalStringKind }
}
deprecated class CherryPyRequestSource extends HttpRequestTaintSource {
CherryPyRequestSource() { this.(ControlFlowNode).pointsTo(Value::named("cherrypy.request")) }
override predicate isSourceOf(TaintKind kind) { kind instanceof CherryPyRequest }
}

View File

@@ -1,18 +0,0 @@
import python
import semmle.python.dataflow.TaintTracking
import semmle.python.security.strings.Untrusted
import semmle.python.web.Http
import semmle.python.web.cherrypy.General
deprecated class CherryPyExposedFunctionResult extends HttpResponseTaintSink {
CherryPyExposedFunctionResult() {
exists(Return ret |
ret.getScope() instanceof CherryPyExposedFunction and
ret.getValue().getAFlowNode() = this
)
}
override predicate sinks(TaintKind kind) { kind instanceof StringKind }
override string toString() { result = "cherrypy handler function result" }
}

View File

@@ -1,22 +0,0 @@
/**
* Modeling outgoing HTTP requests using the `requests` package
* https://pypi.org/project/requests/
*/
import python
private import semmle.python.web.Http
deprecated class RequestsHttpRequest extends Client::HttpRequest, CallNode {
CallableValue func;
string method;
RequestsHttpRequest() {
method = httpVerbLower() and
func = Module::named("requests").attr(method) and
this = func.getACall()
}
override ControlFlowNode getAUrlPart() { result = func.getNamedArgumentForCall(this, "url") }
override string getMethodUpper() { result = method.toUpperCase() }
}

View File

@@ -1,55 +0,0 @@
import python
private import semmle.python.web.Http
deprecated ClassValue httpConnectionClass() {
// Python 2
result = Value::named("httplib.HTTPConnection")
or
result = Value::named("httplib.HTTPSConnection")
or
// Python 3
result = Value::named("http.client.HTTPConnection")
or
result = Value::named("http.client.HTTPSConnection")
or
// six
result = Value::named("six.moves.http_client.HTTPConnection")
or
result = Value::named("six.moves.http_client.HTTPSConnection")
}
deprecated class HttpConnectionHttpRequest extends Client::HttpRequest, CallNode {
CallNode constructor_call;
CallableValue func;
HttpConnectionHttpRequest() {
exists(ClassValue cls, AttrNode call_origin, Value constructor_call_value |
cls = httpConnectionClass() and
func = cls.lookup("request") and
this = func.getACall() and
// since you can do `r = conn.request; r('GET', path)`, we need to find the origin
this.getFunction().pointsTo(_, _, call_origin) and
// Since HTTPSConnection is a subtype of HTTPConnection, up until this point, `cls` could be either class,
// because `HTTPSConnection.request == HTTPConnection.request`. To avoid generating 2 results, we filter
// on the actual class used as the constructor
call_origin.getObject().pointsTo(_, constructor_call_value, constructor_call) and
cls = constructor_call_value.getClass() and
constructor_call = cls.getACall()
)
}
override ControlFlowNode getAUrlPart() {
result = func.getNamedArgumentForCall(this, "url")
or
result = constructor_call.getArg(0)
or
result = constructor_call.getArgByName("host")
}
override string getMethodUpper() {
exists(string method |
result = method.toUpperCase() and
func.getNamedArgumentForCall(this, "method").pointsTo(Value::forString(method))
)
}
}

View File

@@ -1,50 +0,0 @@
import python
import semmle.python.security.injection.Sql
/**
* A taint kind representing a django cursor object.
*/
deprecated class DjangoDbCursor extends DbCursor {
DjangoDbCursor() { this = "django.db.connection.cursor" }
}
deprecated private Value theDjangoConnectionObject() {
result = Value::named("django.db.connection")
}
/**
* A kind of taint source representing sources of django cursor objects.
*/
deprecated class DjangoDbCursorSource extends DbConnectionSource {
DjangoDbCursorSource() {
exists(AttrNode cursor |
this.(CallNode).getFunction() = cursor and
cursor.getObject("cursor").pointsTo(theDjangoConnectionObject())
)
}
override string toString() { result = "django.db.connection.cursor" }
override predicate isSourceOf(TaintKind kind) { kind instanceof DjangoDbCursor }
}
deprecated ClassValue theDjangoRawSqlClass() {
result = Value::named("django.db.models.expressions.RawSQL")
}
/**
* A sink of taint on calls to `django.db.models.expressions.RawSQL`. This
* allows arbitrary SQL statements to be executed, which is a security risk.
*/
deprecated class DjangoRawSqlSink extends SqlInjectionSink {
DjangoRawSqlSink() {
exists(CallNode call |
call = theDjangoRawSqlClass().getACall() and
this = call.getArg(0)
)
}
override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind }
override string toString() { result = "django.db.models.expressions.RawSQL(sink,...)" }
}

View File

@@ -1,136 +0,0 @@
import python
import semmle.python.regex
import semmle.python.web.Http
// TODO: Since django uses `path = partial(...)`, our analysis doesn't understand this is
// a FunctionValue, so we can't use `FunctionValue.getArgumentForCall`
// https://github.com/django/django/blob/master/django/urls/conf.py#L76
abstract deprecated class DjangoRoute extends CallNode {
DjangoViewHandler getViewHandler() {
result = view_handler_from_view_arg(this.getArg(1))
or
result = view_handler_from_view_arg(this.getArgByName("view"))
}
abstract string getANamedArgument();
/**
* Get the number of positional arguments that will be passed to the view.
* Will only return a result if there are no named arguments.
*/
abstract int getNumPositionalArguments();
}
/**
* For function based views -- also see `DjangoClassBasedViewHandler`
* https://docs.djangoproject.com/en/1.11/topics/http/views/
* https://docs.djangoproject.com/en/3.0/topics/http/views/
*/
deprecated class DjangoViewHandler extends PythonFunctionValue {
/** Gets the index of the 'request' argument */
int getRequestArgIndex() { result = 0 }
}
/**
* Class based views
* https://docs.djangoproject.com/en/1.11/topics/class-based-views/
* https://docs.djangoproject.com/en/3.0/topics/class-based-views/
*/
deprecated private class DjangoViewClass extends ClassValue {
DjangoViewClass() {
Value::named("django.views.generic.View") = this.getASuperType()
or
Value::named("django.views.View") = this.getASuperType()
}
}
deprecated class DjangoClassBasedViewHandler extends DjangoViewHandler {
DjangoClassBasedViewHandler() { exists(DjangoViewClass cls | cls.lookup(httpVerbLower()) = this) }
override int getRequestArgIndex() {
// due to `self` being the first parameter
result = 1
}
}
/**
* Gets the function that will handle requests when `view_arg` is used as the view argument to a
* django route. That is, this methods handles Class-based Views and its `as_view()` function.
*/
deprecated private DjangoViewHandler view_handler_from_view_arg(ControlFlowNode view_arg) {
// Function-based view
result = view_arg.pointsTo()
or
// Class-based view
exists(ClassValue cls |
cls = view_arg.(CallNode).getFunction().(AttrNode).getObject("as_view").pointsTo() and
result = cls.lookup(httpVerbLower())
)
}
// We need this "dummy" class, since otherwise the regex argument would not be considered
// a regex (RegexString is abstract)
deprecated class DjangoRouteRegex extends RegexString {
DjangoRouteRegex() { exists(DjangoRegexRoute route | route.getRouteArg() = this.getAFlowNode()) }
}
deprecated class DjangoRegexRoute extends DjangoRoute {
ControlFlowNode route;
DjangoRegexRoute() {
exists(FunctionValue route_maker |
// Django 1.x: https://docs.djangoproject.com/en/1.11/ref/urls/#django.conf.urls.url
Value::named("django.conf.urls.url") = route_maker and
route_maker.getArgumentForCall(this, 0) = route
)
or
// Django 2.x and 3.x: https://docs.djangoproject.com/en/3.0/ref/urls/#re-path
this = Value::named("django.urls.re_path").getACall() and
(
route = this.getArg(0)
or
route = this.getArgByName("route")
)
}
ControlFlowNode getRouteArg() { result = route }
override string getANamedArgument() {
exists(DjangoRouteRegex regex | regex.getAFlowNode() = route |
result = regex.getGroupName(_, _)
)
}
override int getNumPositionalArguments() {
not exists(this.getANamedArgument()) and
exists(DjangoRouteRegex regex | regex.getAFlowNode() = route |
result = count(regex.getGroupNumber(_, _))
)
}
}
deprecated class DjangoPathRoute extends DjangoRoute {
ControlFlowNode route;
DjangoPathRoute() {
// Django 2.x and 3.x: https://docs.djangoproject.com/en/3.0/ref/urls/#path
this = Value::named("django.urls.path").getACall() and
(
route = this.getArg(0)
or
route = this.getArgByName("route")
)
}
override string getANamedArgument() {
// regexp taken from django:
// https://github.com/django/django/blob/7d1bf29977bb368d7c28e7c6eb146db3b3009ae7/django/urls/resolvers.py#L199
exists(StrConst route_str, string match |
route_str = route.getNode() and
match = route_str.getText().regexpFind("<(?:(?<converter>[^>:]+):)?(?<parameter>\\w+)>", _, _) and
result = match.regexpCapture("<(?:(?<converter>[^>:]+):)?(?<parameter>\\w+)>", 2)
)
}
override int getNumPositionalArguments() { none() }
}

View File

@@ -1,69 +0,0 @@
import python
import semmle.python.dataflow.TaintTracking
import semmle.python.security.strings.Basic
import semmle.python.web.Http
import semmle.python.security.injection.Sql
/** A django model class */
deprecated class DjangoModel extends ClassValue {
DjangoModel() { Value::named("django.db.models.Model") = this.getASuperType() }
}
/** A "taint" for django database tables */
deprecated class DjangoDbTableObjects extends TaintKind {
DjangoDbTableObjects() { this = "django.db.models.Model.objects" }
override TaintKind getTaintOfMethodResult(string name) {
result = this and
name in [
"filter", "exclude", "none", "all", "union", "intersection", "difference", "select_related",
"prefetch_related", "extra", "defer", "only", "annotate", "using", "select_for_update",
"raw", "order_by", "reverse", "distinct", "values", "values_list", "dates", "datetimes"
]
}
}
/** Django model objects, which are sources of django database table "taint" */
deprecated class DjangoModelObjects extends TaintSource {
DjangoModelObjects() {
this.(AttrNode).isLoad() and this.(AttrNode).getObject("objects").pointsTo(any(DjangoModel m))
}
override predicate isSourceOf(TaintKind kind) { kind instanceof DjangoDbTableObjects }
override string toString() { result = "django.db.models.Model.objects" }
}
/**
* A call to the `raw` method on a django model. This allows a raw SQL query
* to be sent to the database, which is a security risk.
*/
deprecated class DjangoModelRawCall extends SqlInjectionSink {
DjangoModelRawCall() {
exists(CallNode raw_call, ControlFlowNode queryset | this = raw_call.getArg(0) |
raw_call.getFunction().(AttrNode).getObject("raw") = queryset and
any(DjangoDbTableObjects objs).taints(queryset)
)
}
override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind }
override string toString() { result = "django.models.QuerySet.raw(sink,...)" }
}
/**
* A call to the `extra` method on a django model. This allows a raw SQL query
* to be sent to the database, which is a security risk.
*/
deprecated class DjangoModelExtraCall extends SqlInjectionSink {
DjangoModelExtraCall() {
exists(CallNode extra_call, ControlFlowNode queryset | this = extra_call.getArg(0) |
extra_call.getFunction().(AttrNode).getObject("extra") = queryset and
any(DjangoDbTableObjects objs).taints(queryset)
)
}
override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind }
override string toString() { result = "django.models.QuerySet.extra(sink,...)" }
}

View File

@@ -1,37 +0,0 @@
/**
* Provides class representing the `django.redirect` function.
* This module is intended to be imported into a taint-tracking query
* to extend `TaintSink`.
*/
import python
import semmle.python.dataflow.TaintTracking
import semmle.python.security.strings.Basic
private import semmle.python.web.django.Shared
private import semmle.python.web.Http
/**
* The URL argument for a call to the `django.shortcuts.redirect` function.
*/
deprecated class DjangoShortcutsRedirectSink extends HttpRedirectTaintSink {
override string toString() { result = "DjangoShortcutsRedirectSink" }
DjangoShortcutsRedirectSink() {
this = Value::named("django.shortcuts.redirect").(FunctionValue).getArgumentForCall(_, 0)
}
}
/**
* The URL argument when instantiating a Django Redirect Response.
*/
deprecated class DjangoRedirectResponseSink extends HttpRedirectTaintSink {
DjangoRedirectResponseSink() {
exists(CallNode call | call = any(DjangoRedirectResponseClass cls).getACall() |
this = call.getArg(0)
or
this = call.getArgByName("redirect_to")
)
}
override string toString() { result = "DjangoRedirectResponseSink" }
}

View File

@@ -1,78 +0,0 @@
import python
import semmle.python.dataflow.TaintTracking
import semmle.python.web.Http
import semmle.python.web.django.General
/** A django.request.HttpRequest object */
deprecated class DjangoRequest extends TaintKind {
DjangoRequest() { this = "django.request.HttpRequest" }
override TaintKind getTaintOfAttribute(string name) {
(name = "GET" or name = "POST") and
result instanceof DjangoQueryDict
}
override TaintKind getTaintOfMethodResult(string name) {
(name = "body" or name = "path") and
result instanceof ExternalStringKind
}
}
/* Helper for getTaintForStep() */
pragma[noinline]
deprecated private predicate subscript_taint(SubscriptNode sub, ControlFlowNode obj, TaintKind kind) {
sub.getObject() = obj and
kind instanceof ExternalStringKind
}
/** A django.request.QueryDict object */
deprecated class DjangoQueryDict extends TaintKind {
DjangoQueryDict() { this = "django.http.request.QueryDict" }
override TaintKind getTaintForFlowStep(ControlFlowNode fromnode, ControlFlowNode tonode) {
this.taints(fromnode) and
subscript_taint(tonode, fromnode, result)
}
override TaintKind getTaintOfMethodResult(string name) {
name = "get" and result instanceof ExternalStringKind
}
}
/** A Django request parameter */
deprecated class DjangoRequestSource extends HttpRequestTaintSource {
DjangoRequestSource() {
exists(DjangoRoute route, DjangoViewHandler view, int request_arg_index |
route.getViewHandler() = view and
request_arg_index = view.getRequestArgIndex() and
this = view.getScope().getArg(request_arg_index).asName().getAFlowNode()
)
}
override string toString() { result = "Django request source" }
override predicate isSourceOf(TaintKind kind) { kind instanceof DjangoRequest }
}
/** An argument specified in a url routing table */
deprecated class DjangoRequestParameter extends HttpRequestTaintSource {
DjangoRequestParameter() {
exists(DjangoRoute route, Function f, DjangoViewHandler view, int request_arg_index |
route.getViewHandler() = view and
request_arg_index = view.getRequestArgIndex() and
f = view.getScope()
|
this.(ControlFlowNode).getNode() = f.getArgByName(route.getANamedArgument())
or
exists(int i | i >= 0 |
i < route.getNumPositionalArguments() and
// +1 because first argument is always the request
this.(ControlFlowNode).getNode() = f.getArg(request_arg_index + 1 + i)
)
)
}
override predicate isSourceOf(TaintKind kind) { kind instanceof ExternalStringKind }
override string toString() { result = "django.http.request.parameter" }
}

View File

@@ -1,79 +0,0 @@
import python
import semmle.python.dataflow.TaintTracking
import semmle.python.security.strings.Basic
private import semmle.python.web.django.Shared
private import semmle.python.web.Http
/** INTERNAL class used for tracking a django response object. */
deprecated private class DjangoResponseKind extends TaintKind {
DjangoResponseKind() { this = "django.response.HttpResponse" }
}
/** INTERNAL taint-source used for tracking a django response object. */
deprecated private class DjangoResponseSource extends TaintSource {
DjangoResponseSource() { exists(DjangoContentResponseClass cls | cls.getACall() = this) }
override predicate isSourceOf(TaintKind kind) { kind instanceof DjangoResponseKind }
override string toString() { result = "django.http.response.HttpResponse" }
}
/** A write to a django response, which is vulnerable to external data (xss) */
deprecated class DjangoResponseWrite extends HttpResponseTaintSink {
DjangoResponseWrite() {
exists(AttrNode meth, CallNode call |
call.getFunction() = meth and
any(DjangoResponseKind response).taints(meth.getObject("write")) and
this = call.getArg(0)
)
}
override predicate sinks(TaintKind kind) { kind instanceof StringKind }
override string toString() { result = "django.Response.write(...)" }
}
/**
* An argument to initialization of a django response.
*/
deprecated class DjangoResponseContent extends HttpResponseTaintSink {
DjangoContentResponseClass cls;
CallNode call;
DjangoResponseContent() {
call = cls.getACall() and
this = cls.getContentArg(call)
}
override predicate sinks(TaintKind kind) { kind instanceof StringKind }
override string toString() { result = "django.Response(...)" }
}
/**
* An argument to initialization of a django response, which is vulnerable to external data (XSS).
*/
deprecated class DjangoResponseContentXSSVulnerable extends DjangoResponseContent {
override DjangoXSSVulnerableResponseClass cls;
DjangoResponseContentXSSVulnerable() {
not exists(cls.getContentTypeArg(call))
or
exists(StringValue s |
cls.getContentTypeArg(call).pointsTo(s) and
s.getText().matches("text/html%")
)
}
}
deprecated class DjangoCookieSet extends CookieSet, CallNode {
DjangoCookieSet() {
any(DjangoResponseKind r).taints(this.getFunction().(AttrNode).getObject("set_cookie"))
}
override string toString() { result = CallNode.super.toString() }
override ControlFlowNode getKey() { result = this.getArg(0) }
override ControlFlowNode getValue() { result = this.getArg(1) }
}

View File

@@ -1,6 +0,0 @@
import python
/*
* Sanitizers
* No django sanitizers implemented yet.
*/

View File

@@ -1,72 +0,0 @@
import python
/** A class that is a Django Redirect Response (subclass of `django.http.HttpResponseRedirectBase`). */
deprecated class DjangoRedirectResponseClass extends ClassValue {
DjangoRedirectResponseClass() {
exists(ClassValue redirect_base |
// version 1.x
redirect_base = Value::named("django.http.response.HttpResponseRedirectBase")
or
// version 2.x and 3.x
redirect_base = Value::named("django.http.HttpResponseRedirectBase")
|
this.getASuperType() = redirect_base
)
}
}
/**
* A class that is a Django Response, which can contain content.
* A subclass of `django.http.HttpResponse` that is not a `DjangoRedirectResponseClass`.
*/
deprecated class DjangoContentResponseClass extends ClassValue {
ClassValue base;
DjangoContentResponseClass() {
(
// version 1.x
base = Value::named("django.http.response.HttpResponse")
or
// version 2.x and 3.x
// https://docs.djangoproject.com/en/2.2/ref/request-response/#httpresponse-objects
base = Value::named("django.http.HttpResponse")
) and
this.getASuperType() = base
}
// The reason these two methods are defined in this class (and not in the Sink
// definition that uses this class), is that if we were to add support for
// `django.http.response.HttpResponseNotAllowed` it would make much more sense to add
// the custom logic in this class (or subclass), than to handle all of it in the sink
// definition.
/** Gets the `content` argument of a `call` to the constructor */
ControlFlowNode getContentArg(CallNode call) { none() }
/** Gets the `content_type` argument of a `call` to the constructor */
ControlFlowNode getContentTypeArg(CallNode call) { none() }
}
/** A class that is a Django Response, and is vulnerable to XSS. */
deprecated class DjangoXSSVulnerableResponseClass extends DjangoContentResponseClass {
DjangoXSSVulnerableResponseClass() {
// We want to avoid FPs on subclasses that are not exposed to XSS, for example `JsonResponse`.
// The easiest way is to disregard any subclass that has a special `__init__` method.
// It's not guaranteed to remove all FPs, or not to generate FNs, but compared to our
// previous implementation that would treat 0-th argument to _any_ subclass as a sink,
// this gets us much closer to reality.
this.lookup("__init__") = base.lookup("__init__") and
not this instanceof DjangoRedirectResponseClass
}
override ControlFlowNode getContentArg(CallNode call) {
result = call.getArg(0)
or
result = call.getArgByName("content")
}
override ControlFlowNode getContentTypeArg(CallNode call) {
result = call.getArg(1)
or
result = call.getArgByName("content_type")
}
}

View File

@@ -1,46 +0,0 @@
import python
import semmle.python.web.Http
/** Gets the falcon API class */
deprecated ClassValue theFalconAPIClass() { result = Value::named("falcon.API") }
/** Holds if `route` is routed to `resource` */
deprecated private predicate api_route(
CallNode route_call, ControlFlowNode route, ClassValue resource
) {
route_call.getFunction().(AttrNode).getObject("add_route").pointsTo().getClass() =
theFalconAPIClass() and
route_call.getArg(0) = route and
route_call.getArg(1).pointsTo().getClass() = resource
}
deprecated private predicate route(FalconRoute route, Function target, string funcname) {
route.getResourceClass().lookup("on_" + funcname).(FunctionValue).getScope() = target
}
deprecated class FalconRoute extends ControlFlowNode {
FalconRoute() { api_route(this, _, _) }
string getUrl() {
exists(StrConst url |
api_route(this, url.getAFlowNode(), _) and
result = url.getText()
)
}
ClassValue getResourceClass() { api_route(this, _, result) }
FalconHandlerFunction getHandlerFunction(string method) { route(this, result, method) }
}
deprecated class FalconHandlerFunction extends Function {
FalconHandlerFunction() { route(_, this, _) }
private string methodName() { route(_, this, result) }
string getMethod() { result = this.methodName().toUpperCase() }
Parameter getRequest() { result = this.getArg(1) }
Parameter getResponse() { result = this.getArg(2) }
}

View File

@@ -1,37 +0,0 @@
import python
import semmle.python.dataflow.TaintTracking
import semmle.python.web.Http
import semmle.python.web.falcon.General
/** https://falcon.readthedocs.io/en/stable/api/request_and_response.html */
deprecated class FalconRequest extends TaintKind {
FalconRequest() { this = "falcon.request" }
override TaintKind getTaintOfAttribute(string name) {
name = "env" and result instanceof WsgiEnvironment
or
result instanceof ExternalStringKind and
name in ["uri", "url", "forwarded_uri", "relative_uri", "query_string"]
or
result instanceof ExternalStringDictKind and
(name = "cookies" or name = "params")
or
name = "stream" and result instanceof ExternalFileObject
}
override TaintKind getTaintOfMethodResult(string name) {
name = "get_param" and result instanceof ExternalStringKind
or
name = "get_param_as_json" and result instanceof ExternalJsonKind
or
name = "get_param_as_list" and result instanceof ExternalStringSequenceKind
}
}
deprecated class FalconRequestParameter extends HttpRequestTaintSource {
FalconRequestParameter() {
exists(FalconHandlerFunction f | f.getRequest() = this.(ControlFlowNode).getNode())
}
override predicate isSourceOf(TaintKind k) { k instanceof FalconRequest }
}

View File

@@ -1,28 +0,0 @@
import python
import semmle.python.dataflow.TaintTracking
import semmle.python.web.Http
import semmle.python.web.falcon.General
/** https://falcon.readthedocs.io/en/stable/api/request_and_response.html */
deprecated class FalconResponse extends TaintKind {
FalconResponse() { this = "falcon.response" }
}
/** Only used internally to track the response parameter */
deprecated private class FalconResponseParameter extends TaintSource {
FalconResponseParameter() {
exists(FalconHandlerFunction f | f.getResponse() = this.(ControlFlowNode).getNode())
}
override predicate isSourceOf(TaintKind k) { k instanceof FalconResponse }
}
deprecated class FalconResponseBodySink extends HttpResponseTaintSink {
FalconResponseBodySink() {
exists(AttrNode attr | any(FalconResponse f).taints(attr.getObject("body")) |
attr.(DefinitionNode).getValue() = this
)
}
override predicate sinks(TaintKind kind) { kind instanceof StringKind }
}

View File

@@ -1,104 +0,0 @@
import python
import semmle.python.web.Http
import semmle.python.web.flask.Response
/** Gets the flask app class */
deprecated ClassValue theFlaskClass() { result = Value::named("flask.Flask") }
/** Gets the flask MethodView class */
deprecated ClassValue theFlaskMethodViewClass() { result = Value::named("flask.views.MethodView") }
deprecated ClassValue theFlaskReponseClass() { result = Value::named("flask.Response") }
/**
* Holds if `route` is routed to `func`
* by decorating `func` with `app.route(route)`
*/
deprecated predicate app_route(ControlFlowNode route, Function func) {
exists(CallNode route_call, CallNode decorator_call |
route_call.getFunction().(AttrNode).getObject("route").pointsTo().getClass() = theFlaskClass() and
decorator_call.getFunction() = route_call and
route_call.getArg(0) = route and
decorator_call.getArg(0).getNode().(FunctionExpr).getInnerScope() = func
)
}
/* Helper for add_url_rule */
deprecated private predicate add_url_rule_call(ControlFlowNode regex, ControlFlowNode callable) {
exists(CallNode call |
call.getFunction().(AttrNode).getObject("add_url_rule").pointsTo().getClass() = theFlaskClass() and
regex = call.getArg(0)
|
callable = call.getArg(2) or
callable = call.getArgByName("view_func")
)
}
/** Holds if urls matching `regex` are routed to `func` */
deprecated predicate add_url_rule(ControlFlowNode regex, Function func) {
exists(ControlFlowNode callable | add_url_rule_call(regex, callable) |
exists(PythonFunctionValue f | f.getScope() = func and callable.pointsTo(f))
or
/* MethodView.as_view() */
exists(MethodViewClass view_cls | view_cls.asTaint().taints(callable) |
func = view_cls.lookup(httpVerbLower()).(FunctionValue).getScope()
)
/* TODO: -- Handle Views that aren't MethodViews */
)
}
/**
* Holds if urls matching `regex` are routed to `func` using
* any of flask's routing mechanisms.
*/
deprecated predicate flask_routing(ControlFlowNode regex, Function func) {
app_route(regex, func)
or
add_url_rule(regex, func)
}
/** A class that extends flask.views.MethodView */
deprecated private class MethodViewClass extends ClassValue {
MethodViewClass() { this.getASuperType() = theFlaskMethodViewClass() }
/* As we are restricted to strings for taint kinds, we need to map these classes to strings. */
string taintString() { result = "flask/" + this.getQualifiedName() + ".as.view" }
/* As we are restricted to strings for taint kinds, we need to map these classes to strings. */
TaintKind asTaint() { result = this.taintString() }
}
deprecated private class MethodViewTaint extends TaintKind {
MethodViewTaint() { any(MethodViewClass cls).taintString() = this }
}
/** A source of method view "taint"s. */
deprecated private class AsView extends TaintSource {
AsView() {
exists(ClassValue view_class |
view_class.getASuperType() = theFlaskMethodViewClass() and
this.(CallNode).getFunction().(AttrNode).getObject("as_view").pointsTo(view_class)
)
}
override string toString() { result = "flask.MethodView.as_view()" }
override predicate isSourceOf(TaintKind kind) {
exists(MethodViewClass view_class |
kind = view_class.asTaint() and
this.(CallNode).getFunction().(AttrNode).getObject("as_view").pointsTo(view_class)
)
}
}
deprecated class FlaskCookieSet extends CookieSet, CallNode {
FlaskCookieSet() {
any(FlaskResponseTaintKind t).taints(this.getFunction().(AttrNode).getObject("set_cookie"))
}
override string toString() { result = CallNode.super.toString() }
override ControlFlowNode getKey() { result = this.getArg(0) }
override ControlFlowNode getValue() { result = this.getArg(1) }
}

View File

@@ -1,26 +0,0 @@
/**
* Provides class representing the `flask.redirect` function.
* This module is intended to be imported into a taint-tracking query
* to extend `TaintSink`.
*/
import python
import semmle.python.dataflow.TaintTracking
import semmle.python.security.strings.Basic
import semmle.python.web.flask.General
deprecated FunctionValue flask_redirect() { result = Value::named("flask.redirect") }
/**
* Represents an argument to the `flask.redirect` function.
*/
deprecated class FlaskRedirect extends HttpRedirectTaintSink {
override string toString() { result = "flask.redirect" }
FlaskRedirect() {
exists(CallNode call |
flask_redirect().getACall() = call and
this = call.getAnArg()
)
}
}

View File

@@ -1,80 +0,0 @@
import python
import semmle.python.dataflow.TaintTracking
import semmle.python.web.Http
import semmle.python.web.flask.General
deprecated private Value theFlaskRequestObject() { result = Value::named("flask.request") }
/** Holds if `attr` is an access of attribute `name` of the flask request object */
deprecated private predicate flask_request_attr(AttrNode attr, string name) {
attr.isLoad() and
attr.getObject(name).pointsTo(theFlaskRequestObject())
}
/** Source of external data from a flask request */
deprecated class FlaskRequestData extends HttpRequestTaintSource {
FlaskRequestData() {
not this instanceof FlaskRequestArgs and
exists(string name | flask_request_attr(this, name) |
name in ["path", "full_path", "base_url", "url"]
)
}
override predicate isSourceOf(TaintKind kind) { kind instanceof ExternalStringKind }
override string toString() { result = "flask.request" }
}
/** Source of dictionary whose values are externally controlled */
deprecated class FlaskRequestArgs extends HttpRequestTaintSource {
FlaskRequestArgs() {
exists(string attr | flask_request_attr(this, attr) |
attr in ["args", "form", "values", "files", "headers", "json"]
)
}
override predicate isSourceOf(TaintKind kind) { kind instanceof ExternalStringDictKind }
override string toString() { result = "flask.request.args" }
}
/** Source of dictionary whose values are externally controlled */
deprecated class FlaskRequestJson extends HttpRequestTaintSource {
FlaskRequestJson() { flask_request_attr(this, "json") }
override predicate isSourceOf(TaintKind kind) { kind instanceof ExternalJsonKind }
override string toString() { result = "flask.request.json" }
}
/**
* A parameter to a flask request handler, that can capture a part of the URL (as specified in
* the url-pattern of a route).
*
* For example, the `name` parameter in:
* ```
* @app.route('/hello/<name>')
* def hello(name):
* ```
*/
deprecated class FlaskRoutedParameter extends HttpRequestTaintSource {
FlaskRoutedParameter() {
exists(string name, Function func, StrConst url_pattern |
this.(ControlFlowNode).getNode() = func.getArgByName(name) and
flask_routing(url_pattern.getAFlowNode(), func) and
exists(string match |
match = url_pattern.getS().regexpFind(werkzeug_rule_re(), _, _) and
name = match.regexpCapture(werkzeug_rule_re(), 4)
)
)
}
override predicate isSourceOf(TaintKind kind) { kind instanceof ExternalStringKind }
}
deprecated private string werkzeug_rule_re() {
// since flask uses werkzeug internally, we are using its routing rules from
// https://github.com/pallets/werkzeug/blob/4dc8d6ab840d4b78cbd5789cef91b01e3bde01d5/src/werkzeug/routing.py#L138-L151
result =
"(?<static>[^<]*)<(?:(?<converter>[a-zA-Z_][a-zA-Z0-9_]*)(?:\\((?<args>.*?)\\))?\\:)?(?<variable>[a-zA-Z_][a-zA-Z0-9_]*)>"
}

View File

@@ -1,55 +0,0 @@
import python
import semmle.python.dataflow.TaintTracking
import semmle.python.security.strings.Basic
import semmle.python.web.flask.General
/**
* A flask response, which is vulnerable to any sort of
* http response malice.
*/
deprecated class FlaskRoutedResponse extends HttpResponseTaintSink {
FlaskRoutedResponse() {
exists(PythonFunctionValue response |
flask_routing(_, response.getScope()) and
this = response.getAReturnedNode()
)
}
override predicate sinks(TaintKind kind) { kind instanceof StringKind }
override string toString() { result = "flask.routed.response" }
}
deprecated class FlaskResponseArgument extends HttpResponseTaintSink {
FlaskResponseArgument() {
exists(CallNode call |
(
call.getFunction().pointsTo(theFlaskReponseClass())
or
call.getFunction().pointsTo(Value::named("flask.make_response"))
) and
call.getArg(0) = this
)
}
override predicate sinks(TaintKind kind) { kind instanceof StringKind }
override string toString() { result = "flask.response.argument" }
}
deprecated class FlaskResponseTaintKind extends TaintKind {
FlaskResponseTaintKind() { this = "flask.Response" }
}
deprecated class FlaskResponseConfiguration extends TaintTracking::Configuration {
FlaskResponseConfiguration() { this = "Flask response configuration" }
override predicate isSource(DataFlow::Node node, TaintKind kind) {
kind instanceof FlaskResponseTaintKind and
(
node.asCfgNode().(CallNode).getFunction().pointsTo(theFlaskReponseClass())
or
node.asCfgNode().(CallNode).getFunction().pointsTo(Value::named("flask.make_response"))
)
}
}

View File

@@ -1,33 +0,0 @@
/**
* Provides class representing the `pyramid.redirect` function.
* This module is intended to be imported into a taint-tracking query
* to extend `TaintSink`.
*/
import python
import semmle.python.dataflow.TaintTracking
import semmle.python.security.strings.Basic
import semmle.python.web.Http
deprecated private ClassValue redirectClass() {
exists(ModuleValue ex | ex.getName() = "pyramid.httpexceptions" |
ex.attr("HTTPFound") = result
or
ex.attr("HTTPTemporaryRedirect") = result
)
}
/**
* Represents an argument to the `tornado.redirect` function.
*/
deprecated class PyramidRedirect extends HttpRedirectTaintSink {
override string toString() { result = "pyramid.redirect" }
PyramidRedirect() {
exists(CallNode call | call.getFunction().pointsTo(redirectClass()) |
call.getArg(0) = this
or
call.getArgByName("location") = this
)
}
}

View File

@@ -1,25 +0,0 @@
import python
import semmle.python.dataflow.TaintTracking
import semmle.python.web.Http
private import semmle.python.web.webob.Request
private import semmle.python.web.pyramid.View
deprecated class PyramidRequest extends BaseWebobRequest {
PyramidRequest() { this = "pyramid.request" }
override ClassValue getType() { result = Value::named("pyramid.request.Request") }
}
/** Source of pyramid request objects */
deprecated class PyramidViewArgument extends HttpRequestTaintSource {
PyramidViewArgument() {
exists(Function view_func |
is_pyramid_view_function(view_func) and
this.(ControlFlowNode).getNode() = view_func.getArg(0)
)
}
override predicate isSourceOf(TaintKind kind) { kind instanceof PyramidRequest }
override string toString() { result = "pyramid.view.argument" }
}

View File

@@ -1,37 +0,0 @@
import python
import semmle.python.dataflow.TaintTracking
import semmle.python.security.strings.Basic
import semmle.python.web.Http
private import semmle.python.web.pyramid.View
/**
* A pyramid response, which is vulnerable to any sort of
* http response malice.
*/
deprecated class PyramidRoutedResponse extends HttpResponseTaintSink {
PyramidRoutedResponse() {
exists(PythonFunctionValue view |
is_pyramid_view_function(view.getScope()) and
this = view.getAReturnedNode()
)
}
override predicate sinks(TaintKind kind) { kind instanceof StringKind }
override string toString() { result = "pyramid.routed.response" }
}
deprecated class PyramidCookieSet extends CookieSet, CallNode {
PyramidCookieSet() {
exists(ControlFlowNode f |
f = this.getFunction().(AttrNode).getObject("set_cookie") and
f.pointsTo().getClass() = Value::named("pyramid.response.Response")
)
}
override string toString() { result = CallNode.super.toString() }
override ControlFlowNode getKey() { result = this.getArg(0) }
override ControlFlowNode getValue() { result = this.getArg(1) }
}

View File

@@ -1,9 +0,0 @@
import python
deprecated ModuleValue thePyramidViewModule() { result.getName() = "pyramid.view" }
deprecated Value thePyramidViewConfig() { result = thePyramidViewModule().attr("view_config") }
deprecated predicate is_pyramid_view_function(Function func) {
func.getADecorator().pointsTo().getClass() = thePyramidViewConfig()
}

View File

@@ -1,126 +0,0 @@
/**
* Provides the sources and taint-flow for HTTP servers defined using the standard library (stdlib).
* Specifically, we model `HttpRequestTaintSource`s from instances of `BaseHTTPRequestHandler`
* (or subclasses) and form parsing using `cgi.FieldStorage`.
*/
import python
import semmle.python.dataflow.TaintTracking
import semmle.python.web.Http
/** Source of BaseHttpRequestHandler instances. */
deprecated class StdLibRequestSource extends HttpRequestTaintSource {
StdLibRequestSource() {
exists(ClassValue cls |
cls.getABaseType+() = Value::named("BaseHTTPServer.BaseHTTPRequestHandler")
or
cls.getABaseType+() = Value::named("http.server.BaseHTTPRequestHandler")
|
this.(ControlFlowNode).pointsTo().getClass() = cls
)
}
override predicate isSourceOf(TaintKind kind) { kind instanceof BaseHTTPRequestHandlerKind }
}
/** TaintKind for an instance of BaseHttpRequestHandler. */
deprecated class BaseHTTPRequestHandlerKind extends TaintKind {
BaseHTTPRequestHandlerKind() { this = "BaseHTTPRequestHandlerKind" }
override TaintKind getTaintOfAttribute(string name) {
name in ["requestline", "path"] and
result instanceof ExternalStringKind
or
name = "headers" and
result instanceof HTTPMessageKind
or
name = "rfile" and
result instanceof ExternalFileObject
}
}
/** TaintKind for headers (instance of HttpMessage). */
deprecated class HTTPMessageKind extends ExternalStringDictKind {
override TaintKind getTaintOfMethodResult(string name) {
result = super.getTaintOfMethodResult(name)
or
name = "get_all" and
result.(SequenceKind).getItem() = this.getValue()
or
name in ["as_bytes", "as_string"] and
result instanceof ExternalStringKind
}
override TaintKind getTaintForFlowStep(ControlFlowNode fromnode, ControlFlowNode tonode) {
result = super.getTaintForFlowStep(fromnode, tonode)
or
exists(ClassValue cls | cls = ClassValue::unicode() or cls = ClassValue::bytes() |
tonode = cls.getACall() and
tonode.(CallNode).getArg(0) = fromnode and
result instanceof ExternalStringKind
)
}
}
/** Source of parsed HTTP forms (by using the `cgi` module). */
deprecated class CgiFieldStorageSource extends HttpRequestTaintSource {
CgiFieldStorageSource() { this = Value::named("cgi.FieldStorage").getACall() }
override predicate isSourceOf(TaintKind kind) { kind instanceof CgiFieldStorageFormKind }
}
/** TaintKind for a parsed HTTP form. */
deprecated class CgiFieldStorageFormKind extends TaintKind {
/*
* There is a slight difference between how we model form/fields and how it is handled by the code.
* In the code
* ```
* form = cgi.FieldStorage()
* field = form['myfield']
* ```
* both `form` and `field` have the type `cgi.FieldStorage`. This allows the code to represent
* nested forms as `form['nested_form']['myfield']`. However, since HTML forms can't be nested
* we ignore that detail since it allows for a more clean modeling.
*/
CgiFieldStorageFormKind() { this = "CgiFieldStorageFormKind" }
override TaintKind getTaintOfAttribute(string name) {
name = "value" and result.(SequenceKind).getItem() instanceof CgiFieldStorageFieldKind
}
override TaintKind getTaintOfMethodResult(string name) {
name = "getvalue" and
(
result instanceof ExternalStringKind
or
result.(SequenceKind).getItem() instanceof ExternalStringKind
)
or
name = "getfirst" and
result instanceof ExternalStringKind
or
name = "getlist" and
result.(SequenceKind).getItem() instanceof ExternalStringKind
}
override TaintKind getTaintForFlowStep(ControlFlowNode fromnode, ControlFlowNode tonode) {
tonode.(SubscriptNode).getObject() = fromnode and
(
result instanceof CgiFieldStorageFieldKind
or
result.(SequenceKind).getItem() instanceof CgiFieldStorageFieldKind
)
}
}
/** TaintKind for the field of a parsed HTTP form. */
deprecated class CgiFieldStorageFieldKind extends TaintKind {
CgiFieldStorageFieldKind() { this = "CgiFieldStorageFieldKind" }
override TaintKind getTaintOfAttribute(string name) {
name in ["filename", "value"] and result instanceof ExternalStringKind
or
name = "file" and result instanceof ExternalFileObject
}
}

View File

@@ -1,43 +0,0 @@
/**
* Provides the sinks for HTTP servers defined with standard library (stdlib).
*/
import python
import semmle.python.dataflow.TaintTracking
import semmle.python.web.Http
deprecated private predicate is_wfile(AttrNode wfile) {
exists(ClassValue cls |
// Python 2
cls.getABaseType+() = Value::named("BaseHTTPServer.BaseHTTPRequestHandler")
or
// Python 3
cls.getABaseType+() = Value::named("http.server.BaseHTTPRequestHandler")
|
wfile.getObject("wfile").pointsTo().getClass() = cls
)
}
/** Sink for `h.wfile.write` where `h` is an instance of BaseHttpRequestHandler. */
deprecated class StdLibWFileWriteSink extends HttpResponseTaintSink {
StdLibWFileWriteSink() {
exists(CallNode call |
is_wfile(call.getFunction().(AttrNode).getObject("write")) and
call.getArg(0) = this
)
}
override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind }
}
/** Sink for `h.wfile.writelines` where `h` is an instance of BaseHttpRequestHandler. */
deprecated class StdLibWFileWritelinesSink extends HttpResponseTaintSink {
StdLibWFileWritelinesSink() {
exists(CallNode call |
is_wfile(call.getFunction().(AttrNode).getObject("writelines")) and
call.getArg(0) = this
)
}
override predicate sinks(TaintKind kind) { kind instanceof ExternalStringSequenceKind }
}

View File

@@ -1,28 +0,0 @@
/**
* Provides class representing the `tornado.redirect` function.
* This module is intended to be imported into a taint-tracking query
* to extend `TaintSink`.
*/
import python
import semmle.python.dataflow.TaintTracking
import semmle.python.security.strings.Basic
import semmle.python.web.Http
import Tornado
/**
* Represents an argument to the `tornado.redirect` function.
*/
deprecated class TornadoHttpRequestHandlerRedirect extends HttpRedirectTaintSink {
override string toString() { result = "tornado.HttpRequestHandler.redirect" }
TornadoHttpRequestHandlerRedirect() {
exists(CallNode call, ControlFlowNode node |
node = call.getFunction().(AttrNode).getObject("redirect") and
isTornadoRequestHandlerInstance(node) and
this = call.getArg(0)
)
}
override predicate sinks(TaintKind kind) { kind instanceof StringKind }
}

View File

@@ -1,69 +0,0 @@
import python
import semmle.python.dataflow.TaintTracking
import semmle.python.web.Http
import Tornado
/** A tornado.request.HttpRequest object */
deprecated class TornadoRequest extends TaintKind {
TornadoRequest() { this = "tornado.request.HttpRequest" }
override TaintKind getTaintOfAttribute(string name) {
result instanceof ExternalStringDictKind and
(
name = "headers" or
name = "cookies"
)
or
result instanceof ExternalStringKind and
(
name = "uri" or
name = "query" or
name = "body"
)
or
result instanceof ExternalStringSequenceDictKind and
(
name = "arguments" or
name = "query_arguments" or
name = "body_arguments"
)
}
}
deprecated class TornadoRequestSource extends HttpRequestTaintSource {
TornadoRequestSource() { isTornadoRequestHandlerInstance(this.(AttrNode).getObject("request")) }
override string toString() { result = "Tornado request source" }
override predicate isSourceOf(TaintKind kind) { kind instanceof TornadoRequest }
}
deprecated class TornadoExternalInputSource extends HttpRequestTaintSource {
TornadoExternalInputSource() {
exists(string name |
name in ["get_argument", "get_query_argument", "get_body_argument", "decode_argument"]
|
this = callToNamedTornadoRequestHandlerMethod(name)
)
}
override string toString() { result = "Tornado request method" }
override predicate isSourceOf(TaintKind kind) { kind instanceof ExternalStringKind }
}
deprecated class TornadoExternalInputListSource extends HttpRequestTaintSource {
TornadoExternalInputListSource() {
exists(string name |
name = "get_arguments" or
name = "get_query_arguments" or
name = "get_body_arguments"
|
this = callToNamedTornadoRequestHandlerMethod(name)
)
}
override string toString() { result = "Tornado request method" }
override predicate isSourceOf(TaintKind kind) { kind instanceof ExternalStringSequenceKind }
}

View File

@@ -1,47 +0,0 @@
import python
import semmle.python.dataflow.TaintTracking
import semmle.python.security.strings.Basic
private import semmle.python.web.Http
import Tornado
deprecated class TornadoConnection extends TaintKind {
TornadoConnection() { this = "tornado.http.connection" }
}
deprecated class TornadoConnectionSource extends TaintSource {
TornadoConnectionSource() {
isTornadoRequestHandlerInstance(this.(AttrNode).getObject("connection"))
}
override string toString() { result = "Tornado http connection source" }
override predicate isSourceOf(TaintKind kind) { kind instanceof TornadoConnection }
}
deprecated class TornadoConnectionWrite extends HttpResponseTaintSink {
override string toString() { result = "tornado.connection.write" }
TornadoConnectionWrite() {
exists(CallNode call, ControlFlowNode conn |
conn = call.getFunction().(AttrNode).getObject("write") and
this = call.getAnArg() and
exists(TornadoConnection tc | tc.taints(conn))
)
}
override predicate sinks(TaintKind kind) { kind instanceof StringKind }
}
deprecated class TornadoHttpRequestHandlerWrite extends HttpResponseTaintSink {
override string toString() { result = "tornado.HttpRequestHandler.write" }
TornadoHttpRequestHandlerWrite() {
exists(CallNode call, ControlFlowNode node |
node = call.getFunction().(AttrNode).getObject("write") and
this = call.getAnArg() and
isTornadoRequestHandlerInstance(node)
)
}
override predicate sinks(TaintKind kind) { kind instanceof StringKind }
}

View File

@@ -1,50 +0,0 @@
import python
import semmle.python.dataflow.TaintTracking
import semmle.python.web.Http
deprecated private ClassValue theTornadoRequestHandlerClass() {
result = Value::named("tornado.web.RequestHandler")
}
deprecated ClassValue aTornadoRequestHandlerClass() {
result.getABaseType+() = theTornadoRequestHandlerClass()
}
/**
* Holds if `node` is likely to refer to an instance of a tornado
* `RequestHandler` class.
*/
deprecated predicate isTornadoRequestHandlerInstance(ControlFlowNode node) {
node.pointsTo().getClass() = aTornadoRequestHandlerClass()
or
/*
* In some cases, the points-to analysis won't capture all instances we care
* about. For these, we use the following syntactic check. First, that
* `node` appears inside a method of a subclass of
* `tornado.web.RequestHandler`:
*/
node.getScope().getEnclosingScope() = aTornadoRequestHandlerClass().getScope() and
/* Secondly, that `node` refers to the `self` argument: */
node.isLoad() and
node.(NameNode).isSelf()
}
deprecated CallNode callToNamedTornadoRequestHandlerMethod(string name) {
isTornadoRequestHandlerInstance(result.getFunction().(AttrNode).getObject(name))
}
deprecated class TornadoCookieSet extends CookieSet, CallNode {
TornadoCookieSet() {
exists(ControlFlowNode f |
f = this.getFunction().(AttrNode).getObject("set_cookie") and
isTornadoRequestHandlerInstance(f)
)
}
override string toString() { result = CallNode.super.toString() }
override ControlFlowNode getKey() { result = this.getArg(0) }
override ControlFlowNode getValue() { result = this.getArg(1) }
}

View File

@@ -1,26 +0,0 @@
import python
import semmle.python.security.strings.External
import semmle.python.web.Http
import TurboGears
deprecated private class ValidatedMethodParameter extends Parameter {
ValidatedMethodParameter() {
exists(string name, TurboGearsControllerMethod method |
method.getArgByName(name) = this and
method.getValidationDict().getItem(_).(KeyValuePair).getKey().(StrConst).getText() = name
)
}
}
deprecated class UnvalidatedControllerMethodParameter extends HttpRequestTaintSource {
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 ExternalStringKind }
}

View File

@@ -1,31 +0,0 @@
import python
import semmle.python.dataflow.TaintTracking
import semmle.python.security.strings.Basic
import semmle.python.web.Http
import TurboGears
deprecated class ControllerMethodReturnValue extends HttpResponseTaintSink {
override string toString() { result = "TurboGears ControllerMethodReturnValue" }
ControllerMethodReturnValue() {
exists(TurboGearsControllerMethod m |
m.getAReturnValueFlowNode() = this and
not m.isTemplated()
)
}
override predicate sinks(TaintKind kind) { kind instanceof StringKind }
}
deprecated class ControllerMethodTemplatedReturnValue extends HttpResponseTaintSink {
override string toString() { result = "TurboGears ControllerMethodTemplatedReturnValue" }
ControllerMethodTemplatedReturnValue() {
exists(TurboGearsControllerMethod m |
m.getAReturnValueFlowNode() = this and
m.isTemplated()
)
}
override predicate sinks(TaintKind kind) { kind instanceof ExternalStringDictKind }
}

View File

@@ -1,37 +0,0 @@
import python
import semmle.python.dataflow.TaintTracking
deprecated private ClassValue theTurboGearsControllerClass() {
result = Value::named("tg.TGController")
}
deprecated ClassValue aTurboGearsControllerClass() {
result.getABaseType+() = theTurboGearsControllerClass()
}
deprecated class TurboGearsControllerMethod extends Function {
ControlFlowNode decorator;
TurboGearsControllerMethod() {
aTurboGearsControllerClass().getScope() = this.getScope() and
decorator = this.getADecorator().getAFlowNode() and
/* Is decorated with @expose() or @expose(path) */
(
decorator.(CallNode).getFunction().(NameNode).getId() = "expose"
or
decorator.pointsTo().getClass() = Value::named("tg.expose")
)
}
private ControlFlowNode templateName() { result = decorator.(CallNode).getArg(0) }
predicate isTemplated() { exists(this.templateName()) }
Dict getValidationDict() {
exists(Call call |
call = this.getADecorator() and
call.getFunc().(Name).getId() = "validate" and
call.getArg(0).pointsTo(_, result)
)
}
}

View File

@@ -1,30 +0,0 @@
import python
import semmle.python.dataflow.TaintTracking
import semmle.python.web.Http
import Twisted
/** A twisted.web.http.Request object */
deprecated class TwistedRequest extends TaintKind {
TwistedRequest() { this = "twisted.request.http.Request" }
override TaintKind getTaintOfAttribute(string name) {
result instanceof ExternalStringSequenceDictKind and
name = "args"
or
result instanceof ExternalStringKind and
name = "uri"
}
override TaintKind getTaintOfMethodResult(string name) {
name in ["getHeader", "getCookie", "getUser", "getPassword"] and
result instanceof ExternalStringKind
}
}
deprecated class TwistedRequestSource extends HttpRequestTaintSource {
TwistedRequestSource() { isTwistedRequestInstance(this) }
override string toString() { result = "Twisted request source" }
override predicate isSourceOf(TaintKind kind) { kind instanceof TwistedRequest }
}

View File

@@ -1,45 +0,0 @@
import python
import semmle.python.dataflow.TaintTracking
import semmle.python.web.Http
import semmle.python.security.strings.Basic
import Twisted
import Request
deprecated class TwistedResponse extends HttpResponseTaintSink {
TwistedResponse() {
exists(PythonFunctionValue func, string name |
isKnownRequestHandlerMethodName(name) and
name = func.getName() and
func = getTwistedRequestHandlerMethod(name) and
this = func.getAReturnedNode()
)
}
override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind }
override string toString() { result = "Twisted response" }
}
/**
* A sink of taint in the form of a "setter" method on a twisted request
* object, which affects the properties of the subsequent response sent to this
* request.
*/
deprecated class TwistedRequestSetter extends HttpResponseTaintSink {
TwistedRequestSetter() {
exists(CallNode call, ControlFlowNode node, string name |
(
name = "setHeader" or
name = "addCookie" or
name = "write"
) and
any(TwistedRequest t).taints(node) and
node = call.getFunction().(AttrNode).getObject(name) and
this = call.getAnArg()
)
}
override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind }
override string toString() { result = "Twisted request setter" }
}

View File

@@ -1,52 +0,0 @@
import python
import semmle.python.dataflow.TaintTracking
deprecated private ClassValue theTwistedHttpRequestClass() {
result = Value::named("twisted.web.http.Request")
}
deprecated private ClassValue theTwistedHttpResourceClass() {
result = Value::named("twisted.web.resource.Resource")
}
deprecated ClassValue aTwistedRequestHandlerClass() {
result.getABaseType+() = theTwistedHttpResourceClass()
}
deprecated FunctionValue getTwistedRequestHandlerMethod(string name) {
result = aTwistedRequestHandlerClass().declaredAttribute(name)
}
bindingset[name]
deprecated predicate isKnownRequestHandlerMethodName(string name) {
name = "render" or
name.matches("render_%")
}
/**
* Holds if `node` is likely to refer to an instance of the twisted
* `Request` class.
*/
deprecated predicate isTwistedRequestInstance(NameNode node) {
node.pointsTo().getClass() = theTwistedHttpRequestClass()
or
/*
* In points-to analysis cannot infer that a given object is an instance of
* the `twisted.web.http.Request` class, we also include any parameter
* called `request` that appears inside a subclass of a request handler
* class, and the appropriate arguments of known request handler methods.
*/
exists(Function func |
func = node.getScope() and
func.getEnclosingScope() = aTwistedRequestHandlerClass().getScope()
|
/* Any parameter called `request` */
node.getId() = "request" and
node.isParameter()
or
/* Any request parameter of a known request handler method */
isKnownRequestHandlerMethodName(func.getName()) and
node.getNode() = func.getArg(1)
)
}

View File

@@ -1,38 +0,0 @@
import python
import semmle.python.dataflow.TaintTracking
import semmle.python.web.Http
abstract deprecated class BaseWebobRequest extends TaintKind {
bindingset[this]
BaseWebobRequest() { any() }
override TaintKind getTaintOfAttribute(string name) {
result instanceof ExternalStringDictKind and
(
name = "GET" or
name = "POST" or
name = "headers"
)
or
result instanceof ExternalStringKind and
name = "body"
}
override TaintKind getTaintOfMethodResult(string name) {
result = this and
(
name = "copy" or
name = "copy_get" or
name = "copy_body"
)
or
result instanceof ExternalStringKind and
name = "as_bytes"
}
}
deprecated class WebobRequest extends BaseWebobRequest {
WebobRequest() { this = "webob.Request" }
override ClassValue getType() { result = Value::named("webob.request.Request") }
}

View File

@@ -1,19 +0,0 @@
from django.urls import path
from django.http import HttpResponse
from jinja2 import Template as Jinja2_Template
from jinja2 import Environment, DictLoader, escape
def a(request):
# Load the template
template = request.GET['template']
t = Jinja2_Template(template)
name = request.GET['name']
# Render the template with the context data
html = t.render(name=escape(name))
return HttpResponse(html)
urlpatterns = [
path('a', a),
]

View File

@@ -1,20 +0,0 @@
from django.urls import path
from django.http import HttpResponse
from jinja2 import Template as Jinja2_Template
from jinja2 import Environment, DictLoader, escape
def a(request):
# Load the template
template = request.GET['template']
env = SandboxedEnvironment(undefined=StrictUndefined)
t = env.from_string(template)
name = request.GET['name']
# Render the template with the context data
html = t.render(name=escape(name))
return HttpResponse(html)
urlpatterns = [
path('a', a),
]

View File

@@ -1,24 +0,0 @@
<!DOCTYPE qhelp SYSTEM "qhelp.dtd">
<qhelp>
<overview>
<p>
Template Injection occurs when user input is embedded in a template in an unsafe manner.
When an attacker is able to use native template syntax to inject a malicious payload into a template, which is then executed server-side is results in Server Side Template Injection.
</p>
</overview>
<recommendation>
<p>
To fix this, ensure that an untrusted value is not used as a template. If the application requirements do not alow this, use a sandboxed environment where access to unsafe attributes and methods is prohibited.
</p>
</recommendation>
<example>
<p>Consider the example given below, an untrusted HTTP parameter `template` is used to generate a Jinja2 template string. This can lead to remote code execution. </p>
<sample src="JinjaBad.py" />
<p>Here we have fixed the problem by using the Jinja sandbox environment for evaluating untrusted code.</p>
<sample src="JinjaGood.py" />
</example>
<references>
<li>Portswigger : [Server Side Template Injection](https://portswigger.net/web-security/server-side-template-injection)</li>
</references>
</qhelp>

View File

@@ -1,35 +0,0 @@
/**
* @name Server Side Template Injection
* @description Using user-controlled data to create a template can cause security issues.
* @kind path-problem
* @problem.severity error
* @precision high
* @id py/template-injection
* @tags security
* experimental
* external/cwe/cwe-074
*/
import python
import semmle.python.security.Paths
/* Sources */
import semmle.python.web.HttpRequest
/* Sinks */
import experimental.semmle.python.templates.Ssti
/* Flow */
import semmle.python.security.strings.Untrusted
class TemplateInjectionConfiguration extends TaintTracking::Configuration {
TemplateInjectionConfiguration() { this = "Template injection configuration" }
deprecated override predicate isSource(TaintTracking::Source source) {
source instanceof HttpRequestTaintSource
}
deprecated override predicate isSink(TaintTracking::Sink sink) { sink instanceof SSTISink }
}
from TemplateInjectionConfiguration config, TaintedPathSource src, TaintedPathSink sink
where config.hasFlowPath(src, sink)
select sink.getSink(), src, sink, "This Template depends on $@.", src.getSource(),
"a user-provided value"

View File

@@ -1,18 +0,0 @@
<!DOCTYPE qhelp SYSTEM "qhelp.dtd">
<qhelp>
<overview>
<p>
Processing an unvalidated XSL stylesheet can allow an attacker to change the structure and contents of the resultant XML, include arbitrary files from the file system, or execute arbitrary code.
</p>
</overview>
<recommendation>
<p>
This vulnerability can be prevented by not allowing untrusted user input to be passed as an XSL stylesheet.
If the application logic necessitates processing untrusted XSL stylesheets, the input should be properly filtered and sanitized before use.
</p>
</recommendation>
<example>
<p>In the example below, the XSL stylesheet is controlled by the user and hence leads to a vulnerability.</p>
<sample src="xslt.py" />
</example>
</qhelp>

View File

@@ -1,36 +0,0 @@
/**
* @name XSLT query built from user-controlled sources
* @description Building a XSLT query from user-controlled sources is vulnerable to insertion of
* malicious XSLT code by the user.
* @kind path-problem
* @problem.severity error
* @precision high
* @id py/xslt-injection
* @tags security
* experimental
* external/cwe/cwe-643
*/
import python
import semmle.python.security.Paths
/* Sources */
import semmle.python.web.HttpRequest
/* Sinks */
import experimental.semmle.python.security.injection.XSLT
class XsltInjectionConfiguration extends TaintTracking::Configuration {
XsltInjectionConfiguration() { this = "XSLT injection configuration" }
deprecated override predicate isSource(TaintTracking::Source source) {
source instanceof HttpRequestTaintSource
}
deprecated override predicate isSink(TaintTracking::Sink sink) {
sink instanceof XSLTInjection::XSLTInjectionSink
}
}
from XsltInjectionConfiguration config, TaintedPathSource src, TaintedPathSink sink
where config.hasFlowPath(src, sink)
select sink.getSink(), src, sink, "This XSLT query depends on $@.", src.getSource(),
"a user-provided value"

View File

@@ -1,14 +0,0 @@
from lxml import etree
from io import StringIO
from flask import Flask, request
app = Flask(__name__)
@app.route("/xslt")
def bad():
xsltQuery = request.args.get('xml', '')
xslt_root = etree.XML(xsltQuery)
f = StringIO('<foo><bar></bar></foo>')
tree = etree.parse(f)
result_tree = tree.xslt(xslt_root) # Not OK

View File

@@ -8,7 +8,6 @@
import python
import semmle.python.dataflow.TaintTracking
import semmle.python.web.HttpRequest
/** Models XSLT Injection related classes and functions */
module XsltInjection {
@@ -21,21 +20,6 @@ module XsltInjection {
/** DEPRECATED: Alias for XsltInjectionSink */
deprecated class XSLTInjectionSink = XsltInjectionSink;
/**
* A kind of "taint", representing an untrusted XML string
*/
deprecated private class ExternalXmlStringKind extends ExternalStringKind {
ExternalXmlStringKind() { this = "etree.XML string" }
override TaintKind getTaintForFlowStep(ControlFlowNode fromnode, ControlFlowNode tonode) {
etreeXml(fromnode, tonode) and result instanceof ExternalXmlKind
or
etreeFromStringList(fromnode, tonode) and result instanceof ExternalXmlKind
or
etreeFromString(fromnode, tonode) and result instanceof ExternalXmlKind
}
}
/**
* A kind of "taint", representing a XML encoded string
*/
@@ -43,32 +27,6 @@ module XsltInjection {
ExternalXmlKind() { this = "lxml etree xml" }
}
private predicate etreeXml(ControlFlowNode fromnode, CallNode tonode) {
// etree.XML("<xmlContent>")
exists(CallNode call | call.getFunction().(AttrNode).getObject("XML").pointsTo(etree()) |
call.getArg(0) = fromnode and
call = tonode
)
}
private predicate etreeFromString(ControlFlowNode fromnode, CallNode tonode) {
// etree.fromstring(text, parser=None)
exists(CallNode call | call.getFunction().(AttrNode).getObject("fromstring").pointsTo(etree()) |
call.getArg(0) = fromnode and
call = tonode
)
}
private predicate etreeFromStringList(ControlFlowNode fromnode, CallNode tonode) {
// etree.fromstringlist(strings, parser=None)
exists(CallNode call |
call.getFunction().(AttrNode).getObject("fromstringlist").pointsTo(etree())
|
call.getArg(0) = fromnode and
call = tonode
)
}
/**
* A Sink representing an argument to the `etree.XSLT` call.
*

View File

@@ -1,27 +0,0 @@
/** Provides classes which model the `airspeed` package. */
import python
import semmle.python.web.HttpRequest
import experimental.semmle.python.templates.SSTISink
/** returns the ClassValue representing `airspeed.Template` */
deprecated ClassValue theAirspeedTemplateClass() { result = Value::named("airspeed.Template") }
/**
* A sink representing the `airspeed.Template` class instantiation argument.
*
* import airspeed
* temp = airspeed.Template(`"sink"`)
*/
deprecated class AirspeedTemplateSink extends SSTISink {
override string toString() { result = "argument to airspeed.Template()" }
AirspeedTemplateSink() {
exists(CallNode call |
call.getFunction().pointsTo(theAirspeedTemplateClass()) and
call.getArg(0) = this
)
}
override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind }
}

View File

@@ -1,48 +0,0 @@
/** Provides classes which model the `bottle` package. */
import python
import semmle.python.web.HttpRequest
import experimental.semmle.python.templates.SSTISink
/** returns the ClassValue representing `bottle.SimpleTemplate` */
deprecated ClassValue theBottleSimpleTemplateClass() {
result = Value::named("bottle.SimpleTemplate")
}
/**
* A sink representing the `bottle.SimpleTemplate` class instantiation argument.
*
* from bottle import SimpleTemplate
* template = SimpleTemplate(`sink`)
*/
deprecated class BottleSimpleTemplateSink extends SSTISink {
override string toString() { result = "argument to bottle.SimpleTemplate()" }
BottleSimpleTemplateSink() {
exists(CallNode call |
call.getFunction().pointsTo(theBottleSimpleTemplateClass()) and
call.getArg(0) = this
)
}
override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind }
}
/**
* A sink representing the `bottle.template` function call argument.
*
* from bottle import template
* tmp = template(`sink`)
*/
deprecated class BottleTemplateSink extends SSTISink {
override string toString() { result = "argument to bottle.template()" }
BottleTemplateSink() {
exists(CallNode call |
call.getFunction() = theBottleModule().attr("template").getAReference() and
call.getArg(0) = this
)
}
override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind }
}

View File

@@ -1,29 +0,0 @@
/** Provides classes which model the `Chameleon` package. */
import python
import semmle.python.web.HttpRequest
import experimental.semmle.python.templates.SSTISink
/** returns the ClassValue representing `chameleon.PageTemplate` */
deprecated ClassValue theChameleonPageTemplateClass() {
result = Value::named("chameleon.PageTemplate")
}
/**
* A sink representing the `chameleon.PageTemplate` class instantiation argument.
*
* from chameleon import PageTemplate
* template = PageTemplate(`sink`)
*/
deprecated class ChameleonTemplateSink extends SSTISink {
override string toString() { result = "argument to Chameleon.PageTemplate()" }
ChameleonTemplateSink() {
exists(CallNode call |
call.getFunction().pointsTo(theChameleonPageTemplateClass()) and
call.getArg(0) = this
)
}
override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind }
}

View File

@@ -1,39 +0,0 @@
/** Provides classes which model the `Cheetah3` package. */
import python
import semmle.python.web.HttpRequest
import experimental.semmle.python.templates.SSTISink
/** returns the ClassValue representing `Cheetah.Template.Template` */
deprecated ClassValue theCheetahTemplateClass() {
result = Value::named("Cheetah.Template.Template")
}
/**
* A sink representing the instantiation argument of any class which derives from
* the `Cheetah.Template.Template` class .
*
* from Cheetah.Template import Template
* class Template3(Template):
* title = 'Hello World Example!'
* contents = 'Hello World!'
* t3 = Template3("sink")
*
* This will also detect cases of the following type :
*
* from Cheetah.Template import Template
* t3 = Template("sink")
*/
deprecated class CheetahTemplateInstantiationSink extends SSTISink {
override string toString() { result = "argument to Cheetah.Template.Template()" }
CheetahTemplateInstantiationSink() {
exists(CallNode call, ClassValue cv |
cv.getASuperType() = theCheetahTemplateClass() and
call.getFunction().pointsTo(cv) and
call.getArg(0) = this
)
}
override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind }
}

View File

@@ -1,36 +0,0 @@
/** Provides classes which model the `chevron` package. */
import python
import semmle.python.web.HttpRequest
import experimental.semmle.python.templates.SSTISink
/** returns the Value representing `chevron.render` function */
deprecated Value theChevronRenderFunc() { result = Value::named("chevron.render") }
/**
* A sink representing the `chevron.render` function call argument.
*
* import chevron
* tmp = chevron.render(`sink`,{ 'key' : 'value' })
*/
deprecated class ChevronRenderSink extends SSTISink {
override string toString() { result = "argument to chevron.render()" }
ChevronRenderSink() {
exists(CallNode call |
call.getFunction() = theChevronRenderFunc().getAReference() and
call.getArg(0) = this
)
// TODO: this should also detect :
// import chevron
// args = {
// 'template': 'sink',
// 'data': {
// 'mustache': 'World'
// }
// }
// chevron.render(**args)
}
override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind }
}

View File

@@ -1,35 +0,0 @@
/** Provides classes which model the `DjangoTemplate` package. */
import python
import semmle.python.web.HttpRequest
import experimental.semmle.python.templates.SSTISink
deprecated ClassValue theDjangoTemplateClass() { result = Value::named("django.template.Template") }
/**
* A sink representing `django.template.Template` class instantiation argument.
*
* from django.template import Template
* template = Template(`sink`)
*/
deprecated class DjangoTemplateTemplateSink extends SSTISink {
override string toString() { result = "argument to Django.template()" }
DjangoTemplateTemplateSink() {
exists(CallNode call |
call.getFunction().pointsTo(theDjangoTemplateClass()) and
call.getArg(0) = this
)
}
override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind }
}
// TODO (intentionally commented out QLDoc, since qlformat will delete those lines otherwise)
// /**
// * Sinks representing the django.template.Template class instantiation.
// *
// * from django.template import engines
// *
// * django_engine = engines["django"]
// * template = django_engine.from_string(`sink`)
// */

View File

@@ -1,28 +0,0 @@
/** Provides classes which model templates in the`flask` package. */
import python
import semmle.python.web.HttpRequest
import experimental.semmle.python.templates.SSTISink
deprecated Value theFlaskRenderTemplateClass() {
result = Value::named("flask.render_template_string")
}
/**
* A sink representing `flask.render_template_string` function call argument.
*
* from flask import render_template_string
* render_template_string(`sink`)
*/
deprecated class FlaskTemplateSink extends SSTISink {
override string toString() { result = "argument to flask.render_template_string()" }
FlaskTemplateSink() {
exists(CallNode call |
call.getFunction().pointsTo(theFlaskRenderTemplateClass()) and
call.getArg(0) = this
)
}
override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind }
}

View File

@@ -1,53 +0,0 @@
/** Provides classes which model the `Genshi` package. */
import python
import semmle.python.web.HttpRequest
import experimental.semmle.python.templates.SSTISink
/** returns the ClassValue representing `Genshi.template.TextTemplate` */
deprecated ClassValue theGenshiTextTemplateClass() {
result = Value::named("genshi.template.TextTemplate")
}
/** returns the ClassValue representing `Genshi.template.MarkupTemplate` */
deprecated ClassValue theGenshiMarkupTemplateClass() {
result = Value::named("genshi.template.MarkupTemplate")
}
/**
* A sink representing the `genshi.template.TextTemplate` class instantiation argument.
*
* from genshi.template import TextTemplate
* tmpl = TextTemplate('sink')
*/
deprecated class GenshiTextTemplateSink extends SSTISink {
override string toString() { result = "argument to genshi.template.TextTemplate()" }
GenshiTextTemplateSink() {
exists(CallNode call |
call.getFunction().pointsTo(theGenshiTextTemplateClass()) and
call.getArg(0) = this
)
}
override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind }
}
/**
* A sink representing the `genshi.template.MarkupTemplate` class instantiation argument.
*
* from genshi.template import MarkupTemplate
* tmpl = MarkupTemplate('sink')
*/
deprecated class GenshiMarkupTemplateSink extends SSTISink {
override string toString() { result = "argument to genshi.template.MarkupTemplate()" }
GenshiMarkupTemplateSink() {
exists(CallNode call |
call.getFunction().pointsTo(theGenshiMarkupTemplateClass()) and
call.getArg(0) = this
)
}
override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind }
}

View File

@@ -1,49 +0,0 @@
/** Provides classes which model the `Jinja2` package. */
import python
import semmle.python.web.HttpRequest
import experimental.semmle.python.templates.SSTISink
/** returns the ClassValue representing `jinja2.Template` */
deprecated ClassValue theJinja2TemplateClass() { result = Value::named("jinja2.Template") }
/** returns the ClassValue representing `jinja2.Template` */
deprecated Value theJinja2FromStringValue() { result = Value::named("jinja2.from_string") }
/**
* A sink representing the `jinja2.Template` class instantiation argument.
*
* from jinja2 import Template
* template = Template(`sink`)
*/
deprecated class Jinja2TemplateSink extends SSTISink {
override string toString() { result = "argument to jinja2.Template()" }
Jinja2TemplateSink() {
exists(CallNode call |
call.getFunction().pointsTo(theJinja2TemplateClass()) and
call.getArg(0) = this
)
}
override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind }
}
/**
* A sink representing the `jinja2.from_string` function call argument.
*
* from jinja2 import from_string
* template = from_string(`sink`)
*/
deprecated class Jinja2FromStringSink extends SSTISink {
override string toString() { result = "argument to jinja2.from_string()" }
Jinja2FromStringSink() {
exists(CallNode call |
call.getFunction().pointsTo(theJinja2FromStringValue()) and
call.getArg(0) = this
)
}
override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind }
}

View File

@@ -1,27 +0,0 @@
/** Provides classes which model the `Mako` package. */
import python
import semmle.python.web.HttpRequest
import experimental.semmle.python.templates.SSTISink
/** returns the ClassValue representing `mako.template.Template` */
deprecated ClassValue theMakoTemplateClass() { result = Value::named("mako.template.Template") }
/**
* A sink representing the `mako.template.Template` class instantiation argument.
*
* from mako.template import Template
* mytemplate = Template("hello world!")
*/
deprecated class MakoTemplateSink extends SSTISink {
override string toString() { result = "argument to mako.template.Template()" }
MakoTemplateSink() {
exists(CallNode call |
call.getFunction().pointsTo(theMakoTemplateClass()) and
call.getArg(0) = this
)
}
override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind }
}

View File

@@ -1,7 +0,0 @@
import semmle.python.dataflow.TaintTracking
/**
* A generic taint sink that is vulnerable to template inclusions.
* The `temp` in `jinja2.Template(temp)` and similar.
*/
abstract deprecated class SSTISink extends TaintSink { }

View File

@@ -1,13 +0,0 @@
/** Imports all files which model potential SSTI sinks */
import experimental.semmle.python.templates.Airspeed
import experimental.semmle.python.templates.Bottle
import experimental.semmle.python.templates.Chameleon
import experimental.semmle.python.templates.Cheetah
import experimental.semmle.python.templates.Chevron
import experimental.semmle.python.templates.DjangoTemplate
import experimental.semmle.python.templates.FlaskTemplate
import experimental.semmle.python.templates.Genshi
import experimental.semmle.python.templates.Jinja
import experimental.semmle.python.templates.Mako
import experimental.semmle.python.templates.TRender

View File

@@ -1,27 +0,0 @@
/** Provides classes which model the `TRender` package. */
import python
import semmle.python.web.HttpRequest
import experimental.semmle.python.templates.SSTISink
/** returns the ClassValue representing `trender.TRender` */
deprecated ClassValue theTRenderTemplateClass() { result = Value::named("trender.TRender") }
/**
* A sink representing the `trender.TRender` class instantiation argument.
*
* from trender import TRender
* template = TRender(`sink`)
*/
deprecated class TRenderTemplateSink extends SSTISink {
override string toString() { result = "argument to trender.TRender()" }
TRenderTemplateSink() {
exists(CallNode call |
call.getFunction().pointsTo(theTRenderTemplateClass()) and
call.getArg(0) = this
)
}
override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind }
}

View File

@@ -1,44 +0,0 @@
import python
import semmle.python.dataflow.TaintTracking
import semmle.python.security.strings.Untrusted
import semmle.python.security.Exceptions
class SimpleSource extends TaintSource {
SimpleSource() { this.(NameNode).getId() = "TAINTED_STRING" }
override predicate isSourceOf(TaintKind kind) { kind instanceof ExternalStringKind }
override string toString() { result = "taint source" }
}
class ListSource extends TaintSource {
ListSource() { this.(NameNode).getId() = "TAINTED_LIST" }
override predicate isSourceOf(TaintKind kind) { kind instanceof ExternalStringSequenceKind }
override string toString() { result = "list taint source" }
}
class DictSource extends TaintSource {
DictSource() { this.(NameNode).getId() = "TAINTED_DICT" }
override predicate isSourceOf(TaintKind kind) { kind instanceof ExternalStringDictKind }
override string toString() { result = "dict taint source" }
}
class ExceptionInfoSource extends TaintSource {
ExceptionInfoSource() { this.(NameNode).getId() = "TAINTED_EXCEPTION_INFO" }
override predicate isSourceOf(TaintKind kind) { kind instanceof ExceptionInfo }
override string toString() { result = "Exception info source" }
}
class ExternalFileObjectSource extends TaintSource {
ExternalFileObjectSource() { this.(NameNode).getId() = "TAINTED_FILE" }
override predicate isSourceOf(TaintKind kind) { kind instanceof ExternalFileObject }
override string toString() { result = "Tainted file source" }
}

View File

@@ -1 +0,0 @@
| test.py:4 | ok | fstring | Fstring | externally controlled string |

View File

@@ -1,33 +0,0 @@
import python
import semmle.python.security.TaintTracking
import semmle.python.web.HttpRequest
import semmle.python.security.strings.Untrusted
import Taint
from
Call call, Expr arg, boolean expected_taint, boolean has_taint, string test_res,
string taint_string
where
call.getLocation().getFile().getShortName() = "test.py" and
(
call.getFunc().(Name).getId() = "ensure_tainted" and
expected_taint = true
or
call.getFunc().(Name).getId() = "ensure_not_tainted" and
expected_taint = false
) and
arg = call.getAnArg() and
(
not exists(TaintedNode tainted | tainted.getAstNode() = arg) and
taint_string = "<NO TAINT>" and
has_taint = false
or
exists(TaintedNode tainted | tainted.getAstNode() = arg |
taint_string = tainted.getTaintKind().toString()
) and
has_taint = true
) and
if expected_taint = has_taint then test_res = "ok " else test_res = "fail"
// if expected_taint = has_taint then test_res = "✓" else test_res = "✕"
select arg.getLocation().toString(), test_res, call.getScope().(Function).getName(), arg.toString(),
taint_string

View File

@@ -1,5 +0,0 @@
def fstring():
tainted_string = TAINTED_STRING
ensure_tainted(
f"foo {tainted_string} bar"
)

View File

@@ -1,27 +0,0 @@
import python
import semmle.python.dataflow.TaintTracking
import semmle.python.security.strings.Untrusted
class SimpleSource extends TaintSource {
SimpleSource() { this.(NameNode).getId() = "TAINTED_STRING" }
override predicate isSourceOf(TaintKind kind) { kind instanceof ExternalStringKind }
override string toString() { result = "taint source" }
}
class ListSource extends TaintSource {
ListSource() { this.(NameNode).getId() = "TAINTED_LIST" }
override predicate isSourceOf(TaintKind kind) { kind instanceof ExternalStringSequenceKind }
override string toString() { result = "list taint source" }
}
class DictSource extends TaintSource {
DictSource() { this.(NameNode).getId() = "TAINTED_DICT" }
override predicate isSourceOf(TaintKind kind) { kind instanceof ExternalStringDictKind }
override string toString() { result = "dict taint source" }
}

View File

@@ -1,9 +0,0 @@
| test.py:11 | extended_unpacking | first | externally controlled string |
| test.py:11 | extended_unpacking | last | externally controlled string |
| test.py:11 | extended_unpacking | rest | [externally controlled string] |
| test.py:16 | also_allowed | a | [externally controlled string] |
| test.py:24 | also_allowed | b | NO TAINT |
| test.py:24 | also_allowed | c | NO TAINT |
| test.py:31 | nested | x | externally controlled string |
| test.py:31 | nested | xs | [externally controlled string] |
| test.py:31 | nested | ys | [externally controlled string] |

View File

@@ -1,19 +0,0 @@
import python
import semmle.python.dataflow.TaintTracking
import Taint
from Call call, Expr arg, string taint_string
where
call.getLocation().getFile().getShortName() = "test.py" and
call.getFunc().(Name).getId() = "test" and
arg = call.getAnArg() and
(
not exists(TaintedNode tainted | tainted.getAstNode() = arg) and
taint_string = "NO TAINT"
or
exists(TaintedNode tainted | tainted.getAstNode() = arg |
taint_string = tainted.getTaintKind().toString()
)
)
select arg.getLocation().toString(), call.getScope().(Function).getName(), arg.toString(),
taint_string

View File

@@ -1,31 +0,0 @@
# Extended Iterable Unpacking -- PEP 3132
# https://www.python.org/dev/peps/pep-3132/
def test(*args):
pass
def extended_unpacking():
first, *rest, last = TAINTED_LIST
test(first, rest, last)
def also_allowed():
*a, = TAINTED_LIST
test(a)
# for b, *c in [(1, 2, 3), (4, 5, 6, 7)]:
# print(c)
# i=0; c=[2,3]
# i=1; c=[5,6,7]
for b, *c in [TAINTED_LIST, TAINTED_LIST]:
test(b, c) # TODO: mark `c` as [taint]
def nested():
l = TAINTED_LIST
ll = [l,l]
[[x, *xs], ys] = ll
test(x, xs, ys)

View File

@@ -1,60 +0,0 @@
edges
| AirspeedSsti.py:10:16:10:27 | dict of externally controlled string | AirspeedSsti.py:10:16:10:43 | externally controlled string |
| AirspeedSsti.py:10:16:10:27 | dict of externally controlled string | AirspeedSsti.py:10:16:10:43 | externally controlled string |
| AirspeedSsti.py:10:16:10:43 | externally controlled string | AirspeedSsti.py:11:30:11:37 | externally controlled string |
| AirspeedSsti.py:10:16:10:43 | externally controlled string | AirspeedSsti.py:11:30:11:37 | externally controlled string |
| ChevronSsti.py:10:16:10:27 | dict of externally controlled string | ChevronSsti.py:10:16:10:43 | externally controlled string |
| ChevronSsti.py:10:16:10:27 | dict of externally controlled string | ChevronSsti.py:10:16:10:43 | externally controlled string |
| ChevronSsti.py:10:16:10:43 | externally controlled string | ChevronSsti.py:11:27:11:34 | externally controlled string |
| ChevronSsti.py:10:16:10:43 | externally controlled string | ChevronSsti.py:11:27:11:34 | externally controlled string |
| DjangoTemplates.py:6:8:6:14 | django.request.HttpRequest | DjangoTemplates.py:8:16:8:22 | django.request.HttpRequest |
| DjangoTemplates.py:6:8:6:14 | django.request.HttpRequest | DjangoTemplates.py:8:16:8:22 | django.request.HttpRequest |
| DjangoTemplates.py:8:16:8:22 | django.request.HttpRequest | DjangoTemplates.py:8:16:8:26 | django.http.request.QueryDict |
| DjangoTemplates.py:8:16:8:22 | django.request.HttpRequest | DjangoTemplates.py:8:16:8:26 | django.http.request.QueryDict |
| DjangoTemplates.py:8:16:8:26 | django.http.request.QueryDict | DjangoTemplates.py:8:16:8:38 | externally controlled string |
| DjangoTemplates.py:8:16:8:26 | django.http.request.QueryDict | DjangoTemplates.py:8:16:8:38 | externally controlled string |
| DjangoTemplates.py:8:16:8:38 | externally controlled string | DjangoTemplates.py:9:18:9:25 | externally controlled string |
| DjangoTemplates.py:8:16:8:38 | externally controlled string | DjangoTemplates.py:9:18:9:25 | externally controlled string |
| FlaskTemplate.py:17:41:17:52 | dict of externally controlled string | FlaskTemplate.py:17:41:17:68 | externally controlled string |
| FlaskTemplate.py:17:41:17:52 | dict of externally controlled string | FlaskTemplate.py:17:41:17:68 | externally controlled string |
| JinjaSsti.py:7:7:7:13 | django.request.HttpRequest | JinjaSsti.py:9:16:9:22 | django.request.HttpRequest |
| JinjaSsti.py:7:7:7:13 | django.request.HttpRequest | JinjaSsti.py:9:16:9:22 | django.request.HttpRequest |
| JinjaSsti.py:9:16:9:22 | django.request.HttpRequest | JinjaSsti.py:9:16:9:26 | django.http.request.QueryDict |
| JinjaSsti.py:9:16:9:22 | django.request.HttpRequest | JinjaSsti.py:9:16:9:26 | django.http.request.QueryDict |
| JinjaSsti.py:9:16:9:26 | django.http.request.QueryDict | JinjaSsti.py:9:16:9:38 | externally controlled string |
| JinjaSsti.py:9:16:9:26 | django.http.request.QueryDict | JinjaSsti.py:9:16:9:38 | externally controlled string |
| JinjaSsti.py:9:16:9:38 | externally controlled string | JinjaSsti.py:10:25:10:32 | externally controlled string |
| JinjaSsti.py:9:16:9:38 | externally controlled string | JinjaSsti.py:10:25:10:32 | externally controlled string |
| JinjaSsti.py:16:7:16:13 | django.request.HttpRequest | JinjaSsti.py:19:16:19:22 | django.request.HttpRequest |
| JinjaSsti.py:16:7:16:13 | django.request.HttpRequest | JinjaSsti.py:19:16:19:22 | django.request.HttpRequest |
| JinjaSsti.py:19:16:19:22 | django.request.HttpRequest | JinjaSsti.py:19:16:19:26 | django.http.request.QueryDict |
| JinjaSsti.py:19:16:19:22 | django.request.HttpRequest | JinjaSsti.py:19:16:19:26 | django.http.request.QueryDict |
| JinjaSsti.py:19:16:19:26 | django.http.request.QueryDict | JinjaSsti.py:19:16:19:38 | externally controlled string |
| JinjaSsti.py:19:16:19:26 | django.http.request.QueryDict | JinjaSsti.py:19:16:19:38 | externally controlled string |
| JinjaSsti.py:19:16:19:38 | externally controlled string | JinjaSsti.py:20:28:20:35 | externally controlled string |
| JinjaSsti.py:19:16:19:38 | externally controlled string | JinjaSsti.py:20:28:20:35 | externally controlled string |
| MakoSsti.py:6:10:6:16 | django.request.HttpRequest | MakoSsti.py:8:16:8:22 | django.request.HttpRequest |
| MakoSsti.py:6:10:6:16 | django.request.HttpRequest | MakoSsti.py:8:16:8:22 | django.request.HttpRequest |
| MakoSsti.py:8:16:8:22 | django.request.HttpRequest | MakoSsti.py:8:16:8:26 | django.http.request.QueryDict |
| MakoSsti.py:8:16:8:22 | django.request.HttpRequest | MakoSsti.py:8:16:8:26 | django.http.request.QueryDict |
| MakoSsti.py:8:16:8:26 | django.http.request.QueryDict | MakoSsti.py:8:16:8:38 | externally controlled string |
| MakoSsti.py:8:16:8:26 | django.http.request.QueryDict | MakoSsti.py:8:16:8:38 | externally controlled string |
| MakoSsti.py:8:16:8:38 | externally controlled string | MakoSsti.py:9:27:9:34 | externally controlled string |
| MakoSsti.py:8:16:8:38 | externally controlled string | MakoSsti.py:9:27:9:34 | externally controlled string |
| TRender.py:5:13:5:19 | django.request.HttpRequest | TRender.py:6:16:6:22 | django.request.HttpRequest |
| TRender.py:5:13:5:19 | django.request.HttpRequest | TRender.py:6:16:6:22 | django.request.HttpRequest |
| TRender.py:6:16:6:22 | django.request.HttpRequest | TRender.py:6:16:6:26 | django.http.request.QueryDict |
| TRender.py:6:16:6:22 | django.request.HttpRequest | TRender.py:6:16:6:26 | django.http.request.QueryDict |
| TRender.py:6:16:6:26 | django.http.request.QueryDict | TRender.py:6:16:6:38 | externally controlled string |
| TRender.py:6:16:6:26 | django.http.request.QueryDict | TRender.py:6:16:6:38 | externally controlled string |
| TRender.py:6:16:6:38 | externally controlled string | TRender.py:7:24:7:31 | externally controlled string |
| TRender.py:6:16:6:38 | externally controlled string | TRender.py:7:24:7:31 | externally controlled string |
#select
| AirspeedSsti.py:11:30:11:37 | template | AirspeedSsti.py:10:16:10:27 | dict of externally controlled string | AirspeedSsti.py:11:30:11:37 | externally controlled string | This Template depends on $@. | AirspeedSsti.py:10:16:10:27 | Attribute | a user-provided value |
| ChevronSsti.py:11:27:11:34 | template | ChevronSsti.py:10:16:10:27 | dict of externally controlled string | ChevronSsti.py:11:27:11:34 | externally controlled string | This Template depends on $@. | ChevronSsti.py:10:16:10:27 | Attribute | a user-provided value |
| DjangoTemplates.py:9:18:9:25 | template | DjangoTemplates.py:6:8:6:14 | django.request.HttpRequest | DjangoTemplates.py:9:18:9:25 | externally controlled string | This Template depends on $@. | DjangoTemplates.py:6:8:6:14 | request | a user-provided value |
| FlaskTemplate.py:17:41:17:68 | Attribute() | FlaskTemplate.py:17:41:17:52 | dict of externally controlled string | FlaskTemplate.py:17:41:17:68 | externally controlled string | This Template depends on $@. | FlaskTemplate.py:17:41:17:52 | Attribute | a user-provided value |
| JinjaSsti.py:10:25:10:32 | template | JinjaSsti.py:7:7:7:13 | django.request.HttpRequest | JinjaSsti.py:10:25:10:32 | externally controlled string | This Template depends on $@. | JinjaSsti.py:7:7:7:13 | request | a user-provided value |
| JinjaSsti.py:20:28:20:35 | template | JinjaSsti.py:16:7:16:13 | django.request.HttpRequest | JinjaSsti.py:20:28:20:35 | externally controlled string | This Template depends on $@. | JinjaSsti.py:16:7:16:13 | request | a user-provided value |
| MakoSsti.py:9:27:9:34 | template | MakoSsti.py:6:10:6:16 | django.request.HttpRequest | MakoSsti.py:9:27:9:34 | externally controlled string | This Template depends on $@. | MakoSsti.py:6:10:6:16 | request | a user-provided value |
| TRender.py:7:24:7:31 | template | TRender.py:5:13:5:19 | django.request.HttpRequest | TRender.py:7:24:7:31 | externally controlled string | This Template depends on $@. | TRender.py:5:13:5:19 | request | a user-provided value |

View File

@@ -1 +0,0 @@
experimental/Security/CWE-074/TemplateInjection.ql

View File

@@ -1,47 +0,0 @@
edges
| xslt.py:10:17:10:28 | dict of etree.XML string | xslt.py:10:17:10:43 | etree.XML string |
| xslt.py:10:17:10:28 | dict of etree.XML string | xslt.py:10:17:10:43 | etree.XML string |
| xslt.py:10:17:10:43 | etree.XML string | xslt.py:11:27:11:35 | etree.XML string |
| xslt.py:10:17:10:43 | etree.XML string | xslt.py:11:27:11:35 | etree.XML string |
| xslt.py:11:17:11:36 | lxml etree xml | xslt.py:14:29:14:37 | lxml etree xml |
| xslt.py:11:17:11:36 | lxml etree xml | xslt.py:14:29:14:37 | lxml etree xml |
| xslt.py:11:27:11:35 | etree.XML string | xslt.py:11:17:11:36 | lxml etree xml |
| xslt.py:11:27:11:35 | etree.XML string | xslt.py:11:17:11:36 | lxml etree xml |
| xsltInjection.py:10:17:10:28 | dict of etree.XML string | xsltInjection.py:10:17:10:43 | etree.XML string |
| xsltInjection.py:10:17:10:28 | dict of etree.XML string | xsltInjection.py:10:17:10:43 | etree.XML string |
| xsltInjection.py:10:17:10:43 | etree.XML string | xsltInjection.py:11:27:11:35 | etree.XML string |
| xsltInjection.py:10:17:10:43 | etree.XML string | xsltInjection.py:11:27:11:35 | etree.XML string |
| xsltInjection.py:11:17:11:36 | lxml etree xml | xsltInjection.py:12:28:12:36 | lxml etree xml |
| xsltInjection.py:11:17:11:36 | lxml etree xml | xsltInjection.py:12:28:12:36 | lxml etree xml |
| xsltInjection.py:11:27:11:35 | etree.XML string | xsltInjection.py:11:17:11:36 | lxml etree xml |
| xsltInjection.py:11:27:11:35 | etree.XML string | xsltInjection.py:11:17:11:36 | lxml etree xml |
| xsltInjection.py:17:17:17:28 | dict of etree.XML string | xsltInjection.py:17:17:17:43 | etree.XML string |
| xsltInjection.py:17:17:17:28 | dict of etree.XML string | xsltInjection.py:17:17:17:43 | etree.XML string |
| xsltInjection.py:17:17:17:43 | etree.XML string | xsltInjection.py:18:27:18:35 | etree.XML string |
| xsltInjection.py:17:17:17:43 | etree.XML string | xsltInjection.py:18:27:18:35 | etree.XML string |
| xsltInjection.py:18:17:18:36 | lxml etree xml | xsltInjection.py:21:29:21:37 | lxml etree xml |
| xsltInjection.py:18:17:18:36 | lxml etree xml | xsltInjection.py:21:29:21:37 | lxml etree xml |
| xsltInjection.py:18:27:18:35 | etree.XML string | xsltInjection.py:18:17:18:36 | lxml etree xml |
| xsltInjection.py:18:27:18:35 | etree.XML string | xsltInjection.py:18:17:18:36 | lxml etree xml |
| xsltInjection.py:26:17:26:28 | dict of etree.XML string | xsltInjection.py:26:17:26:43 | etree.XML string |
| xsltInjection.py:26:17:26:28 | dict of etree.XML string | xsltInjection.py:26:17:26:43 | etree.XML string |
| xsltInjection.py:26:17:26:43 | etree.XML string | xsltInjection.py:27:27:27:35 | etree.XML string |
| xsltInjection.py:26:17:26:43 | etree.XML string | xsltInjection.py:27:27:27:35 | etree.XML string |
| xsltInjection.py:27:17:27:36 | lxml etree xml | xsltInjection.py:31:24:31:32 | lxml etree xml |
| xsltInjection.py:27:17:27:36 | lxml etree xml | xsltInjection.py:31:24:31:32 | lxml etree xml |
| xsltInjection.py:27:27:27:35 | etree.XML string | xsltInjection.py:27:17:27:36 | lxml etree xml |
| xsltInjection.py:27:27:27:35 | etree.XML string | xsltInjection.py:27:17:27:36 | lxml etree xml |
| xsltInjection.py:35:17:35:28 | dict of etree.XML string | xsltInjection.py:35:17:35:43 | etree.XML string |
| xsltInjection.py:35:17:35:28 | dict of etree.XML string | xsltInjection.py:35:17:35:43 | etree.XML string |
| xsltInjection.py:35:17:35:43 | etree.XML string | xsltInjection.py:36:34:36:42 | etree.XML string |
| xsltInjection.py:35:17:35:43 | etree.XML string | xsltInjection.py:36:34:36:42 | etree.XML string |
| xsltInjection.py:36:17:36:43 | lxml etree xml | xsltInjection.py:40:24:40:32 | lxml etree xml |
| xsltInjection.py:36:17:36:43 | lxml etree xml | xsltInjection.py:40:24:40:32 | lxml etree xml |
| xsltInjection.py:36:34:36:42 | etree.XML string | xsltInjection.py:36:17:36:43 | lxml etree xml |
| xsltInjection.py:36:34:36:42 | etree.XML string | xsltInjection.py:36:17:36:43 | lxml etree xml |
#select
| xslt.py:14:29:14:37 | xslt_root | xslt.py:10:17:10:28 | dict of etree.XML string | xslt.py:14:29:14:37 | lxml etree xml | This XSLT query depends on $@. | xslt.py:10:17:10:28 | Attribute | a user-provided value |
| xsltInjection.py:12:28:12:36 | xslt_root | xsltInjection.py:10:17:10:28 | dict of etree.XML string | xsltInjection.py:12:28:12:36 | lxml etree xml | This XSLT query depends on $@. | xsltInjection.py:10:17:10:28 | Attribute | a user-provided value |
| xsltInjection.py:21:29:21:37 | xslt_root | xsltInjection.py:17:17:17:28 | dict of etree.XML string | xsltInjection.py:21:29:21:37 | lxml etree xml | This XSLT query depends on $@. | xsltInjection.py:17:17:17:28 | Attribute | a user-provided value |
| xsltInjection.py:31:24:31:32 | xslt_root | xsltInjection.py:26:17:26:28 | dict of etree.XML string | xsltInjection.py:31:24:31:32 | lxml etree xml | This XSLT query depends on $@. | xsltInjection.py:26:17:26:28 | Attribute | a user-provided value |
| xsltInjection.py:40:24:40:32 | xslt_root | xsltInjection.py:35:17:35:28 | dict of etree.XML string | xsltInjection.py:40:24:40:32 | lxml etree xml | This XSLT query depends on $@. | xsltInjection.py:35:17:35:28 | Attribute | a user-provided value |

View File

@@ -1 +0,0 @@
experimental/Security/CWE-091/Xslt.ql

View File

@@ -1,14 +0,0 @@
from lxml import etree
from io import StringIO
from flask import Flask, request
app = Flask(__name__)
@app.route("/xslt")
def bad():
xsltQuery = request.args.get('xml', '')
xslt_root = etree.XML(xsltQuery)
f = StringIO('<foo><bar></bar></foo>')
tree = etree.parse(f)
result_tree = tree.xslt(xslt_root) # Not OK

View File

@@ -1,10 +0,0 @@
from bottle import Bottle, route, request, redirect, response
import airspeed
app = Bottle()
@route('/other')
def a():
return airspeed.Template("sink")

View File

@@ -1,2 +0,0 @@
WARNING: Type SSTISink has been deprecated and may be removed in future (AirspeedSSTISinks.ql:4,6-14)
| Airspeed.py:10:30:10:35 | argument to airspeed.Template() |

View File

@@ -1,5 +0,0 @@
import python
import experimental.semmle.python.templates.Airspeed
from SSTISink s
select s

View File

@@ -1,17 +0,0 @@
from bottle import Bottle, route, request, redirect, response, SimpleTemplate
from bottle import template as temp
app = Bottle()
@route('/other')
def a():
template = "test"
tpl = SimpleTemplate(template)
@route('/other2')
def b():
template = "test"
return temp(template, name='World')

View File

@@ -1,3 +0,0 @@
WARNING: Type SSTISink has been deprecated and may be removed in future (BottleSSTISinks.ql:4,6-14)
| Bottle.py:11:26:11:33 | argument to bottle.SimpleTemplate() |
| Bottle.py:17:17:17:24 | argument to bottle.template() |

View File

@@ -1,5 +0,0 @@
import python
import experimental.semmle.python.templates.Bottle
from SSTISink s
select s

View File

@@ -1,5 +0,0 @@
from chameleon import PageTemplate
def chameleon():
template = PageTemplate("sink")

View File

@@ -1,2 +0,0 @@
WARNING: Type SSTISink has been deprecated and may be removed in future (ChameleonSSTISinks.ql:4,6-14)
| Chameleon.py:5:29:5:34 | argument to Chameleon.PageTemplate() |

View File

@@ -1,5 +0,0 @@
import python
import experimental.semmle.python.templates.Chameleon
from SSTISink s
select s

View File

@@ -1,3 +0,0 @@
WARNING: Type SSTISink has been deprecated and may be removed in future (CheetahSSTISinks.ql:4,6-14)
| CheetahSinks.py:10:21:10:26 | argument to Cheetah.Template.Template() |
| CheetahSinks.py:20:20:20:25 | argument to Cheetah.Template.Template() |

View File

@@ -1,5 +0,0 @@
import python
import experimental.semmle.python.templates.Cheetah
from SSTISink s
select s

Some files were not shown because too many files have changed in this diff Show More