Java: Use an IPA type instead of a string

While the string representation is useful for quickly modifying queries, it's
a bit clunky when the data needs to be further parsed. Instead, the two queries
now select all of the columns of the sinkmodel separately (which makes it easy
to pull them out of the relevant output later on).
This commit is contained in:
Taus
2023-07-03 23:17:55 +02:00
parent 6f24d939f6
commit b7e4bd290d
3 changed files with 93 additions and 24 deletions

View File

@@ -11,6 +11,72 @@ private import semmle.code.java.security.TaintedPathQuery
private import semmle.code.java.security.SqlInjectionQuery
private import AutomodelJavaUtil
private newtype TSinkModel =
MkSinkModel(
string package, string type, boolean subtypes, string name, string signature, string input,
string ext, string kind, string provenance
) {
ExternalFlow::sinkModel(package, type, subtypes, name, signature, ext, input, kind, provenance)
}
class SinkModel extends TSinkModel {
string package;
string type;
boolean subtypes;
string name;
string signature;
string input;
string ext;
string kind;
string provenance;
SinkModel() {
this = MkSinkModel(package, type, subtypes, name, signature, input, ext, kind, provenance)
}
/** Gets the package for this sink model. */
string getPackage() { result = package }
/** Gets the type for this sink model. */
string getType() { result = type }
/** Gets whether this sink model considers subtypes. */
boolean getSubtypes() { result = subtypes }
/** Gets the name for this sink model. */
string getName() { result = name }
/** Gets the signature for this sink model. */
string getSignature() { result = signature }
/** Gets the input for this sink model. */
string getInput() { result = input }
/** Gets the extension for this sink model. */
string getExt() { result = ext }
/** Gets the kind for this sink model. */
string getKind() { result = kind }
/** Gets the provenance for this sink model. */
string getProvenance() { result = provenance }
/** Gets a string representation of this sink model. */
string toString() {
result =
"SinkModel(" + package + ", " + type + ", " + subtypes + ", " + name + ", " + signature + ", "
+ input + ", " + ext + ", " + kind + ", " + provenance + ")"
}
/** Gets a string representation of this sink model as it would appear in a Models-as-Data file. */
string getRepr() {
result =
"\"" + package + "\", \"" + type + "\", " + pyBool(subtypes) + ", \"" + name + "\", \"" +
signature + "\", \"" + ext + "\", \"" + input + "\", \"" + kind + "\", \"" + provenance +
"\""
}
}
/** An expression that may correspond to a sink model. */
private class PotentialSinkModelExpr extends Expr {
/**
@@ -36,6 +102,12 @@ private class PotentialSinkModelExpr extends Expr {
signature = ExternalFlow::paramsString(callable)
)
}
/** Gets a sink model that corresponds to this expression. */
SinkModel getSinkModel() {
this.hasSignature(result.getPackage(), result.getType(), result.getSubtypes(), result.getName(),
result.getSignature(), result.getInput())
}
}
private string pyBool(boolean b) {
@@ -46,21 +118,12 @@ private string pyBool(boolean b) {
/**
* Gets a string representation of the existing sink model at the expression `e`, in the format in
* which it would appear in a Models-as-Data file.
* which it would appear in a Models-as-Data file. Also restricts the provenance of the sink model
* to be `ai-generated`.
*/
string getSinkModelRepr(PotentialSinkModelExpr e) {
exists(
string package, string type, boolean subtypes, string name, string signature, string input,
string ext, string kind, string provenance
|
e.hasSignature(package, type, subtypes, name, signature, input) and
ExternalFlow::sinkModel(package, type, subtypes, name, signature, ext, input, kind, provenance) and
provenance = "ai-generated" and
result =
"\"" + package + "\", \"" + type + "\", " + pyBool(subtypes) + ", \"" + name + "\", \"" +
signature + "\", \"" + ext + "\", \"" + input + "\", \"" + kind + "\", \"" + provenance +
"\""
)
result = e.getSinkModel().getRepr() and
e.getSinkModel().getProvenance() = "ai-generated"
}
/**
@@ -78,17 +141,17 @@ string getSinkModelQueryRepr(PotentialSinkModelExpr e) {
private module SinkTallier<DataFlow::ConfigSig Config> {
module ConfigFlow = TaintTracking::Global<Config>;
predicate getSinkModelCount(int c, string s) {
s = getSinkModelRepr(any(ConfigFlow::PathNode sink).getNode().asExpr()) and
predicate getSinkModelCount(int c, SinkModel s) {
s = any(ConfigFlow::PathNode sink).getNode().asExpr().(PotentialSinkModelExpr).getSinkModel() and
c =
strictcount(ConfigFlow::PathNode sink |
ConfigFlow::flowPath(_, sink) and
s = getSinkModelRepr(sink.getNode().asExpr())
s = sink.getNode().asExpr().(PotentialSinkModelExpr).getSinkModel()
)
}
}
predicate sinkModelTallyPerQuery(string queryName, int alertCount, string sinkModel) {
predicate sinkModelTallyPerQuery(string queryName, int alertCount, SinkModel sinkModel) {
queryName = "java/request-forgery" and
SinkTallier<RequestForgeryConfig>::getSinkModelCount(alertCount, sinkModel)
or
@@ -115,7 +178,7 @@ predicate sinkModelTallyPerQuery(string queryName, int alertCount, string sinkMo
SinkTallier<QueryInjectionFlowConfig>::getSinkModelCount(alertCount, sinkModel)
}
predicate sinkModelTally(int alertCount, string sinkModel) {
predicate sinkModelTally(int alertCount, SinkModel sinkModel) {
sinkModelTallyPerQuery(_, _, sinkModel) and
alertCount = sum(int c | sinkModelTallyPerQuery(_, c, sinkModel))
}

View File

@@ -9,6 +9,8 @@
private import java
private import AutomodelAlertSinkUtil
from int alertCount, string sinkModel
where sinkModelTally(alertCount, sinkModel)
select alertCount, sinkModel
from int alertCount, SinkModel s
where sinkModelTally(alertCount, s) and s.getProvenance() = "ai-generated"
select alertCount, s.getPackage() as package, s.getType() as type, s.getSubtypes() as subtypes,
s.getName() as name, s.getSignature() as signature, s.getInput() as input, s.getExt() as ext,
s.getKind() as kind, s.getProvenance() as provenance

View File

@@ -9,6 +9,10 @@
private import java
private import AutomodelAlertSinkUtil
from string queryId, int alertCount, string sinkModel
where sinkModelTallyPerQuery(queryId, alertCount, sinkModel)
select queryId, alertCount, sinkModel
from string queryId, int alertCount, SinkModel s
where
sinkModelTallyPerQuery(queryId, alertCount, s) and
s.getProvenance() = "ai-generated"
select queryId, alertCount, s.getPackage() as package, s.getType() as type,
s.getSubtypes() as subtypes, s.getName() as name, s.getSignature() as signature,
s.getInput() as input, s.getExt() as ext, s.getKind() as kind, s.getProvenance() as provenance