Skip to content
Draft
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,19 @@ module SourceSinkInterpretationInput implements
)
}

predicate barrierElement(
Element n, string output, string kind, Public::Provenance provenance, string model
) {
none()
}

predicate barrierGuardElement(
Element n, string input, Public::AcceptingValue acceptingvalue, string kind,
Public::Provenance provenance, string model
) {
none()
}

private newtype TInterpretNode =
TElement_(Element n) or
TNode_(Node n)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,19 @@ module SourceSinkInterpretationInput implements
)
}

predicate barrierElement(
Element n, string output, string kind, Public::Provenance provenance, string model
) {
none()
}

predicate barrierGuardElement(
Element n, string input, Public::AcceptingValue acceptingvalue, string kind,
Public::Provenance provenance, string model
) {
none()
}

class SourceOrSinkElement = Element;

private newtype TInterpretNode =
Expand Down
13 changes: 13 additions & 0 deletions go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,19 @@ module SourceSinkInterpretationInput implements
)
}

predicate barrierElement(
Element n, string output, string kind, Public::Provenance provenance, string model
) {
none()
}

predicate barrierGuardElement(
Element n, string input, Public::AcceptingValue acceptingvalue, string kind,
Public::Provenance provenance, string model
) {
none()
}

// Note that due to embedding, which is currently implemented via some
// Methods having multiple qualified names, a given Method is liable to have
// more than one SourceOrSinkElement, one for each of the names it claims.
Expand Down
8 changes: 8 additions & 0 deletions java/ql/lib/ext/empty.model.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@ extensions:
pack: codeql/java-all
extensible: summaryModel
data: []
- addsTo:
pack: codeql/java-all
extensible: barrierModel
data: []
- addsTo:
pack: codeql/java-all
extensible: barrierGuardModel
data: []
- addsTo:
pack: codeql/java-all
extensible: neutralModel
Expand Down
5 changes: 5 additions & 0 deletions java/ql/lib/ext/java.io.model.yml
Original file line number Diff line number Diff line change
Expand Up @@ -162,3 +162,8 @@ extensions:
extensible: sourceModel
data:
- ["java.io", "FileInputStream", True, "FileInputStream", "", "", "Argument[this]", "file", "manual"]
- addsTo:
pack: codeql/java-all
extensible: barrierModel
data:
- ["java.io", "File", True, "getName", "()", "", "ReturnValue", "path-injection", "manual"]
38 changes: 37 additions & 1 deletion java/ql/lib/ext/org.owasp.esapi.model.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,42 @@
extensions:
- addsTo:
pack: codeql/java-all
extensible: barrierGuardModel
data:
- ["org.owasp.esapi", "Validator", true, "isValidCreditCard", "", "", "Argument[1]", "true", "trust-boundary-violation", "manual"]
- ["org.owasp.esapi", "Validator", true, "isValidDate", "", "", "Argument[1]", "true", "trust-boundary-violation", "manual"]
- ["org.owasp.esapi", "Validator", true, "isValidDirectoryPath", "", "", "Argument[1]", "true", "trust-boundary-violation", "manual"]
- ["org.owasp.esapi", "Validator", true, "isValidDouble", "", "", "Argument[1]", "true", "trust-boundary-violation", "manual"]
- ["org.owasp.esapi", "Validator", true, "isValidFileContent", "", "", "Argument[1]", "true", "trust-boundary-violation", "manual"]
- ["org.owasp.esapi", "Validator", true, "isValidFileName", "", "", "Argument[1]", "true", "trust-boundary-violation", "manual"]
- ["org.owasp.esapi", "Validator", true, "isValidInput", "", "", "Argument[1]", "true", "trust-boundary-violation", "manual"]
- ["org.owasp.esapi", "Validator", true, "isValidInteger", "", "", "Argument[1]", "true", "trust-boundary-violation", "manual"]
- ["org.owasp.esapi", "Validator", true, "isValidListItem", "", "", "Argument[1]", "true", "trust-boundary-violation", "manual"]
- ["org.owasp.esapi", "Validator", true, "isValidNumber", "", "", "Argument[1]", "true", "trust-boundary-violation", "manual"]
- ["org.owasp.esapi", "Validator", true, "isValidPrintable", "", "", "Argument[1]", "true", "trust-boundary-violation", "manual"]
- ["org.owasp.esapi", "Validator", true, "isValidRedirectLocation", "", "", "Argument[1]", "true", "trust-boundary-violation", "manual"]
- ["org.owasp.esapi", "Validator", true, "isValidSafeHTML", "", "", "Argument[1]", "true", "trust-boundary-violation", "manual"]
- ["org.owasp.esapi", "Validator", true, "isValidURI", "", "", "Argument[1]", "true", "trust-boundary-violation", "manual"]
- addsTo:
pack: codeql/java-all
extensible: barrierModel
data:
- ["org.owasp.esapi", "Validator", true, "getValidCreditCard", "", "", "ReturnValue", "trust-boundary-violation", "manual"]
- ["org.owasp.esapi", "Validator", true, "getValidDate", "", "", "ReturnValue", "trust-boundary-violation", "manual"]
- ["org.owasp.esapi", "Validator", true, "getValidDirectoryPath", "", "", "ReturnValue", "trust-boundary-violation", "manual"]
- ["org.owasp.esapi", "Validator", true, "getValidDouble", "", "", "ReturnValue", "trust-boundary-violation", "manual"]
- ["org.owasp.esapi", "Validator", true, "getValidFileContent", "", "", "ReturnValue", "trust-boundary-violation", "manual"]
- ["org.owasp.esapi", "Validator", true, "getValidFileName", "", "", "ReturnValue", "trust-boundary-violation", "manual"]
- ["org.owasp.esapi", "Validator", true, "getValidInput", "", "", "ReturnValue", "trust-boundary-violation", "manual"]
- ["org.owasp.esapi", "Validator", true, "getValidInteger", "", "", "ReturnValue", "trust-boundary-violation", "manual"]
- ["org.owasp.esapi", "Validator", true, "getValidListItem", "", "", "ReturnValue", "trust-boundary-violation", "manual"]
- ["org.owasp.esapi", "Validator", true, "getValidNumber", "", "", "ReturnValue", "trust-boundary-violation", "manual"]
- ["org.owasp.esapi", "Validator", true, "getValidPrintable", "", "", "ReturnValue", "trust-boundary-violation", "manual"]
- ["org.owasp.esapi", "Validator", true, "getValidRedirectLocation", "", "", "ReturnValue", "trust-boundary-violation", "manual"]
- ["org.owasp.esapi", "Validator", true, "getValidSafeHTML", "", "", "ReturnValue", "trust-boundary-violation", "manual"]
- ["org.owasp.esapi", "Validator", true, "getValidURI", "", "", "ReturnValue", "trust-boundary-violation", "manual"]
- addsTo:
pack: codeql/java-all
extensible: summaryModel
data:
- ["org.owasp.esapi", "Encoder", true, "encodeForHTML", "(String)", "", "Argument[0]", "ReturnValue", "taint", "manual"]
- ["org.owasp.esapi", "Encoder", true, "encodeForHTML", "(String)", "", "Argument[0]", "ReturnValue", "taint", "manual"]
114 changes: 112 additions & 2 deletions java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ module;

import java
private import semmle.code.java.dataflow.DataFlow::DataFlow
private import semmle.code.java.controlflow.Guards
private import FlowSummary as FlowSummary
private import internal.DataFlowPrivate
private import internal.FlowSummaryImpl
Expand Down Expand Up @@ -174,6 +175,24 @@ predicate sinkModel(
)
}

/** Holds if a barrier model exists for the given parameters. */
predicate barrierModel(
string package, string type, boolean subtypes, string name, string signature, string ext,
string output, string kind, string provenance, QlBuiltins::ExtensionId madId
) {
Extensions::barrierModel(package, type, subtypes, name, signature, ext, output, kind, provenance,
madId)
}

/** Holds if a barrier guard model exists for the given parameters. */
predicate barrierGuardModel(
string package, string type, boolean subtypes, string name, string signature, string ext,
string input, string acceptingvalue, string kind, string provenance, QlBuiltins::ExtensionId madId
) {
Extensions::barrierGuardModel(package, type, subtypes, name, signature, ext, input,
acceptingvalue, kind, provenance, madId)
}

/** Holds if a summary model exists for the given parameters. */
predicate summaryModel(
string package, string type, boolean subtypes, string name, string signature, string ext,
Expand Down Expand Up @@ -234,6 +253,7 @@ predicate interpretModelForTest(QlBuiltins::ExtensionId madId, string model) {
"Summary: " + package + "; " + type + "; " + subtypes + "; " + name + "; " + signature + "; " +
ext + "; " + input + "; " + output + "; " + kind + "; " + provenance
)
//TODO: possibly barrier models?
}

/** Holds if a neutral model exists for the given parameters. */
Expand Down Expand Up @@ -292,6 +312,7 @@ predicate modelCoverage(string package, int pkgs, string kind, string part, int
summaryModel(subpkg, type, subtypes, name, signature, ext, input, output, kind, provenance,
_)
)
// TODO: possibly barrier models?
)
}

Expand All @@ -303,7 +324,9 @@ module ModelValidation {
summaryModel(_, _, _, _, _, _, path, _, _, _, _) or
summaryModel(_, _, _, _, _, _, _, path, _, _, _) or
sinkModel(_, _, _, _, _, _, path, _, _, _) or
sourceModel(_, _, _, _, _, _, path, _, _, _)
sourceModel(_, _, _, _, _, _, path, _, _, _) or
barrierModel(_, _, _, _, _, _, path, _, _, _) or
barrierGuardModel(_, _, _, _, _, _, path, _, _, _, _)
}

private module MkAccessPath = AccessPathSyntax::AccessPath<getRelevantAccessPath/1>;
Expand All @@ -316,6 +339,8 @@ module ModelValidation {
exists(string pred, AccessPath input, AccessPathToken part |
sinkModel(_, _, _, _, _, _, input, _, _, _) and pred = "sink"
or
barrierGuardModel(_, _, _, _, _, _, input, _, _, _, _) and pred = "barrier guard"
or
summaryModel(_, _, _, _, _, _, input, _, _, _, _) and pred = "summary"
|
(
Expand All @@ -338,6 +363,8 @@ module ModelValidation {
exists(string pred, AccessPath output, AccessPathToken part |
sourceModel(_, _, _, _, _, _, output, _, _, _) and pred = "source"
or
barrierModel(_, _, _, _, _, _, output, _, _, _) and pred = "barrier"
or
summaryModel(_, _, _, _, _, _, _, output, _, _, _) and pred = "summary"
|
(
Expand All @@ -355,7 +382,13 @@ module ModelValidation {
private module KindValConfig implements SharedModelVal::KindValidationConfigSig {
predicate summaryKind(string kind) { summaryModel(_, _, _, _, _, _, _, _, kind, _, _) }

predicate sinkKind(string kind) { sinkModel(_, _, _, _, _, _, _, kind, _, _) }
predicate sinkKind(string kind) {
sinkModel(_, _, _, _, _, _, _, kind, _, _)
or
barrierModel(_, _, _, _, _, _, _, kind, _, _)
or
barrierGuardModel(_, _, _, _, _, _, _, _, kind, _, _)
}

predicate sourceKind(string kind) { sourceModel(_, _, _, _, _, _, _, kind, _, _) }

Expand All @@ -373,6 +406,11 @@ module ModelValidation {
or
sinkModel(package, type, _, name, signature, ext, _, _, provenance, _) and pred = "sink"
or
barrierModel(package, type, _, name, signature, ext, _, _, provenance, _) and pred = "barrier"
or
barrierGuardModel(package, type, _, name, signature, ext, _, _, _, provenance, _) and
pred = "barrier guard"
or
summaryModel(package, type, _, name, signature, ext, _, _, _, provenance, _) and
pred = "summary"
or
Expand All @@ -398,6 +436,14 @@ module ModelValidation {
invalidProvenance(provenance) and
result = "Unrecognized provenance description \"" + provenance + "\" in " + pred + " model."
)
or
exists(string acceptingvalue |
barrierGuardModel(_, _, _, _, _, _, _, acceptingvalue, _, _, _) and
invalidAcceptingValue(acceptingvalue) and
result =
"Unrecognized accepting value description \"" + acceptingvalue +
"\" in barrier guard model."
)
}

/** Holds if some row in a MaD flow model appears to contain typos. */
Expand All @@ -418,6 +464,10 @@ private predicate elementSpec(
or
sinkModel(package, type, subtypes, name, signature, ext, _, _, _, _)
or
barrierModel(package, type, subtypes, name, signature, ext, _, _, _, _)
or
barrierGuardModel(package, type, subtypes, name, signature, ext, _, _, _, _, _)
or
summaryModel(package, type, subtypes, name, signature, ext, _, _, _, _, _)
or
neutralModel(package, type, name, signature, _, _) and ext = "" and subtypes = true
Expand Down Expand Up @@ -578,6 +628,60 @@ private module Cached {
isSinkNode(n, kind, model) and n.asNode() = node
)
}

private newtype TKindModelPair =
TMkPair(string kind, string model) { isBarrierGuardNode(_, _, kind, model) }

private boolean convertAcceptingValue(AcceptingValue av) {
av.isTrue() and result = true
or
av.isFalse() and result = false
}

// private GuardValue convertAcceptingValue(AcceptingValue av) {
// av.isTrue() and result.asBooleanValue() = true
// or
// av.isFalse() and result.asBooleanValue() = false
// or
// av.isNoException() and result.getDualValue().isThrowsException()
// or
// av.isZero() and result.asIntValue() = 0
// or
// av.isNotZero() and result.getDualValue().asIntValue() = 0
// or
// av.isNull() and result.isNullValue()
// or
// av.isNotNull() and result.isNonNullValue()
// }
// private predicate barrierGuardChecks(Guard g, Expr e, GuardValue gv, TKindModelPair kmp) {
private predicate barrierGuardChecks(Guard g, Expr e, boolean branch, TKindModelPair kmp) {
exists(
SourceSinkInterpretationInput::InterpretNode n, AcceptingValue acceptingvalue, string kind,
string model
|
isBarrierGuardNode(n, acceptingvalue, kind, model) and
n.asNode().asExpr() = e and
kmp = TMkPair(kind, model) and
// gv = convertAcceptingValue(acceptingvalue)
branch = convertAcceptingValue(acceptingvalue)
|
g.(Call).getAnArgument() = e or g.(MethodCall).getQualifier() = e
)
}

/**
* Holds if `node` is specified as a barrier with the given kind in a MaD flow
* model.
*/
cached
predicate barrierNode(Node node, string kind, string model) {
exists(SourceSinkInterpretationInput::InterpretNode n |
isBarrierNode(n, kind, model) and n.asNode() = node
)
or
ParameterizedBarrierGuard<TKindModelPair, barrierGuardChecks/4>::getABarrierNode(TMkPair(kind,
model)) = node
}
}

import Cached
Expand All @@ -594,6 +698,12 @@ predicate sourceNode(Node node, string kind) { sourceNode(node, kind, _) }
*/
predicate sinkNode(Node node, string kind) { sinkNode(node, kind, _) }

/**
* Holds if `node` is specified as a barrier with the given kind in a MaD flow
* model.
*/
predicate barrierNode(Node node, string kind) { barrierNode(node, kind, _) }

// adapter class for converting Mad summaries to `SummarizedCallable`s
private class SummarizedCallableAdapter extends SummarizedCallable {
SummarizedCallableAdapter() { summaryElement(this, _, _, _, _, _, _) }
Expand Down
29 changes: 29 additions & 0 deletions java/ql/lib/semmle/code/java/dataflow/internal/DataFlowUtil.qll
Original file line number Diff line number Diff line change
Expand Up @@ -396,3 +396,32 @@
SsaImpl::DataFlowIntegration::BarrierGuard<guardChecks/3>::getABarrierNode()
}
}

bindingset[this]
signature class ParamSig;

module WithParam<ParamSig P> {

Check warning on line 403 in java/ql/lib/semmle/code/java/dataflow/internal/DataFlowUtil.qll

View workflow job for this annotation

GitHub Actions / qldoc

Missing QLdoc for module DataFlowUtil::WithParam
/**
* Holds if the guard `g` validates the expression `e` upon evaluating to `gv`.
*
* The expression `e` is expected to be a syntactic part of the guard `g`.
* For example, the guard `g` might be a call `isSafe(x)` and the expression `e`
* the argument `x`.
*/
// signature predicate guardChecksSig(Guard g, Expr e, GuardValue gv, P param);
signature predicate guardChecksSig(Guard g, Expr e, boolean branch, P param);
}

/**
* Provides a set of barrier nodes for a guard that validates an expression.
*
* This is expected to be used in `isBarrier`/`isSanitizer` definitions
* in data flow and taint tracking.
*/
module ParameterizedBarrierGuard<ParamSig P, WithParam<P>::guardChecksSig/4 guardChecks> {
/** Gets a node that is safely guarded by the given guard check. */
Node getABarrierNode(P param) {
SsaFlow::asNode(result) =
SsaImpl::DataFlowIntegration::ParameterizedBarrierGuard<P, guardChecks/4>::getABarrierNode(param)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,22 @@ extensible predicate sinkModel(
string input, string kind, string provenance, QlBuiltins::ExtensionId madId
);

/**
* Holds if a barrier model exists for the given parameters.
*/
extensible predicate barrierModel(
string package, string type, boolean subtypes, string name, string signature, string ext,
string output, string kind, string provenance, QlBuiltins::ExtensionId madId
);

/**
* Holds if a barrier guard model exists for the given parameters.
*/
extensible predicate barrierGuardModel(
string package, string type, boolean subtypes, string name, string signature, string ext,
string input, string acceptingvalue, string kind, string provenance, QlBuiltins::ExtensionId madId
);

/**
* Holds if a summary model exists for the given parameters.
*/
Expand Down
Loading
Loading