Files
codeql/python/ql/test/library-tests/taint/general/TaintLib.qll
2025-11-26 12:30:31 +00:00

282 lines
7.7 KiB
Plaintext

import python
import semmle.python.dataflow.TaintTracking
private import LegacyPointsTo
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
}
override predicate sanitizingDefinition(TaintKind taint, EssaDefinition def) {
exists(CallNode call |
def.(ArgumentRefinement).getInput().getAUse() = call.getAnArg() and
call.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 }
}
class Falsey extends TaintKind {
Falsey() { this = "falsey" }
override boolean booleanValue() { result = false }
}
class FalseySource extends TaintSource {
FalseySource() { this.(NameNode).getId() = "FALSEY" }
override predicate isSourceOf(TaintKind kind) { kind instanceof Falsey }
override string toString() { result = "falsey.source" }
}
class TaintIterable extends TaintKind {
TaintIterable() { this = "iterable.simple" }
override TaintKind getTaintForIteration() { result instanceof SimpleTest }
}
class TaintIterableSource extends TaintSource {
TaintIterableSource() { this.(NameNode).getId() = "ITERABLE_SOURCE" }
override predicate isSourceOf(TaintKind kind) { kind instanceof TaintIterable }
}