/** * @name SQLI Vulnerability * @description Using untrusted strings in a sql query allows sql injection attacks. * @kind path-problem * @id cpp/sqlivulnerable * @problem.severity warning */ import cpp // from Call cl // select cl /* * int get_new_id() { * int id = getpid(); * return id; * } */ // Goal: Find connection // 1. reading user data -- source // count = read(STDIN_FILENO, buf, BUFSIZE - 1); // ^^^ // from FunctionCall read, Expr buf // where read.getTarget().getName() = "read" // and buf = read.getArgument(1) // select read, buf predicate isSource(Expr buf) { exists(FunctionCall read | read.getTarget().getName() = "read" and buf = read.getArgument(1) ) } // from Expr buf // where isSource(buf) // select buf class MySource extends Expr { MySource() { exists(FunctionCall read | read.getTarget().getName() = "read" and this = read.getArgument(1) ) } } // from MySource buf // select buf // 2. writing sql -- sink // rc = sqlite3_exec(db, query, NULL, 0, &zErrMsg); // ^^^^^ // from FunctionCall exec, Expr query // where exec.getTarget().getName() = "sqlite3_exec" // and query = exec.getArgument(1) // select exec, query predicate isSink(Expr query) { exists(FunctionCall exec | exec.getTarget().getName() = "sqlite3_exec" and query = exec.getArgument(1) ) } // from Expr query // where isSink(query) // select query class MySink extends Expr { FunctionCall exec; MySink() { exec.getTarget().getName() = "sqlite3_exec" and this = exec.getArgument(1) } FunctionCall getTheCall() { result = exec } } // from MySink query // select query, query.getTheCall() // 3. find call path between 1 and 2 them import semmle.code.cpp.dataflow.new.TaintTracking module SqliFlowConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { exists(MySource ms | ms = source.asDefiningArgument()) } predicate isSink(DataFlow::Node sink) { exists(MySink ms | ms = sink.asIndirectArgument()) } } module MyFlow = TaintTracking::Global; import MyFlow::PathGraph from MyFlow::PathNode source, MyFlow::PathNode sink where MyFlow::flowPath(source, sink) select sink, source, sink, "Possible SQL injection" // from MySource ms // select ms.getASuccessor*()