|
|
|
|
@@ -65,7 +65,7 @@ abstract class EndpointCharacteristic extends string {
|
|
|
|
|
* Holds for endpoints that have this characteristic. This predicate contains the logic that applies characteristics
|
|
|
|
|
* to the appropriate set of dataflow nodes.
|
|
|
|
|
*/
|
|
|
|
|
abstract predicate getEndpoints(DataFlow::Node n);
|
|
|
|
|
abstract predicate appliesToEndpoint(DataFlow::Node n);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* This predicate describes what the characteristic tells us about an endpoint.
|
|
|
|
|
@@ -81,7 +81,7 @@ abstract class EndpointCharacteristic extends string {
|
|
|
|
|
* indicator of whether or not the endpoint belongs to the class. A confidence of 1 means that all endpoints with
|
|
|
|
|
* this characteristic definitively do/don't belong to the class.
|
|
|
|
|
*/
|
|
|
|
|
abstract predicate getImplications(
|
|
|
|
|
abstract predicate hasImplications(
|
|
|
|
|
EndpointType endpointClass, boolean isPositiveIndicator, float confidence
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
@@ -213,9 +213,9 @@ DataFlow::CallNode getALikelyExternalLibraryCall() { result = getACallWithoutCal
|
|
|
|
|
private class DomBasedXssSinkCharacteristic extends EndpointCharacteristic {
|
|
|
|
|
DomBasedXssSinkCharacteristic() { this = "DomBasedXssSink" }
|
|
|
|
|
|
|
|
|
|
override predicate getEndpoints(DataFlow::Node n) { n instanceof DomBasedXss::Sink }
|
|
|
|
|
override predicate appliesToEndpoint(DataFlow::Node n) { n instanceof DomBasedXss::Sink }
|
|
|
|
|
|
|
|
|
|
override predicate getImplications(
|
|
|
|
|
override predicate hasImplications(
|
|
|
|
|
EndpointType endpointClass, boolean isPositiveIndicator, float confidence
|
|
|
|
|
) {
|
|
|
|
|
endpointClass instanceof XssSinkType and
|
|
|
|
|
@@ -231,9 +231,9 @@ private class DomBasedXssSinkCharacteristic extends EndpointCharacteristic {
|
|
|
|
|
private class TaintedPathSinkCharacteristic extends EndpointCharacteristic {
|
|
|
|
|
TaintedPathSinkCharacteristic() { this = "TaintedPathSink" }
|
|
|
|
|
|
|
|
|
|
override predicate getEndpoints(DataFlow::Node n) { n instanceof TaintedPath::Sink }
|
|
|
|
|
override predicate appliesToEndpoint(DataFlow::Node n) { n instanceof TaintedPath::Sink }
|
|
|
|
|
|
|
|
|
|
override predicate getImplications(
|
|
|
|
|
override predicate hasImplications(
|
|
|
|
|
EndpointType endpointClass, boolean isPositiveIndicator, float confidence
|
|
|
|
|
) {
|
|
|
|
|
endpointClass instanceof TaintedPathSinkType and
|
|
|
|
|
@@ -249,9 +249,9 @@ private class TaintedPathSinkCharacteristic extends EndpointCharacteristic {
|
|
|
|
|
private class SqlInjectionSinkCharacteristic extends EndpointCharacteristic {
|
|
|
|
|
SqlInjectionSinkCharacteristic() { this = "SqlInjectionSink" }
|
|
|
|
|
|
|
|
|
|
override predicate getEndpoints(DataFlow::Node n) { n instanceof SqlInjection::Sink }
|
|
|
|
|
override predicate appliesToEndpoint(DataFlow::Node n) { n instanceof SqlInjection::Sink }
|
|
|
|
|
|
|
|
|
|
override predicate getImplications(
|
|
|
|
|
override predicate hasImplications(
|
|
|
|
|
EndpointType endpointClass, boolean isPositiveIndicator, float confidence
|
|
|
|
|
) {
|
|
|
|
|
endpointClass instanceof SqlInjectionSinkType and
|
|
|
|
|
@@ -267,9 +267,9 @@ private class SqlInjectionSinkCharacteristic extends EndpointCharacteristic {
|
|
|
|
|
private class NosqlInjectionSinkCharacteristic extends EndpointCharacteristic {
|
|
|
|
|
NosqlInjectionSinkCharacteristic() { this = "NosqlInjectionSink" }
|
|
|
|
|
|
|
|
|
|
override predicate getEndpoints(DataFlow::Node n) { n instanceof NosqlInjection::Sink }
|
|
|
|
|
override predicate appliesToEndpoint(DataFlow::Node n) { n instanceof NosqlInjection::Sink }
|
|
|
|
|
|
|
|
|
|
override predicate getImplications(
|
|
|
|
|
override predicate hasImplications(
|
|
|
|
|
EndpointType endpointClass, boolean isPositiveIndicator, float confidence
|
|
|
|
|
) {
|
|
|
|
|
endpointClass instanceof NosqlInjectionSinkType and
|
|
|
|
|
@@ -307,7 +307,7 @@ abstract private class NotASinkCharacteristic extends EndpointCharacteristic {
|
|
|
|
|
bindingset[this]
|
|
|
|
|
NotASinkCharacteristic() { any() }
|
|
|
|
|
|
|
|
|
|
override predicate getImplications(
|
|
|
|
|
override predicate hasImplications(
|
|
|
|
|
EndpointType endpointClass, boolean isPositiveIndicator, float confidence
|
|
|
|
|
) {
|
|
|
|
|
endpointClass instanceof NegativeType and
|
|
|
|
|
@@ -326,7 +326,7 @@ abstract class LikelyNotASinkCharacteristic extends EndpointCharacteristic {
|
|
|
|
|
bindingset[this]
|
|
|
|
|
LikelyNotASinkCharacteristic() { any() }
|
|
|
|
|
|
|
|
|
|
override predicate getImplications(
|
|
|
|
|
override predicate hasImplications(
|
|
|
|
|
EndpointType endpointClass, boolean isPositiveIndicator, float confidence
|
|
|
|
|
) {
|
|
|
|
|
endpointClass instanceof NegativeType and
|
|
|
|
|
@@ -339,7 +339,7 @@ private class LodashUnderscoreCharacteristic extends NotASinkCharacteristic,
|
|
|
|
|
OtherModeledArgumentCharacteristic {
|
|
|
|
|
LodashUnderscoreCharacteristic() { this = "LodashUnderscoreArgument" }
|
|
|
|
|
|
|
|
|
|
override predicate getEndpoints(DataFlow::Node n) {
|
|
|
|
|
override predicate appliesToEndpoint(DataFlow::Node n) {
|
|
|
|
|
any(LodashUnderscore::Member m).getACall().getAnArgument() = n
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -348,7 +348,7 @@ private class JQueryArgumentCharacteristic extends NotASinkCharacteristic,
|
|
|
|
|
OtherModeledArgumentCharacteristic {
|
|
|
|
|
JQueryArgumentCharacteristic() { this = "JQueryArgument" }
|
|
|
|
|
|
|
|
|
|
override predicate getEndpoints(DataFlow::Node n) {
|
|
|
|
|
override predicate appliesToEndpoint(DataFlow::Node n) {
|
|
|
|
|
any(JQuery::MethodCall m).getAnArgument() = n
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -357,7 +357,7 @@ private class ClientRequestCharacteristic extends NotASinkCharacteristic,
|
|
|
|
|
OtherModeledArgumentCharacteristic {
|
|
|
|
|
ClientRequestCharacteristic() { this = "ClientRequest" }
|
|
|
|
|
|
|
|
|
|
override predicate getEndpoints(DataFlow::Node n) {
|
|
|
|
|
override predicate appliesToEndpoint(DataFlow::Node n) {
|
|
|
|
|
exists(ClientRequest r |
|
|
|
|
|
r.getAnArgument() = n or n = r.getUrl() or n = r.getHost() or n = r.getADataNode()
|
|
|
|
|
)
|
|
|
|
|
@@ -368,7 +368,7 @@ private class PromiseDefinitionCharacteristic extends NotASinkCharacteristic,
|
|
|
|
|
OtherModeledArgumentCharacteristic {
|
|
|
|
|
PromiseDefinitionCharacteristic() { this = "PromiseDefinition" }
|
|
|
|
|
|
|
|
|
|
override predicate getEndpoints(DataFlow::Node n) {
|
|
|
|
|
override predicate appliesToEndpoint(DataFlow::Node n) {
|
|
|
|
|
exists(PromiseDefinition p |
|
|
|
|
|
n = [p.getResolveParameter(), p.getRejectParameter()].getACall().getAnArgument()
|
|
|
|
|
)
|
|
|
|
|
@@ -379,14 +379,14 @@ private class CryptographicKeyCharacteristic extends NotASinkCharacteristic,
|
|
|
|
|
OtherModeledArgumentCharacteristic {
|
|
|
|
|
CryptographicKeyCharacteristic() { this = "CryptographicKey" }
|
|
|
|
|
|
|
|
|
|
override predicate getEndpoints(DataFlow::Node n) { n instanceof CryptographicKey }
|
|
|
|
|
override predicate appliesToEndpoint(DataFlow::Node n) { n instanceof CryptographicKey }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private class CryptographicOperationFlowCharacteristic extends NotASinkCharacteristic,
|
|
|
|
|
OtherModeledArgumentCharacteristic {
|
|
|
|
|
CryptographicOperationFlowCharacteristic() { this = "CryptographicOperationFlow" }
|
|
|
|
|
|
|
|
|
|
override predicate getEndpoints(DataFlow::Node n) {
|
|
|
|
|
override predicate appliesToEndpoint(DataFlow::Node n) {
|
|
|
|
|
any(CryptographicOperation op).getInput() = n
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -395,7 +395,7 @@ private class LoggerMethodCharacteristic extends NotASinkCharacteristic,
|
|
|
|
|
OtherModeledArgumentCharacteristic {
|
|
|
|
|
LoggerMethodCharacteristic() { this = "LoggerMethod" }
|
|
|
|
|
|
|
|
|
|
override predicate getEndpoints(DataFlow::Node n) {
|
|
|
|
|
override predicate appliesToEndpoint(DataFlow::Node n) {
|
|
|
|
|
exists(DataFlow::CallNode call | n = call.getAnArgument() |
|
|
|
|
|
call.getCalleeName() = getAStandardLoggerMethodName()
|
|
|
|
|
)
|
|
|
|
|
@@ -406,7 +406,7 @@ private class TimeoutCharacteristic extends NotASinkCharacteristic,
|
|
|
|
|
OtherModeledArgumentCharacteristic {
|
|
|
|
|
TimeoutCharacteristic() { this = "Timeout" }
|
|
|
|
|
|
|
|
|
|
override predicate getEndpoints(DataFlow::Node n) {
|
|
|
|
|
override predicate appliesToEndpoint(DataFlow::Node n) {
|
|
|
|
|
exists(DataFlow::CallNode call | n = call.getAnArgument() |
|
|
|
|
|
call.getCalleeName() = ["setTimeout", "clearTimeout"]
|
|
|
|
|
)
|
|
|
|
|
@@ -417,7 +417,7 @@ private class ReceiverStorageCharacteristic extends NotASinkCharacteristic,
|
|
|
|
|
OtherModeledArgumentCharacteristic {
|
|
|
|
|
ReceiverStorageCharacteristic() { this = "ReceiverStorage" }
|
|
|
|
|
|
|
|
|
|
override predicate getEndpoints(DataFlow::Node n) {
|
|
|
|
|
override predicate appliesToEndpoint(DataFlow::Node n) {
|
|
|
|
|
exists(DataFlow::CallNode call | n = call.getAnArgument() |
|
|
|
|
|
call.getReceiver() = DataFlow::globalVarRef(["localStorage", "sessionStorage"])
|
|
|
|
|
)
|
|
|
|
|
@@ -428,7 +428,7 @@ private class StringStartsWithCharacteristic extends NotASinkCharacteristic,
|
|
|
|
|
OtherModeledArgumentCharacteristic {
|
|
|
|
|
StringStartsWithCharacteristic() { this = "StringStartsWith" }
|
|
|
|
|
|
|
|
|
|
override predicate getEndpoints(DataFlow::Node n) {
|
|
|
|
|
override predicate appliesToEndpoint(DataFlow::Node n) {
|
|
|
|
|
exists(DataFlow::CallNode call | n = call.getAnArgument() |
|
|
|
|
|
call instanceof StringOps::StartsWith
|
|
|
|
|
)
|
|
|
|
|
@@ -439,7 +439,7 @@ private class StringEndsWithCharacteristic extends NotASinkCharacteristic,
|
|
|
|
|
OtherModeledArgumentCharacteristic {
|
|
|
|
|
StringEndsWithCharacteristic() { this = "StringEndsWith" }
|
|
|
|
|
|
|
|
|
|
override predicate getEndpoints(DataFlow::Node n) {
|
|
|
|
|
override predicate appliesToEndpoint(DataFlow::Node n) {
|
|
|
|
|
exists(DataFlow::CallNode call | n = call.getAnArgument() | call instanceof StringOps::EndsWith)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -448,7 +448,7 @@ private class StringRegExpTestCharacteristic extends NotASinkCharacteristic,
|
|
|
|
|
OtherModeledArgumentCharacteristic {
|
|
|
|
|
StringRegExpTestCharacteristic() { this = "StringRegExpTest" }
|
|
|
|
|
|
|
|
|
|
override predicate getEndpoints(DataFlow::Node n) {
|
|
|
|
|
override predicate appliesToEndpoint(DataFlow::Node n) {
|
|
|
|
|
exists(DataFlow::CallNode call | n = call.getAnArgument() |
|
|
|
|
|
call instanceof StringOps::RegExpTest
|
|
|
|
|
)
|
|
|
|
|
@@ -459,7 +459,7 @@ private class EventRegistrationCharacteristic extends NotASinkCharacteristic,
|
|
|
|
|
OtherModeledArgumentCharacteristic {
|
|
|
|
|
EventRegistrationCharacteristic() { this = "EventRegistration" }
|
|
|
|
|
|
|
|
|
|
override predicate getEndpoints(DataFlow::Node n) {
|
|
|
|
|
override predicate appliesToEndpoint(DataFlow::Node n) {
|
|
|
|
|
exists(DataFlow::CallNode call | n = call.getAnArgument() | call instanceof EventRegistration)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -468,7 +468,7 @@ private class EventDispatchCharacteristic extends NotASinkCharacteristic,
|
|
|
|
|
OtherModeledArgumentCharacteristic {
|
|
|
|
|
EventDispatchCharacteristic() { this = "EventDispatch" }
|
|
|
|
|
|
|
|
|
|
override predicate getEndpoints(DataFlow::Node n) {
|
|
|
|
|
override predicate appliesToEndpoint(DataFlow::Node n) {
|
|
|
|
|
exists(DataFlow::CallNode call | n = call.getAnArgument() | call instanceof EventDispatch)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -477,7 +477,7 @@ private class MembershipCandidateTestCharacteristic extends NotASinkCharacterist
|
|
|
|
|
OtherModeledArgumentCharacteristic {
|
|
|
|
|
MembershipCandidateTestCharacteristic() { this = "MembershipCandidateTest" }
|
|
|
|
|
|
|
|
|
|
override predicate getEndpoints(DataFlow::Node n) {
|
|
|
|
|
override predicate appliesToEndpoint(DataFlow::Node n) {
|
|
|
|
|
exists(DataFlow::CallNode call | n = call.getAnArgument() |
|
|
|
|
|
call = any(MembershipCandidate c).getTest()
|
|
|
|
|
)
|
|
|
|
|
@@ -488,7 +488,7 @@ private class FileSystemAccessCharacteristic extends NotASinkCharacteristic,
|
|
|
|
|
OtherModeledArgumentCharacteristic {
|
|
|
|
|
FileSystemAccessCharacteristic() { this = "FileSystemAccess" }
|
|
|
|
|
|
|
|
|
|
override predicate getEndpoints(DataFlow::Node n) {
|
|
|
|
|
override predicate appliesToEndpoint(DataFlow::Node n) {
|
|
|
|
|
exists(DataFlow::CallNode call | n = call.getAnArgument() | call instanceof FileSystemAccess)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -497,7 +497,7 @@ private class DatabaseAccessCharacteristic extends NotASinkCharacteristic,
|
|
|
|
|
OtherModeledArgumentCharacteristic {
|
|
|
|
|
DatabaseAccessCharacteristic() { this = "DatabaseAccess" }
|
|
|
|
|
|
|
|
|
|
override predicate getEndpoints(DataFlow::Node n) {
|
|
|
|
|
override predicate appliesToEndpoint(DataFlow::Node n) {
|
|
|
|
|
// TODO database accesses are less well defined than database query sinks, so this may cover unmodeled sinks on
|
|
|
|
|
// existing database models
|
|
|
|
|
exists(DataFlow::CallNode call | n = call.getAnArgument() |
|
|
|
|
|
@@ -512,7 +512,7 @@ private class DatabaseAccessCharacteristic extends NotASinkCharacteristic,
|
|
|
|
|
private class DomCharacteristic extends NotASinkCharacteristic, OtherModeledArgumentCharacteristic {
|
|
|
|
|
DomCharacteristic() { this = "DOM" }
|
|
|
|
|
|
|
|
|
|
override predicate getEndpoints(DataFlow::Node n) {
|
|
|
|
|
override predicate appliesToEndpoint(DataFlow::Node n) {
|
|
|
|
|
exists(DataFlow::CallNode call | n = call.getAnArgument() | call = DOM::domValueRef())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -521,7 +521,7 @@ private class NextFunctionCallCharacteristic extends NotASinkCharacteristic,
|
|
|
|
|
OtherModeledArgumentCharacteristic {
|
|
|
|
|
NextFunctionCallCharacteristic() { this = "NextFunctionCall" }
|
|
|
|
|
|
|
|
|
|
override predicate getEndpoints(DataFlow::Node n) {
|
|
|
|
|
override predicate appliesToEndpoint(DataFlow::Node n) {
|
|
|
|
|
exists(DataFlow::CallNode call | n = call.getAnArgument() |
|
|
|
|
|
call.getCalleeName() = "next" and
|
|
|
|
|
exists(DataFlow::FunctionNode f | call = f.getLastParameter().getACall())
|
|
|
|
|
@@ -533,7 +533,7 @@ private class DojoRequireCharacteristic extends NotASinkCharacteristic,
|
|
|
|
|
OtherModeledArgumentCharacteristic {
|
|
|
|
|
DojoRequireCharacteristic() { this = "DojoRequire" }
|
|
|
|
|
|
|
|
|
|
override predicate getEndpoints(DataFlow::Node n) {
|
|
|
|
|
override predicate appliesToEndpoint(DataFlow::Node n) {
|
|
|
|
|
exists(DataFlow::CallNode call | n = call.getAnArgument() |
|
|
|
|
|
call = DataFlow::globalVarRef("dojo").getAPropertyRead("require").getACall()
|
|
|
|
|
)
|
|
|
|
|
@@ -544,7 +544,7 @@ private class Base64ManipulationCharacteristic extends NotASinkCharacteristic,
|
|
|
|
|
OtherModeledArgumentCharacteristic {
|
|
|
|
|
Base64ManipulationCharacteristic() { this = "Base64Manipulation" }
|
|
|
|
|
|
|
|
|
|
override predicate getEndpoints(DataFlow::Node n) {
|
|
|
|
|
override predicate appliesToEndpoint(DataFlow::Node n) {
|
|
|
|
|
exists(Base64::Decode d | n = d.getInput()) or
|
|
|
|
|
exists(Base64::Encode d | n = d.getInput())
|
|
|
|
|
}
|
|
|
|
|
@@ -554,7 +554,7 @@ private class ArgumentToArrayCharacteristic extends ArgumentToBuiltinFunctionCha
|
|
|
|
|
LikelyNotASinkCharacteristic {
|
|
|
|
|
ArgumentToArrayCharacteristic() { this = "ArgumentToArray" }
|
|
|
|
|
|
|
|
|
|
override predicate getEndpoints(DataFlow::Node n) {
|
|
|
|
|
override predicate appliesToEndpoint(DataFlow::Node n) {
|
|
|
|
|
exists(DataFlow::SourceNode builtin, DataFlow::SourceNode receiver, DataFlow::InvokeNode invk |
|
|
|
|
|
builtin instanceof DataFlow::ArrayCreationNode
|
|
|
|
|
|
|
|
|
|
|
@@ -569,7 +569,7 @@ private class ArgumentToBuiltinGlobalVarRefCharacteristic extends ArgumentToBuil
|
|
|
|
|
LikelyNotASinkCharacteristic {
|
|
|
|
|
ArgumentToBuiltinGlobalVarRefCharacteristic() { this = "ArgumentToBuiltinGlobalVarRef" }
|
|
|
|
|
|
|
|
|
|
override predicate getEndpoints(DataFlow::Node n) {
|
|
|
|
|
override predicate appliesToEndpoint(DataFlow::Node n) {
|
|
|
|
|
exists(DataFlow::SourceNode builtin, DataFlow::SourceNode receiver, DataFlow::InvokeNode invk |
|
|
|
|
|
builtin =
|
|
|
|
|
DataFlow::globalVarRef([
|
|
|
|
|
@@ -588,7 +588,7 @@ private class ConstantReceiverCharacteristic extends ArgumentToBuiltinFunctionCh
|
|
|
|
|
NotASinkCharacteristic {
|
|
|
|
|
ConstantReceiverCharacteristic() { this = "ConstantReceiver" }
|
|
|
|
|
|
|
|
|
|
override predicate getEndpoints(DataFlow::Node n) {
|
|
|
|
|
override predicate appliesToEndpoint(DataFlow::Node n) {
|
|
|
|
|
exists(Expr primitive, MethodCallExpr c |
|
|
|
|
|
primitive instanceof ConstantString or
|
|
|
|
|
primitive instanceof NumberLiteral or
|
|
|
|
|
@@ -604,7 +604,7 @@ private class BuiltinCallNameCharacteristic extends ArgumentToBuiltinFunctionCha
|
|
|
|
|
NotASinkCharacteristic {
|
|
|
|
|
BuiltinCallNameCharacteristic() { this = "BuiltinCallName" }
|
|
|
|
|
|
|
|
|
|
override predicate getEndpoints(DataFlow::Node n) {
|
|
|
|
|
override predicate appliesToEndpoint(DataFlow::Node n) {
|
|
|
|
|
exists(DataFlow::CallNode call |
|
|
|
|
|
call.getAnArgument() = n and
|
|
|
|
|
call.getCalleeName() =
|
|
|
|
|
@@ -633,7 +633,7 @@ abstract private class StandardEndpointFilterCharacteristic extends EndpointFilt
|
|
|
|
|
bindingset[this]
|
|
|
|
|
StandardEndpointFilterCharacteristic() { any() }
|
|
|
|
|
|
|
|
|
|
override predicate getImplications(
|
|
|
|
|
override predicate hasImplications(
|
|
|
|
|
EndpointType endpointClass, boolean isPositiveIndicator, float confidence
|
|
|
|
|
) {
|
|
|
|
|
endpointClass instanceof NegativeType and
|
|
|
|
|
@@ -645,7 +645,7 @@ abstract private class StandardEndpointFilterCharacteristic extends EndpointFilt
|
|
|
|
|
class IsArgumentToModeledFunctionCharacteristic extends StandardEndpointFilterCharacteristic {
|
|
|
|
|
IsArgumentToModeledFunctionCharacteristic() { this = "argument to modeled function" }
|
|
|
|
|
|
|
|
|
|
override predicate getEndpoints(DataFlow::Node n) {
|
|
|
|
|
override predicate appliesToEndpoint(DataFlow::Node n) {
|
|
|
|
|
exists(DataFlow::InvokeNode invk, DataFlow::Node known |
|
|
|
|
|
invk.getAnArgument() = n and
|
|
|
|
|
invk.getAnArgument() = known and
|
|
|
|
|
@@ -655,7 +655,7 @@ class IsArgumentToModeledFunctionCharacteristic extends StandardEndpointFilterCh
|
|
|
|
|
isKnownStepSrc(known)
|
|
|
|
|
or
|
|
|
|
|
exists(OtherModeledArgumentCharacteristic characteristic |
|
|
|
|
|
characteristic.getEndpoints(known)
|
|
|
|
|
characteristic.appliesToEndpoint(known)
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
@@ -665,7 +665,7 @@ class IsArgumentToModeledFunctionCharacteristic extends StandardEndpointFilterCh
|
|
|
|
|
private class IsArgumentToSinklessLibraryCharacteristic extends StandardEndpointFilterCharacteristic {
|
|
|
|
|
IsArgumentToSinklessLibraryCharacteristic() { this = "argument to sinkless library" }
|
|
|
|
|
|
|
|
|
|
override predicate getEndpoints(DataFlow::Node n) {
|
|
|
|
|
override predicate appliesToEndpoint(DataFlow::Node n) {
|
|
|
|
|
exists(DataFlow::InvokeNode invk, DataFlow::SourceNode commonSafeLibrary, string libraryName |
|
|
|
|
|
libraryName = ["slugify", "striptags", "marked"]
|
|
|
|
|
|
|
|
|
|
|
@@ -679,7 +679,7 @@ private class IsArgumentToSinklessLibraryCharacteristic extends StandardEndpoint
|
|
|
|
|
private class IsSanitizerCharacteristic extends StandardEndpointFilterCharacteristic {
|
|
|
|
|
IsSanitizerCharacteristic() { this = "sanitizer" }
|
|
|
|
|
|
|
|
|
|
override predicate getEndpoints(DataFlow::Node n) {
|
|
|
|
|
override predicate appliesToEndpoint(DataFlow::Node n) {
|
|
|
|
|
exists(DataFlow::CallNode call | n = call.getAnArgument() |
|
|
|
|
|
call.getCalleeName().regexpMatch("(?i).*(escape|valid(ate)?|sanitize|purify).*")
|
|
|
|
|
)
|
|
|
|
|
@@ -689,7 +689,7 @@ private class IsSanitizerCharacteristic extends StandardEndpointFilterCharacteri
|
|
|
|
|
private class IsPredicateCharacteristic extends StandardEndpointFilterCharacteristic {
|
|
|
|
|
IsPredicateCharacteristic() { this = "predicate" }
|
|
|
|
|
|
|
|
|
|
override predicate getEndpoints(DataFlow::Node n) {
|
|
|
|
|
override predicate appliesToEndpoint(DataFlow::Node n) {
|
|
|
|
|
exists(DataFlow::CallNode call | n = call.getAnArgument() |
|
|
|
|
|
call.getCalleeName().regexpMatch("(equals|(|is|has|can)(_|[A-Z])).*")
|
|
|
|
|
)
|
|
|
|
|
@@ -699,7 +699,7 @@ private class IsPredicateCharacteristic extends StandardEndpointFilterCharacteri
|
|
|
|
|
private class IsHashCharacteristic extends StandardEndpointFilterCharacteristic {
|
|
|
|
|
IsHashCharacteristic() { this = "hash" }
|
|
|
|
|
|
|
|
|
|
override predicate getEndpoints(DataFlow::Node n) {
|
|
|
|
|
override predicate appliesToEndpoint(DataFlow::Node n) {
|
|
|
|
|
exists(DataFlow::CallNode call | n = call.getAnArgument() |
|
|
|
|
|
call.getCalleeName().regexpMatch("(?i)^(sha\\d*|md5|hash)$")
|
|
|
|
|
)
|
|
|
|
|
@@ -709,7 +709,7 @@ private class IsHashCharacteristic extends StandardEndpointFilterCharacteristic
|
|
|
|
|
private class IsNumericCharacteristic extends StandardEndpointFilterCharacteristic {
|
|
|
|
|
IsNumericCharacteristic() { this = "numeric" }
|
|
|
|
|
|
|
|
|
|
override predicate getEndpoints(DataFlow::Node n) {
|
|
|
|
|
override predicate appliesToEndpoint(DataFlow::Node n) {
|
|
|
|
|
SyntacticHeuristics::isReadFrom(n, ".*index.*")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -721,7 +721,7 @@ private class InIrrelevantFileCharacteristic extends StandardEndpointFilterChara
|
|
|
|
|
this = "in " + category + " file" and category = ["externs", "generated", "library", "test"]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
override predicate getEndpoints(DataFlow::Node n) {
|
|
|
|
|
override predicate appliesToEndpoint(DataFlow::Node n) {
|
|
|
|
|
// Ignore candidate sinks within externs, generated, library, and test code
|
|
|
|
|
ClassifyFiles::classify(n.getFile(), category)
|
|
|
|
|
}
|
|
|
|
|
@@ -732,7 +732,7 @@ abstract private class NosqlInjectionSinkEndpointFilterCharacteristic extends En
|
|
|
|
|
bindingset[this]
|
|
|
|
|
NosqlInjectionSinkEndpointFilterCharacteristic() { any() }
|
|
|
|
|
|
|
|
|
|
override predicate getImplications(
|
|
|
|
|
override predicate hasImplications(
|
|
|
|
|
EndpointType endpointClass, boolean isPositiveIndicator, float confidence
|
|
|
|
|
) {
|
|
|
|
|
endpointClass instanceof NosqlInjectionSinkType and
|
|
|
|
|
@@ -744,7 +744,7 @@ abstract private class NosqlInjectionSinkEndpointFilterCharacteristic extends En
|
|
|
|
|
private class DatabaseAccessCallHeuristicCharacteristic extends NosqlInjectionSinkEndpointFilterCharacteristic {
|
|
|
|
|
DatabaseAccessCallHeuristicCharacteristic() { this = "matches database access call heuristic" }
|
|
|
|
|
|
|
|
|
|
override predicate getEndpoints(DataFlow::Node n) {
|
|
|
|
|
override predicate appliesToEndpoint(DataFlow::Node n) {
|
|
|
|
|
exists(DataFlow::MethodCallNode call | n = call.getAnArgument() |
|
|
|
|
|
// additional databases accesses that aren't modeled yet
|
|
|
|
|
call.getMethodName() = ["create", "createCollection", "createIndexes"]
|
|
|
|
|
@@ -764,7 +764,7 @@ private class ModeledSinkCharacteristic extends NosqlInjectionSinkEndpointFilter
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
override predicate getEndpoints(DataFlow::Node n) {
|
|
|
|
|
override predicate appliesToEndpoint(DataFlow::Node n) {
|
|
|
|
|
exists(DataFlow::CallNode call | n = call.getAnArgument() |
|
|
|
|
|
// Remove modeled sinks
|
|
|
|
|
isArgumentToKnownLibrarySinkFunction(n)
|
|
|
|
|
@@ -775,7 +775,7 @@ private class ModeledSinkCharacteristic extends NosqlInjectionSinkEndpointFilter
|
|
|
|
|
private class PredecessorInModeledFlowStepCharacteristic extends NosqlInjectionSinkEndpointFilterCharacteristic {
|
|
|
|
|
PredecessorInModeledFlowStepCharacteristic() { this = "predecessor in a modeled flow step" }
|
|
|
|
|
|
|
|
|
|
override predicate getEndpoints(DataFlow::Node n) {
|
|
|
|
|
override predicate appliesToEndpoint(DataFlow::Node n) {
|
|
|
|
|
exists(DataFlow::CallNode call | n = call.getAnArgument() |
|
|
|
|
|
// Remove common kinds of unlikely sinks
|
|
|
|
|
isKnownStepSrc(n)
|
|
|
|
|
@@ -786,7 +786,7 @@ private class PredecessorInModeledFlowStepCharacteristic extends NosqlInjectionS
|
|
|
|
|
private class ModeledDatabaseAccessCharacteristic extends NosqlInjectionSinkEndpointFilterCharacteristic {
|
|
|
|
|
ModeledDatabaseAccessCharacteristic() { this = "modeled database access" }
|
|
|
|
|
|
|
|
|
|
override predicate getEndpoints(DataFlow::Node n) {
|
|
|
|
|
override predicate appliesToEndpoint(DataFlow::Node n) {
|
|
|
|
|
exists(DataFlow::CallNode call | n = call.getAnArgument() |
|
|
|
|
|
// Remove modeled database calls. Arguments to modeled calls are very likely to be modeled
|
|
|
|
|
// as sinks if they are true positives. Therefore arguments that are not modeled as sinks
|
|
|
|
|
@@ -799,7 +799,7 @@ private class ModeledDatabaseAccessCharacteristic extends NosqlInjectionSinkEndp
|
|
|
|
|
private class ReceiverIsHttpRequestExpressionCharacteristic extends NosqlInjectionSinkEndpointFilterCharacteristic {
|
|
|
|
|
ReceiverIsHttpRequestExpressionCharacteristic() { this = "receiver is a HTTP request expression" }
|
|
|
|
|
|
|
|
|
|
override predicate getEndpoints(DataFlow::Node n) {
|
|
|
|
|
override predicate appliesToEndpoint(DataFlow::Node n) {
|
|
|
|
|
exists(DataFlow::CallNode call | n = call.getAnArgument() |
|
|
|
|
|
// Remove calls to APIs that aren't relevant to NoSQL injection
|
|
|
|
|
call.getReceiver() instanceof Http::RequestNode
|
|
|
|
|
@@ -812,7 +812,7 @@ private class ReceiverIsHttpResponseExpressionCharacteristic extends NosqlInject
|
|
|
|
|
this = "receiver is a HTTP response expression"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
override predicate getEndpoints(DataFlow::Node n) {
|
|
|
|
|
override predicate appliesToEndpoint(DataFlow::Node n) {
|
|
|
|
|
exists(DataFlow::CallNode call | n = call.getAnArgument() |
|
|
|
|
|
// Remove calls to APIs that aren't relevant to NoSQL injection
|
|
|
|
|
call.getReceiver() instanceof Http::ResponseNode
|
|
|
|
|
@@ -825,7 +825,7 @@ private class NotDirectArgumentToLikelyExternalLibraryCallOrHeuristicSinkNosqlCh
|
|
|
|
|
this = "not a direct argument to a likely external library call or a heuristic sink (nosql)"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
override predicate getEndpoints(DataFlow::Node n) {
|
|
|
|
|
override predicate appliesToEndpoint(DataFlow::Node n) {
|
|
|
|
|
// Require NoSQL injection sink candidates to be (a) direct arguments to external library calls
|
|
|
|
|
// or (b) heuristic sinks for NoSQL injection.
|
|
|
|
|
//
|
|
|
|
|
@@ -867,7 +867,7 @@ abstract private class SqlInjectionSinkEndpointFilterCharacteristic extends Endp
|
|
|
|
|
bindingset[this]
|
|
|
|
|
SqlInjectionSinkEndpointFilterCharacteristic() { any() }
|
|
|
|
|
|
|
|
|
|
override predicate getImplications(
|
|
|
|
|
override predicate hasImplications(
|
|
|
|
|
EndpointType endpointClass, boolean isPositiveIndicator, float confidence
|
|
|
|
|
) {
|
|
|
|
|
endpointClass instanceof SqlInjectionSinkType and
|
|
|
|
|
@@ -879,7 +879,7 @@ abstract private class SqlInjectionSinkEndpointFilterCharacteristic extends Endp
|
|
|
|
|
private class PreparedSqlStatementCharacteristic extends SqlInjectionSinkEndpointFilterCharacteristic {
|
|
|
|
|
PreparedSqlStatementCharacteristic() { this = "prepared SQL statement" }
|
|
|
|
|
|
|
|
|
|
override predicate getEndpoints(DataFlow::Node n) {
|
|
|
|
|
override predicate appliesToEndpoint(DataFlow::Node n) {
|
|
|
|
|
exists(DataFlow::CallNode call | n = call.getAnArgument() |
|
|
|
|
|
// prepared statements for SQL
|
|
|
|
|
any(DataFlow::CallNode cn | cn.getCalleeName() = "prepare")
|
|
|
|
|
@@ -892,7 +892,7 @@ private class PreparedSqlStatementCharacteristic extends SqlInjectionSinkEndpoin
|
|
|
|
|
private class ArrayCreationCharacteristic extends SqlInjectionSinkEndpointFilterCharacteristic {
|
|
|
|
|
ArrayCreationCharacteristic() { this = "array creation" }
|
|
|
|
|
|
|
|
|
|
override predicate getEndpoints(DataFlow::Node n) {
|
|
|
|
|
override predicate appliesToEndpoint(DataFlow::Node n) {
|
|
|
|
|
exists(DataFlow::CallNode call | n = call.getAnArgument() |
|
|
|
|
|
n instanceof DataFlow::ArrayCreationNode
|
|
|
|
|
)
|
|
|
|
|
@@ -902,7 +902,7 @@ private class ArrayCreationCharacteristic extends SqlInjectionSinkEndpointFilter
|
|
|
|
|
private class HtmlOrRenderingCharacteristic extends SqlInjectionSinkEndpointFilterCharacteristic {
|
|
|
|
|
HtmlOrRenderingCharacteristic() { this = "HTML / rendering" }
|
|
|
|
|
|
|
|
|
|
override predicate getEndpoints(DataFlow::Node n) {
|
|
|
|
|
override predicate appliesToEndpoint(DataFlow::Node n) {
|
|
|
|
|
exists(DataFlow::CallNode call | n = call.getAnArgument() |
|
|
|
|
|
// UI is unrelated to SQL
|
|
|
|
|
call.getCalleeName().regexpMatch("(?i).*(render|html).*")
|
|
|
|
|
@@ -915,7 +915,7 @@ private class NotAnArgumentToLikelyExternalLibraryCallOrHeuristicSinkCharacteris
|
|
|
|
|
this = "not an argument to a likely external library call or a heuristic sink"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
override predicate getEndpoints(DataFlow::Node n) {
|
|
|
|
|
override predicate appliesToEndpoint(DataFlow::Node n) {
|
|
|
|
|
// Require SQL injection sink candidates to be (a) arguments to external library calls
|
|
|
|
|
// (possibly indirectly), or (b) heuristic sinks.
|
|
|
|
|
//
|
|
|
|
|
@@ -938,7 +938,7 @@ abstract private class TaintedPathSinkEndpointFilterCharacteristic extends Endpo
|
|
|
|
|
bindingset[this]
|
|
|
|
|
TaintedPathSinkEndpointFilterCharacteristic() { any() }
|
|
|
|
|
|
|
|
|
|
override predicate getImplications(
|
|
|
|
|
override predicate hasImplications(
|
|
|
|
|
EndpointType endpointClass, boolean isPositiveIndicator, float confidence
|
|
|
|
|
) {
|
|
|
|
|
endpointClass instanceof TaintedPathSinkType and
|
|
|
|
|
@@ -953,7 +953,7 @@ private class NotDirectArgumentToLikelyExternalLibraryCallOrHeuristicSinkTainted
|
|
|
|
|
"not a direct argument to a likely external library call or a heuristic sink (tainted path)"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
override predicate getEndpoints(DataFlow::Node n) {
|
|
|
|
|
override predicate appliesToEndpoint(DataFlow::Node n) {
|
|
|
|
|
// Require path injection sink candidates to be (a) arguments to external library calls
|
|
|
|
|
// (possibly indirectly), or (b) heuristic sinks.
|
|
|
|
|
//
|
|
|
|
|
@@ -990,7 +990,7 @@ abstract private class XssSinkEndpointFilterCharacteristic extends EndpointFilte
|
|
|
|
|
bindingset[this]
|
|
|
|
|
XssSinkEndpointFilterCharacteristic() { any() }
|
|
|
|
|
|
|
|
|
|
override predicate getImplications(
|
|
|
|
|
override predicate hasImplications(
|
|
|
|
|
EndpointType endpointClass, boolean isPositiveIndicator, float confidence
|
|
|
|
|
) {
|
|
|
|
|
endpointClass instanceof XssSinkType and
|
|
|
|
|
@@ -1004,7 +1004,7 @@ private class SetStateCallsInReactApplicationsCharacteristic extends XssSinkEndp
|
|
|
|
|
this = "setState calls ought to be safe in react applications"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
override predicate getEndpoints(DataFlow::Node n) {
|
|
|
|
|
override predicate appliesToEndpoint(DataFlow::Node n) {
|
|
|
|
|
exists(DataFlow::CallNode call | n = call.getAnArgument() | call.getCalleeName() = "setState")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -1014,7 +1014,7 @@ private class NotDirectArgumentToLikelyExternalLibraryCallOrHeuristicSinkXssChar
|
|
|
|
|
this = "not a direct argument to a likely external library call or a heuristic sink (xss)"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
override predicate getEndpoints(DataFlow::Node n) {
|
|
|
|
|
override predicate appliesToEndpoint(DataFlow::Node n) {
|
|
|
|
|
// Require XSS sink candidates to be (a) arguments to external library calls (possibly
|
|
|
|
|
// indirectly), or (b) heuristic sinks.
|
|
|
|
|
//
|
|
|
|
|
|