class OneTwoThree extends int { OneTwoThree() { // characteristic predicate this =1or this =2or this =3 }
string getAString() { // member predicate result= "One, two or three: " + this.toString() }
predicate isEven() { // member predicate this =2 } }
characteristic predicate, defined inside the body of class. They are logical perporties that use the variable this to restrict the possible values in the class.
1 2 3 4 5 6 7 8 9 10 11 12
import cpp class NetworkByteSwap extends Expr { NetworkByteSwap () { exists( MacroInvocation mi | this = mi.getExpr() and mi.getMacro().getName() in ["ntohs", "ntohl", "ntohll"] ) } }
from NetworkByteSwap n select n, "Network byte swap"
NetworkByteSwap represents all expressions that ntoh* macros expand to.
step-10 final step
Write a query to track the flow of tainted data from network controlled interges to the memcpy length argument. As a result, we will find 9 real vulnerabilities.
CodeQL’s taint tracking library can help us to achieve our goal.
class NetworkByteSwap extends Expr { NetworkByteSwap () { exists( MacroInvocation mi | this = mi.getExpr() and mi.getMacro().getName() in ["ntohs", "ntohl", "ntohll"] ) } }
class Config extends TaintTracking::Configuration { Config() { this = "NetworkToMemFuncLength" }
override predicate isSink(DataFlow::Node sink) { // sink should be the size argument of calls to memcpy (exists(FunctionCall call| sink.asExpr() = call.getArgument(2) and call.getTarget().getName() = "memcpy")) } }
from Config cfg, DataFlow::PathNode source, DataFlow::PathNode sink where cfg.hasFlowPath(source, sink) select sink, source, sink, "Network byte swap flows to memcpy"
isSource define a predicate to select collection of source data. In our goal, we can consider ntoh* macos as taint source.
isSink define a predicate to select collection of vulnerable target.We can consider
hasFlowPath holds true when tainted data from a given source flows to a sink.