Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions python/ql/src/Security/CWE-022/PathInjection.ql
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* @name Uncontrolled data used in path expression
* @description Accessing paths influenced by users can allow an attacker to access unexpected resources.
* @kind problem
* @kind path-problem

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably have a change note about the conversion of some queries to path queries.

* @problem.severity error
* @sub-severity high
* @precision high
Expand All @@ -17,6 +17,7 @@
*/

import python
import semmle.python.security.Paths

/* Sources */
import semmle.python.web.HttpRequest
Expand All @@ -25,7 +26,6 @@ import semmle.python.web.HttpRequest
import semmle.python.security.injection.Path


from TaintSource src, TaintSink sink
where src.flowsToSink(sink)

select sink, "This path depends on $@.", src, "a user-provided value"
from TaintedPathSource src, TaintedPathSink sink
where src.flowsTo(sink)
select sink.getSink(), src, sink, "This path depends on $@.", src.getSource(), "a user-provided value"
10 changes: 5 additions & 5 deletions python/ql/src/Security/CWE-078/CommandInjection.ql
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* @name Uncontrolled command line
* @description Using externally controlled strings in a command line may allow a malicious
* user to change the meaning of the command.
* @kind problem
* @kind path-problem
* @problem.severity error
* @sub-severity high
* @precision high
Expand All @@ -15,14 +15,14 @@
*/

import python
import semmle.python.security.Paths

/* Sources */
import semmle.python.web.HttpRequest

/* Sinks */
import semmle.python.security.injection.Command

from TaintSource src, TaintSink sink
where src.flowsToSink(sink)

select sink, "This command depends on $@.", src, "a user-provided value"
from TaintedPathSource src, TaintedPathSink sink
where src.flowsTo(sink)
select sink.getSink(), src, sink, "This command depends on $@.", src.getSource(), "a user-provided value"
12 changes: 5 additions & 7 deletions python/ql/src/Security/CWE-079/ReflectedXss.ql
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* @name Reflected server-side cross-site scripting
* @description Writing user input directly to a web page
* allows for a cross-site scripting vulnerability.
* @kind problem
* @kind path-problem
* @problem.severity error
* @sub-severity high
* @precision high
Expand All @@ -13,6 +13,7 @@
*/

import python
import semmle.python.security.Paths

/* Sources */
import semmle.python.web.HttpRequest
Expand All @@ -24,9 +25,6 @@ import semmle.python.web.HttpResponse
/* Flow */
import semmle.python.security.strings.Untrusted

from TaintSource src, TaintSink sink
where src.flowsToSink(sink)

select sink, "Cross-site scripting vulnerability due to $@.",
src, "user-provided value"

from TaintedPathSource src, TaintedPathSink sink
where src.flowsTo(sink)
select sink.getSink(), src, sink, "Cross-site scripting vulnerability due to $@.", src.getSource(), "user-provided value"
10 changes: 5 additions & 5 deletions python/ql/src/Security/CWE-089/SqlInjection.ql
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* @name SQL query built from user-controlled sources
* @description Building a SQL query from user-controlled sources is vulnerable to insertion of
* malicious SQL code by the user.
* @kind problem
* @kind path-problem
* @problem.severity error
* @precision high
* @id py/sql-injection
Expand All @@ -12,6 +12,7 @@
*/

import python
import semmle.python.security.Paths

/* Sources */
import semmle.python.web.HttpRequest
Expand All @@ -22,7 +23,6 @@ import semmle.python.web.django.Db
import semmle.python.web.django.Model


from TaintSource src, TaintSink sink
where src.flowsToSink(sink)

select sink, "This SQL query depends on $@.", src, "a user-provided value"
from TaintedPathSource src, TaintedPathSink sink
where src.flowsTo(sink)
select sink.getSink(), src, sink, "This SQL query depends on $@.", src.getSource(), "a user-provided value"
10 changes: 5 additions & 5 deletions python/ql/src/Security/CWE-094/CodeInjection.ql
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* @name Code injection
* @description Interpreting unsanitized user input as code allows a malicious user arbitrary
* code execution.
* @kind problem
* @kind path-problem
* @problem.severity error
* @sub-severity high
* @precision high
Expand All @@ -15,6 +15,7 @@
*/

import python
import semmle.python.security.Paths

/* Sources */
import semmle.python.web.HttpRequest
Expand All @@ -23,7 +24,6 @@ import semmle.python.web.HttpRequest
import semmle.python.security.injection.Exec


from TaintSource src, TaintSink sink
where src.flowsToSink(sink)

select sink, "$@ flows to here and is interpreted as code.", src, "User-provided value"
from TaintedPathSource src, TaintedPathSink sink
where src.flowsTo(sink)
select sink.getSink(), src, sink, "$@ flows to here and is interpreted as code.", src.getSource(), "User-provided value"
9 changes: 5 additions & 4 deletions python/ql/src/Security/CWE-209/StackTraceExposure.ql
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* @description Leaking information about an exception, such as messages and stack traces, to an
* external user can expose implementation details that are useful to an attacker for
* developing a subsequent exploit.
* @kind problem
* @kind path-problem
* @problem.severity error
* @precision high
* @id py/stack-trace-exposure
Expand All @@ -13,10 +13,11 @@
*/

import python
import semmle.python.security.Paths

import semmle.python.security.Exceptions
import semmle.python.web.HttpResponse

from TaintSource src, TaintSink sink
where src.flowsToSink(sink)
select sink, "$@ may be exposed to an external user", src, "Error information"
from TaintedPathSource src, TaintedPathSink sink
where src.flowsTo(sink)
select sink.getSink(), src, sink, "$@ may be exposed to an external user", src.getSource(), "Error information"
10 changes: 5 additions & 5 deletions python/ql/src/Security/CWE-502/UnsafeDeserialization.ql
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* @name Deserializing untrusted input
* @description Deserializing user-controlled data may allow attackers to execute arbitrary code.
* @kind problem
* @kind path-problem
* @id py/unsafe-deserialization
* @problem.severity error
* @sub-severity high
Expand All @@ -14,6 +14,7 @@ import python

// Sources -- Any untrusted input
import semmle.python.web.HttpRequest
import semmle.python.security.Paths

// Flow -- untrusted string
import semmle.python.security.strings.Untrusted
Expand All @@ -23,8 +24,7 @@ import semmle.python.security.injection.Pickle
import semmle.python.security.injection.Marshal
import semmle.python.security.injection.Yaml

from TaintSource src, TaintSink sink

where src.flowsToSink(sink)

select sink, "Deserializing of $@.", src, "untrusted input"
from TaintedPathSource src, TaintedPathSink sink
where src.flowsTo(sink)
select sink.getSink(), src, sink, "Deserializing of $@.", src.getSource(), "untrusted input"
11 changes: 5 additions & 6 deletions python/ql/src/Security/CWE-601/UrlRedirect.ql
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* @name URL redirection from remote source
* @description URL redirection based on unvalidated user input
* may cause redirection to malicious web sites.
* @kind problem
* @kind path-problem
* @problem.severity error
* @sub-severity low
* @id py/url-redirection
Expand All @@ -12,7 +12,7 @@
*/

import python

import semmle.python.security.Paths

import semmle.python.web.HttpRedirect
import semmle.python.web.HttpRequest
Expand All @@ -28,8 +28,7 @@ class UntrustedPrefixStringKind extends UntrustedStringKind {

}

from TaintSource src, TaintSink sink
where src.flowsToSink(sink)

select sink, "Untrusted URL redirection due to $@.", src, "a user-provided value"
from TaintedPathSource src, TaintedPathSink sink
where src.flowsTo(sink)
select sink.getSink(), src, sink, "Untrusted URL redirection due to $@.", src.getSource(), "a user-provided value"

9 changes: 9 additions & 0 deletions python/ql/src/semmle/python/security/Exceptions.qll
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ class ExceptionInfo extends StringKind {
ExceptionInfo() {
this = "exception.info"
}

override string repr() {
result = "exception info"
}

}


Expand All @@ -36,6 +41,10 @@ class ExceptionKind extends TaintKind {
this = "exception.kind"
}

override string repr() {
result = "exception"
}

override TaintKind getTaintOfAttribute(string name) {
name = "args" and result instanceof ExceptionInfoSequence
or
Expand Down
25 changes: 25 additions & 0 deletions python/ql/src/semmle/python/security/Paths.qll
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import python

import semmle.python.security.TaintTracking

query predicate edges(TaintedNode fromnode, TaintedNode tonode) {
fromnode.getASuccessor() = tonode
}

private TaintedNode first_child(TaintedNode parent) {
result.getContext().getCaller() = parent.getContext() and
parent.getASuccessor() = result
}

private TaintedNode next_sibling(TaintedNode child) {
child.getASuccessor() = result and
child.getContext() = result.getContext()
}

query predicate parents(TaintedNode child, TaintedNode parent) {
child = first_child(parent) or
exists(TaintedNode prev |
parents(prev, parent) and
child = next_sibling(child)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Post-merge drive-by comment: This looks wrong.

)
}
56 changes: 55 additions & 1 deletion python/ql/src/semmle/python/security/TaintTracking.qll
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,8 @@ abstract class TaintKind extends string {
none()
}

string repr() { result = this }

}

/** Taint kinds representing collections of other taint kind.
Expand Down Expand Up @@ -208,6 +210,10 @@ class SequenceKind extends CollectionKind {
name = "pop" and result = this.getItem()
}

override string repr() {
result = "sequence of " + itemKind
}

}

/* Helper for getTaintForStep() */
Expand Down Expand Up @@ -281,6 +287,10 @@ class DictKind extends CollectionKind {
name = "itervalues" and result.(SequenceKind).getItem() = valueKind
}

override string repr() {
result = "dict of " + valueKind
}

}


Expand Down Expand Up @@ -603,7 +613,9 @@ private predicate user_tainted_def(TaintedDefinition def, TaintFlowImplementatio
*/
class TaintedNode extends TTaintedNode {

string toString() { result = this.getTrackedValue().toString() + " at " + this.getLocation() }
string toString() { result = this.getTrackedValue().repr() }

string debug() { result = this.getTrackedValue().toString() + " at " + this.getNode().getLocation() }

TaintedNode getASuccessor() {
exists(TaintFlowImplementation::TrackedValue tokind, CallContext tocontext, ControlFlowNode tonode |
Expand Down Expand Up @@ -675,6 +687,35 @@ class TaintedNode extends TTaintedNode {

}

class TaintedPathSource extends TaintedNode {

TaintedPathSource() {
this.getNode().(TaintSource).isSourceOf(this.getTaintKind(), this.getContext())
}

/** Holds if taint can flow from this source to sink `sink` */
final predicate flowsTo(TaintedPathSink sink) {
this.getASuccessor*() = sink
}

TaintSource getSource() {
result = this.getNode()
}

}

class TaintedPathSink extends TaintedNode {

TaintedPathSink() {
this.getNode().(TaintSink).sinks(this.getTaintKind())
}

TaintSink getSink() {
result = this.getNode()
}

}

/** This module contains the implementation of taint-flow.
* It is recommended that users use the `TaintedNode` class, rather than using this module directly
* as the interface of this module may change without warning.
Expand Down Expand Up @@ -718,12 +759,18 @@ library module TaintFlowImplementation {

abstract string toString();

abstract string repr();

abstract TrackedValue toKind(TaintKind kind);

}

class TrackedTaint extends TrackedValue, TTrackedTaint {

override string repr() {
result = this.getKind().repr()
}

override string toString() {
result = "Taint " + this.getKind()
}
Expand All @@ -740,6 +787,13 @@ library module TaintFlowImplementation {

class TrackedAttribute extends TrackedValue, TTrackedAttribute {

override string repr() {
exists(string name, TaintKind kind |
this = TTrackedAttribute(name, kind) and
result = "." + name + "=" + kind.repr()
)
}

override string toString() {
exists(string name, TaintKind kind |
this = TTrackedAttribute(name, kind) and
Expand Down
3 changes: 3 additions & 0 deletions python/ql/src/semmle/python/security/injection/Command.qll
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ class FirstElementKind extends TaintKind {
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() {
Expand Down
Loading