C++: SqlPqxxTainted.ql style fixes

This commit is contained in:
Evgenii Protsenko
2021-05-05 21:48:14 +03:00
parent 955d97f6be
commit 330eaea467

View File

@@ -13,9 +13,6 @@
import cpp
import semmle.code.cpp.security.Security
// import semmle.code.cpp.security.FunctionWithWrappers
// import semmle.code.cpp.security.TaintTracking
// import TaintedWithPath
import semmle.code.cpp.dataflow.TaintTracking
import DataFlow::PathGraph
@@ -69,102 +66,74 @@ predicate pqxxTransactionSqlArgument(string function, int arg) {
function = "stream" and arg = 0
}
predicate pqxxConnectionSqlArgument(string function, int arg) {
function = "prepare" and arg = 1
}
predicate pqxxConnectionSqlArgument(string function, int arg) { function = "prepare" and arg = 1 }
Expr getPqxxSqlArgument() {
exists(FunctionCall fc, Expr e, int argIndex, Type t |
// examples: 'work' for 'work.exec(...)'; '->' for 'tx->exec()'.
e = fc.getQualifier() and
// to find ConnectionHandle/TransationHandle and similar classes which override '->' operator behavior
// and return pointer to a connection/transation object
e.getType().refersTo(t) and
// transation exec and connection prepare variations
(
pqxxTransationClassNames(t.getName(), _) and pqxxTransactionSqlArgument(fc.getTarget().getName(), argIndex)
or
pqxxConnectionClassNames(t.getName(), _) and pqxxConnectionSqlArgument(fc.getTarget().getName(), argIndex)
)
and
result = fc.getArgument(argIndex)
// examples: 'work' for 'work.exec(...)'; '->' for 'tx->exec()'.
e = fc.getQualifier() and
// to find ConnectionHandle/TransationHandle and similar classes which override '->' operator behavior
// and return pointer to a connection/transation object
e.getType().refersTo(t) and
// transation exec and connection prepare variations
(
pqxxTransationClassNames(t.getName(), _) and
pqxxTransactionSqlArgument(fc.getTarget().getName(), argIndex)
or
pqxxConnectionClassNames(t.getName(), _) and
pqxxConnectionSqlArgument(fc.getTarget().getName(), argIndex)
) and
result = fc.getArgument(argIndex)
)
}
predicate pqxxEscapeArgument(string function, int arg) {
arg = 0 and
(
function = "esc"
or
function = "esc_raw"
or
function = "quote"
or
function = "quote_raw"
or
function = "quote_name"
or
function = "quote_table"
or
function = "esc_like"
function = "esc"
or
function = "esc_raw"
or
function = "quote"
or
function = "quote_raw"
or
function = "quote_name"
or
function = "quote_table"
or
function = "esc_like"
)
}
predicate isEscapedPqxxArgument(Expr argExpr) {
exists(FunctionCall fc, Expr e, int argIndex, Type t |
// examples: 'work' for 'work.exec(...)'; '->' for 'tx->exec()'.
e = fc.getQualifier() and
// to find ConnectionHandle/TransationHandle and similar classes which override '->' operator behavior
// and return pointer to a connection/transation object
e.getType().refersTo(t) and
// transation and connection escape functions
(pqxxTransationClassNames(t.getName(), _) or pqxxConnectionClassNames(t.getName(), _))
and
pqxxEscapeArgument(fc.getTarget().getName(), argIndex)
and
// eval is escaped
argExpr = fc.getArgument(argIndex)
// examples: 'work' for 'work.exec(...)'; '->' for 'tx->exec()'.
e = fc.getQualifier() and
// to find ConnectionHandle/TransationHandle and similar classes which override '->' operator behavior
// and return pointer to a connection/transation object
e.getType().refersTo(t) and
// transation and connection escape functions
(pqxxTransationClassNames(t.getName(), _) or pqxxConnectionClassNames(t.getName(), _)) and
pqxxEscapeArgument(fc.getTarget().getName(), argIndex) and
// eval is escaped
argExpr = fc.getArgument(argIndex)
)
}
// class Configuration extends TaintTrackingConfiguration {
// override predicate isSink(Element tainted) {
// tainted = getPqxxSqlArgument()
// }
// override predicate isBarrier(Expr e) {
// super.isBarrier(e) or e.getUnspecifiedType() instanceof IntegralType
// }
// }
// from
// Expr taintedArg, Expr taintSource, PathNode sourceNode, PathNode sinkNode, string taintCause
// where
// taintedWithPath(taintSource, taintedArg, sourceNode, sinkNode) and
// isUserInput(taintSource, taintCause)
// select taintedArg, sourceNode, sinkNode,
// "This argument to a SQL query function is derived from $@", taintSource, "user input (" + taintCause + ")"
class Configuration extends TaintTracking::Configuration {
Configuration() { this = "SqlPqxxTainted" }
override predicate isSource(DataFlow::Node source) {
isUserInput(source.asExpr(), _)
}
override predicate isSource(DataFlow::Node source) { isUserInput(source.asExpr(), _) }
override predicate isSink(DataFlow::Node sink) {
sink.asExpr() = getPqxxSqlArgument()
}
override predicate isSink(DataFlow::Node sink) { sink.asExpr() = getPqxxSqlArgument() }
override predicate isSanitizer(DataFlow::Node node) {
isEscapedPqxxArgument(node.asExpr())
}
override predicate isSanitizer(DataFlow::Node node) { isEscapedPqxxArgument(node.asExpr()) }
}
from
DataFlow::PathNode source, DataFlow::PathNode sink, Configuration config, string taintCause
where
from DataFlow::PathNode source, DataFlow::PathNode sink, Configuration config, string taintCause
where
config.hasFlowPath(source, sink) and
isUserInput(source.getNode().asExpr(), taintCause)
select
sink, source, sink,
"This argument to a SQL query function is derived from $@", source, "user input (" + taintCause + ")"
select sink, source, sink, "This argument to a SQL query function is derived from $@", source,
"user input (" + taintCause + ")"