Я хочу сделать TaintTracking с функциями, которые портят их аргументы с помощью userinput. Пример:
fgets(buf, sizeof(buf), stdin); // buf is tainted
[...]
n = strlen(buf); // tainted argument to strlen
[...]
memcpy(somewhere, buf, n) // tainted call to memcpy
Семмл должен иметь возможность определить это с помощью запроса, подобного следующему (просто с fgets-> strlen в качестве примера). Я заимствую код из SecurityOptions:
import cpp
import semmle.code.cpp.dataflow.TaintTracking
class IsTaintedArg extends string {
IsTaintedArg() { this = "IsTaintedArg" }
predicate userInputArgument(FunctionCall functionCall, int arg) {
exists(string fname |
functionCall.getTarget().hasGlobalName(fname) and
exists(functionCall.getArgument(arg)) and (fname = "fgets" and arg = 0) // argument 0 of fgets is tainted
)
}
predicate isUserInput(Expr expr, string cause) {
exists(FunctionCall fc, int i |
this.userInputArgument(fc, i) and
expr = fc.getArgument(i) and
cause = fc.getTarget().getName()
)
}
}
class TaintedFormatConfig extends TaintTracking::Configuration {
TaintedFormatConfig() { this = "TaintedFormatConfig" }
override predicate isSource(DataFlow::Node source) {
exists (IsTaintedArg opts |
opts.isUserInput(source.asExpr(), _)
)
}
override predicate isSink(DataFlow::Node sink) {
exists (FunctionCall fc | sink.asExpr() = fc.getArgument(0) and fc.getTarget().hasName("strlen")) // give me all calls that land in strlen's first argument
}
}
from TaintedFormatConfig cfg, DataFlow::Node source, DataFlow::Node sink
where cfg.hasFlow(source, sink)
select sink, source
И все же не похоже, что он работает.
Когда я просто запрашиваю cfg.isSource()
или cfg.isSink()
, как источник, так и приемникраспознан. Но hasFlow()
по-прежнему ничего не возвращает - хотя путь определенно должен существовать.
Я использую libssh2 для проверки своих результатов, пример потока существует здесь .
Мой запрос для проверки: здесь .
Кто-нибудь знает, что я могу сделать неправильно в запросевыше