Rust: Introduce a QuerySink class, common to all query sinks.

This commit is contained in:
Geoffrey White
2025-03-11 11:39:55 +00:00
parent dc7d7f121e
commit 4924a0faf3
7 changed files with 39 additions and 16 deletions

View File

@@ -152,6 +152,29 @@ class ModeledRemoteSource extends RemoteSource::Range {
ModeledRemoteSource() { sourceNode(this, "remote") }
}
/**
* A data flow sink that is used in a query.
*
* Extend this class to refine existing API models. If you want to model new APIs,
* extend `QuerySink::Range` instead.
*/
final class QuerySink = QuerySink::Range;
/**
* Provides a class for modeling new query sinks.
*/
module QuerySink {
/**
* A data flow sink that is used in a query.
*/
abstract class Range extends DataFlow::Node {
/**
* Gets a string that describes the type of this sink (usually the query it applies to).
*/
abstract string getSinkType();
}
}
/**
* A data flow node that constructs a SQL statement (for later execution).
*

View File

@@ -9,7 +9,7 @@
* v
* `sinkNode` predicate | other QL defined sinks, for example using concepts
* v v
* various `Sink` classes for specific data flow configurations
* various `Sink` classes for specific data flow configurations <- extending `QuerySink`
*
* New sinks should be defined using models-as-data, QL extensions of
* `FlowSink::Range`, or concepts. Data flow configurations should use the

View File

@@ -7,6 +7,7 @@ import rust
private import codeql.rust.dataflow.DataFlow
private import codeql.rust.dataflow.internal.DataFlowImpl
private import codeql.rust.security.SensitiveData
private import codeql.rust.Concepts
/**
* Provides default sources, sinks and barriers for detecting cleartext logging
@@ -21,7 +22,9 @@ module CleartextLogging {
/**
* A data flow sink for cleartext logging vulnerabilities.
*/
abstract class Sink extends DataFlow::Node { }
abstract class Sink extends QuerySink::Range {
override string getSinkType() { result = "CleartextLogging" }
}
/**
* A barrier for cleartext logging vulnerabilities.

View File

@@ -23,7 +23,9 @@ module SqlInjection {
/**
* A data flow sink for SQL injection vulnerabilities.
*/
abstract class Sink extends DataFlow::Node { }
abstract class Sink extends QuerySink::Range {
override string getSinkType() { result = "SqlInjection" }
}
/**
* A barrier for SQL injection vulnerabilities.

View File

@@ -10,8 +10,9 @@
import rust
import codeql.rust.dataflow.DataFlow
import codeql.rust.Concepts
import Stats
from string kind, int num
where num = strictcount(DataFlow::Node n | getAQuerySinkKind(n) = kind)
where num = strictcount(QuerySink s | s.getSinkType() = kind)
select kind, num

View File

@@ -11,7 +11,8 @@
import rust
import codeql.rust.dataflow.DataFlow
import codeql.rust.Concepts
import Stats
from DataFlow::Node n
select n, "Sink for " + strictconcat(getAQuerySinkKind(n), ", ") + "."
from QuerySink s
select s, "Sink for " + concat(s.getSinkType(), ", ") + "."

View File

@@ -9,6 +9,8 @@ private import codeql.rust.dataflow.internal.TaintTrackingImpl
private import codeql.rust.internal.AstConsistency as AstConsistency
private import codeql.rust.controlflow.internal.CfgConsistency as CfgConsistency
private import codeql.rust.dataflow.internal.DataFlowConsistency as DataFlowConsistency
private import codeql.rust.Concepts
// import all query extensions files, so that all extensions of `QuerySink` are found
private import codeql.rust.security.SqlInjectionExtensions
private import codeql.rust.security.CleartextLoggingExtensions
@@ -55,16 +57,7 @@ int getTaintEdgesCount() {
)
}
/**
* Gets a kind of query for which `n` is a sink (if any).
*/
string getAQuerySinkKind(DataFlow::Node n) {
n instanceof SqlInjection::Sink and result = "SqlInjection"
or
n instanceof CleartextLogging::Sink and result = "CleartextLogging"
}
/**
* Gets a count of the total number of query sinks in the database.
*/
int getQuerySinksCount() { result = count(DataFlow::Node n | exists(getAQuerySinkKind(n))) }
int getQuerySinksCount() { result = count(QuerySink s) }