mirror of
https://github.com/github/codeql.git
synced 2026-03-06 15:49:08 +01:00
337 lines
7.5 KiB
Plaintext
337 lines
7.5 KiB
Plaintext
import python
|
|
import semmle.python.security.TaintTracking
|
|
|
|
|
|
class SimpleTest extends TaintKind {
|
|
|
|
SimpleTest() {
|
|
this = "simple.test"
|
|
}
|
|
|
|
}
|
|
|
|
class SimpleSink extends TaintSink {
|
|
|
|
override string toString() { result = "Simple sink" }
|
|
|
|
SimpleSink() {
|
|
exists(CallNode call |
|
|
call.getFunction().(NameNode).getId() = "SINK" and
|
|
this = call.getAnArg()
|
|
)
|
|
}
|
|
|
|
override predicate sinks(TaintKind taint) {
|
|
taint instanceof SimpleTest
|
|
}
|
|
|
|
}
|
|
|
|
class SimpleSource extends TaintSource {
|
|
|
|
SimpleSource() { this.(NameNode).getId() = "SOURCE" }
|
|
|
|
override predicate isSourceOf(TaintKind kind) {
|
|
kind instanceof SimpleTest
|
|
}
|
|
|
|
override string toString() {
|
|
result = "simple.source"
|
|
}
|
|
|
|
}
|
|
|
|
class SimpleSanitizer extends Sanitizer {
|
|
|
|
SimpleSanitizer() { this = "Simple sanitizer" }
|
|
|
|
override predicate sanitizingNode(TaintKind taint, ControlFlowNode node) {
|
|
node.(CallNode).getFunction().(NameNode).getId() = "SANITIZE" and
|
|
taint instanceof SimpleTest
|
|
}
|
|
|
|
}
|
|
|
|
class BasicCustomTaint extends TaintKind {
|
|
|
|
BasicCustomTaint() {
|
|
this = "basic.custom"
|
|
}
|
|
|
|
override TaintKind getTaintForFlowStep(ControlFlowNode fromnode, ControlFlowNode tonode) {
|
|
tonode.(CallNode).getAnArg() = fromnode and
|
|
tonode.(CallNode).getFunction().(NameNode).getId() = "TAINT_FROM_ARG" and
|
|
result = this
|
|
}
|
|
|
|
}
|
|
|
|
class BasicCustomSink extends TaintSink {
|
|
|
|
override string toString() { result = "Basic custom sink" }
|
|
|
|
BasicCustomSink() {
|
|
exists(CallNode call |
|
|
call.getFunction().(NameNode).getId() = "CUSTOM_SINK" and
|
|
this = call.getAnArg()
|
|
)
|
|
}
|
|
|
|
override predicate sinks(TaintKind taint) {
|
|
taint instanceof BasicCustomTaint
|
|
}
|
|
|
|
}
|
|
|
|
|
|
class BasicCustomSource extends TaintSource {
|
|
|
|
BasicCustomSource() { this.(NameNode).getId() = "CUSTOM_SOURCE" }
|
|
|
|
override predicate isSourceOf(TaintKind kind) {
|
|
kind instanceof BasicCustomTaint
|
|
}
|
|
|
|
override string toString() {
|
|
result = "basic.custom.source"
|
|
}
|
|
|
|
}
|
|
|
|
class Rock extends TaintKind {
|
|
|
|
Rock() { this = "rock" }
|
|
|
|
override TaintKind getTaintOfMethodResult(string name) {
|
|
name = "prev" and result instanceof Scissors
|
|
}
|
|
|
|
predicate isSink(ControlFlowNode sink) {
|
|
exists(CallNode call |
|
|
call.getArg(0) = sink and
|
|
call.getFunction().(NameNode).getId() = "paper"
|
|
)
|
|
}
|
|
|
|
}
|
|
|
|
class Paper extends TaintKind {
|
|
|
|
Paper() { this = "paper" }
|
|
|
|
override TaintKind getTaintOfMethodResult(string name) {
|
|
name = "prev" and result instanceof Rock
|
|
}
|
|
|
|
predicate isSink(ControlFlowNode sink) {
|
|
exists(CallNode call |
|
|
call.getArg(0) = sink and
|
|
call.getFunction().(NameNode).getId() = "scissors"
|
|
)
|
|
}
|
|
|
|
}
|
|
|
|
class Scissors extends TaintKind {
|
|
|
|
Scissors() { this = "scissors" }
|
|
|
|
override TaintKind getTaintOfMethodResult(string name) {
|
|
name = "prev" and result instanceof Paper
|
|
}
|
|
|
|
predicate isSink(ControlFlowNode sink) {
|
|
exists(CallNode call |
|
|
call.getArg(0) = sink and
|
|
call.getFunction().(NameNode).getId() = "rock"
|
|
)
|
|
}
|
|
|
|
}
|
|
|
|
class RockPaperScissorSource extends TaintSource {
|
|
|
|
RockPaperScissorSource() {
|
|
exists(string name |
|
|
this.(NameNode).getId() = name |
|
|
name = "ROCK" or name = "PAPER" or name = "SCISSORS"
|
|
)
|
|
}
|
|
|
|
override predicate isSourceOf(TaintKind kind) {
|
|
kind = this.(NameNode).getId().toLowerCase()
|
|
}
|
|
|
|
override string toString() {
|
|
result = "rock.paper.scissors.source"
|
|
}
|
|
|
|
}
|
|
|
|
private predicate function_param(string funcname, ControlFlowNode arg) {
|
|
exists(FunctionObject f |
|
|
f.getName() = funcname and
|
|
arg = f.getArgumentForCall(_, _)
|
|
)
|
|
}
|
|
|
|
class RockPaperScissorSink extends TaintSink {
|
|
|
|
RockPaperScissorSink() {
|
|
exists(string name |
|
|
function_param(name, this) |
|
|
name = "rock" or name = "paper" or name = "scissors"
|
|
)
|
|
}
|
|
|
|
override predicate sinks(TaintKind taint) {
|
|
exists(string name |
|
|
function_param(name, this) |
|
|
name = "paper" and taint = "rock"
|
|
or
|
|
name = "rock" and taint = "scissors"
|
|
or
|
|
name = "scissors" and taint = "paper"
|
|
)
|
|
}
|
|
|
|
override string toString() {
|
|
result = "rock.paper.scissors.sink"
|
|
}
|
|
|
|
}
|
|
|
|
class TaintCarrier extends TaintKind {
|
|
|
|
TaintCarrier() { this = "explicit.carrier" }
|
|
|
|
override TaintKind getTaintOfMethodResult(string name) {
|
|
name = "get_taint" and result instanceof SimpleTest
|
|
}
|
|
|
|
|
|
}
|
|
|
|
/* There is no sink for `TaintCarrier`. It is not "dangerous" in itself; it merely holds a `SimpleTest`. */
|
|
class TaintCarrierSource extends TaintSource {
|
|
|
|
TaintCarrierSource() {
|
|
this.(NameNode).getId() = "TAINT_CARRIER_SOURCE"
|
|
}
|
|
|
|
override predicate isSourceOf(TaintKind kind) {
|
|
kind instanceof TaintCarrier
|
|
}
|
|
|
|
override string toString() {
|
|
result = "taint.carrier.source"
|
|
}
|
|
}
|
|
|
|
|
|
/* Some more realistic examples */
|
|
|
|
abstract class UserInput extends TaintKind {
|
|
|
|
bindingset[this]
|
|
UserInput() { any() }
|
|
|
|
}
|
|
|
|
class UserInputSource extends TaintSource {
|
|
|
|
UserInputSource() {
|
|
this.(CallNode).getFunction().(NameNode).getId() = "user_input"
|
|
}
|
|
|
|
override predicate isSourceOf(TaintKind kind) {
|
|
kind instanceof UserInput
|
|
}
|
|
|
|
override string toString() {
|
|
result = "user.input.source"
|
|
}
|
|
|
|
}
|
|
|
|
class SqlInjectionTaint extends UserInput {
|
|
|
|
SqlInjectionTaint() { this = "SQL injection" }
|
|
|
|
}
|
|
|
|
class CommandInjectionTaint extends UserInput {
|
|
|
|
CommandInjectionTaint() { this = "Command injection" }
|
|
|
|
}
|
|
|
|
class SqlSanitizer extends Sanitizer {
|
|
|
|
SqlSanitizer() { this = "SQL sanitizer" }
|
|
|
|
/** Holds if `test` shows value to be untainted with `taint` */
|
|
override predicate sanitizingEdge(TaintKind taint, PyEdgeRefinement test) {
|
|
exists(FunctionObject f, CallNode call |
|
|
f.getName() = "isEscapedSql" and
|
|
test.getTest() = call and
|
|
call.getAnArg() = test.getSourceVariable().getAUse() and
|
|
f.getACall() = call and
|
|
test.getSense() = true
|
|
) and
|
|
taint instanceof SqlInjectionTaint
|
|
}
|
|
|
|
}
|
|
|
|
class CommandSanitizer extends Sanitizer {
|
|
|
|
CommandSanitizer() { this = "Command sanitizer" }
|
|
|
|
/** Holds if `test` shows value to be untainted with `taint` */
|
|
override predicate sanitizingEdge(TaintKind taint, PyEdgeRefinement test) {
|
|
exists(FunctionObject f |
|
|
f.getName() = "isValidCommand" and
|
|
f.getACall().(CallNode).getAnArg() = test.getSourceVariable().getAUse() and
|
|
test.getSense() = true
|
|
) and
|
|
taint instanceof CommandInjectionTaint
|
|
}
|
|
|
|
}
|
|
|
|
class SqlQuery extends TaintSink {
|
|
|
|
SqlQuery() {
|
|
exists(CallNode call |
|
|
call.getFunction().(NameNode).getId() = "sql_query" and
|
|
call.getAnArg() = this
|
|
)
|
|
}
|
|
|
|
override string toString() { result = "SQL query" }
|
|
|
|
override predicate sinks(TaintKind taint) {
|
|
taint instanceof SqlInjectionTaint
|
|
}
|
|
|
|
}
|
|
|
|
|
|
class OsCommand extends TaintSink {
|
|
|
|
OsCommand() {
|
|
exists(CallNode call |
|
|
call.getFunction().(NameNode).getId() = "os_command" and
|
|
call.getAnArg() = this
|
|
)
|
|
}
|
|
|
|
override string toString() { result = "OS command" }
|
|
|
|
override predicate sinks(TaintKind taint) {
|
|
taint instanceof CommandInjectionTaint
|
|
}
|
|
|
|
}
|