Table of Contents

1. Develop the query bottom-up

  1. Identify the source part of the

    System.console().readLine();
    

    expression, the buf argument. Start from a from..where..select, then convert to a predicate.

  2. Identify the sink part of the

    conn.createStatement().executeUpdate(query);
    

    expression, the query argument. Again start from from..where..select, then convert to a predicate.

  3. Fill in the taintflow configuration boilerplate

    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"

2. 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
       ...

Author: Michael Hohn

Created: 2023-08-16 Wed 10:26

Validate