Develop the query bottom-up
-
Identify the source part of the
System.console().readLine();
expression, the
bufargument. Start from afrom..where..select, then convert to a predicate. -
Identify the sink part of the
conn.createStatement().executeUpdate(query);
expression, the
queryargument. Again start fromfrom..where..select, then convert to a predicate. -
Fill in the taintflow configuration boilerplate XX: update for new module approach; See ~/local/codeql-workshop-dataflow-c/exercises/Exercise16.ql ~/local/codeql-workshop-dataflow-c/exercises/Exercise16.ql::module InputTypesToTypeValidation = DataFlow::Make<InputTypesToTypeValidationConfig>; or ~/local/codeql-workshop-dataflow-c/solutions/Exercise16.ql::module InputTypesToTypeValidation = DataFlow::Make<InputTypesToTypeValidationConfig>;
class SqliFlowConfig extends TaintTracking::Configuration { SqliFlowConfig() { this = "SqliFlow" } override predicate isSource(DataFlow::Node node) { none() } override predicate isSink(DataFlow::Node node) { none() } }
The final query (without isAdditionalTaintStep) is
/**
,* @name SQLI Vulnerability
,* @description Using untrusted strings in a sql query allows sql injection attacks.
,* @kind path-problem
,* @id java/SQLIVulnerable
,* @problem.severity warning
,*/
import java
import semmle.code.java.dataflow.TaintTracking
import DataFlow::PathGraph
class SqliFlowConfig extends TaintTracking::Configuration {
SqliFlowConfig() { this = "SqliFlow" }
override predicate isSource(DataFlow::Node source) {
// System.console().readLine();
exists(Call read |
read.getCallee().getName() = "readLine" and
read = source.asExpr()
)
}
override predicate isSink(DataFlow::Node sink) {
// conn.createStatement().executeUpdate(query);
exists(Call exec |
exec.getCallee().getName() = "executeUpdate" and
exec.getArgument(0) = sink.asExpr()
)
}
}
from SqliFlowConfig conf, DataFlow::PathNode source, DataFlow::PathNode sink
where conf.hasFlowPath(source, sink)
select sink, source, sink, "Possible SQL injection"
Optional: sarif file review of the results
Query results are available in several output formats using the cli. The following produces the sarif format, a json-based result description.
# The setup information from before
export PATH=$HOME/local/vmsync/codeql250:"$PATH"
SRCDIR=$HOME/local/codeql-training-material.java-sqli/java/codeql-dataflow-sql-injection
DB=$SRCDIR/java-sqli-$(cd $SRCDIR && git rev-parse --short HEAD)
# Check paths
echo $DB
echo $SRCDIR
# To see the help
codeql database analyze -h
# Run a query
codeql database analyze \
-v \
--ram=14000 \
-j12 \
--rerun \
--search-path ~/local/vmsync/ql \
--format=sarif-latest \
--output java-sqli.sarif \
-- \
$DB \
$SRCDIR/SqlInjection.ql
# Examine the file in an editor
edit java-sqli.sarif
An example of using the sarif data is in the the jq script ./sarif-summary.jq. When run against the sarif input via
jq --raw-output --join-output -f sarif-summary.jq < java-sqli.sarif > java-sqli.txt
it produces output in a form close to that of compiler error messages:
query-id: message line
Path
...
Path
...