mirror of
https://github.com/github/codeql.git
synced 2025-12-16 16:53:25 +01:00
Merge pull request #12427 from aschackmull/java/refactor-dataflow-queries-1
Java: Refactor some dataflow queries to the new API
This commit is contained in:
@@ -8,9 +8,11 @@ import semmle.code.java.dataflow.FlowSources
|
|||||||
import semmle.code.java.security.RequestForgery
|
import semmle.code.java.security.RequestForgery
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* DEPRECATED: Use `RequestForgeryConfiguration` module instead.
|
||||||
|
*
|
||||||
* A taint-tracking configuration characterising request-forgery risks.
|
* A taint-tracking configuration characterising request-forgery risks.
|
||||||
*/
|
*/
|
||||||
class RequestForgeryConfiguration extends TaintTracking::Configuration {
|
deprecated class RequestForgeryConfiguration extends TaintTracking::Configuration {
|
||||||
RequestForgeryConfiguration() { this = "Server-Side Request Forgery" }
|
RequestForgeryConfiguration() { this = "Server-Side Request Forgery" }
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node source) {
|
override predicate isSource(DataFlow::Node source) {
|
||||||
@@ -29,3 +31,26 @@ class RequestForgeryConfiguration extends TaintTracking::Configuration {
|
|||||||
|
|
||||||
override predicate isSanitizer(DataFlow::Node node) { node instanceof RequestForgerySanitizer }
|
override predicate isSanitizer(DataFlow::Node node) { node instanceof RequestForgerySanitizer }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A taint-tracking configuration characterising request-forgery risks.
|
||||||
|
*/
|
||||||
|
private module RequestForgeryConfiguration implements DataFlow::ConfigSig {
|
||||||
|
predicate isSource(DataFlow::Node source) {
|
||||||
|
source instanceof RemoteFlowSource and
|
||||||
|
// Exclude results of remote HTTP requests: fetching something else based on that result
|
||||||
|
// is no worse than following a redirect returned by the remote server, and typically
|
||||||
|
// we're requesting a resource via https which we trust to only send us to safe URLs.
|
||||||
|
not source.asExpr().(MethodAccess).getCallee() instanceof UrlConnectionGetInputStreamMethod
|
||||||
|
}
|
||||||
|
|
||||||
|
predicate isSink(DataFlow::Node sink) { sink instanceof RequestForgerySink }
|
||||||
|
|
||||||
|
predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) {
|
||||||
|
any(RequestForgeryAdditionalTaintStep r).propagatesTaint(pred, succ)
|
||||||
|
}
|
||||||
|
|
||||||
|
predicate isBarrier(DataFlow::Node node) { node instanceof RequestForgerySanitizer }
|
||||||
|
}
|
||||||
|
|
||||||
|
module RequestForgeryFlow = TaintTracking::Make<RequestForgeryConfiguration>;
|
||||||
|
|||||||
@@ -25,8 +25,12 @@ private class TypeType extends RefType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A data-flow configuration for identifying potentially-sensitive data flowing to a log output. */
|
/**
|
||||||
class SensitiveLoggerConfiguration extends TaintTracking::Configuration {
|
* DEPRECATED: Use `SensitiveLoggerConfiguration` module instead.
|
||||||
|
*
|
||||||
|
* A data-flow configuration for identifying potentially-sensitive data flowing to a log output.
|
||||||
|
*/
|
||||||
|
deprecated class SensitiveLoggerConfiguration extends TaintTracking::Configuration {
|
||||||
SensitiveLoggerConfiguration() { this = "SensitiveLoggerConfiguration" }
|
SensitiveLoggerConfiguration() { this = "SensitiveLoggerConfiguration" }
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node source) { source.asExpr() instanceof CredentialExpr }
|
override predicate isSource(DataFlow::Node source) { source.asExpr() instanceof CredentialExpr }
|
||||||
@@ -43,3 +47,22 @@ class SensitiveLoggerConfiguration extends TaintTracking::Configuration {
|
|||||||
|
|
||||||
override predicate isSanitizerIn(Node node) { this.isSource(node) }
|
override predicate isSanitizerIn(Node node) { this.isSource(node) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** A data-flow configuration for identifying potentially-sensitive data flowing to a log output. */
|
||||||
|
private module SensitiveLoggerConfiguration implements DataFlow::ConfigSig {
|
||||||
|
predicate isSource(DataFlow::Node source) { source.asExpr() instanceof CredentialExpr }
|
||||||
|
|
||||||
|
predicate isSink(DataFlow::Node sink) { sinkNode(sink, "logging") }
|
||||||
|
|
||||||
|
predicate isBarrier(DataFlow::Node sanitizer) {
|
||||||
|
sanitizer.asExpr() instanceof LiveLiteral or
|
||||||
|
sanitizer.getType() instanceof PrimitiveType or
|
||||||
|
sanitizer.getType() instanceof BoxedType or
|
||||||
|
sanitizer.getType() instanceof NumberType or
|
||||||
|
sanitizer.getType() instanceof TypeType
|
||||||
|
}
|
||||||
|
|
||||||
|
predicate isBarrierIn(Node node) { isSource(node) }
|
||||||
|
}
|
||||||
|
|
||||||
|
module SensitiveLoggerFlow = TaintTracking::Make<SensitiveLoggerConfiguration>;
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import semmle.code.java.frameworks.spring.SpringController
|
|||||||
import semmle.code.java.frameworks.spring.SpringHttp
|
import semmle.code.java.frameworks.spring.SpringHttp
|
||||||
import semmle.code.java.frameworks.javaee.jsf.JSFRenderer
|
import semmle.code.java.frameworks.javaee.jsf.JSFRenderer
|
||||||
import semmle.code.java.dataflow.DataFlow
|
import semmle.code.java.dataflow.DataFlow
|
||||||
import semmle.code.java.dataflow.TaintTracking2
|
import semmle.code.java.dataflow.TaintTracking
|
||||||
private import semmle.code.java.dataflow.ExternalFlow
|
private import semmle.code.java.dataflow.ExternalFlow
|
||||||
|
|
||||||
/** A sink that represent a method that outputs data without applying contextual output encoding. */
|
/** A sink that represent a method that outputs data without applying contextual output encoding. */
|
||||||
@@ -41,9 +41,9 @@ private class DefaultXssSink extends XssSink {
|
|||||||
DefaultXssSink() {
|
DefaultXssSink() {
|
||||||
sinkNode(this, "xss")
|
sinkNode(this, "xss")
|
||||||
or
|
or
|
||||||
exists(XssVulnerableWriterSourceToWritingMethodFlowConfig writer, MethodAccess ma |
|
exists(MethodAccess ma |
|
||||||
ma.getMethod() instanceof WritingMethod and
|
ma.getMethod() instanceof WritingMethod and
|
||||||
writer.hasFlowToExpr(ma.getQualifier()) and
|
XssVulnerableWriterSourceToWritingMethodFlow::hasFlowToExpr(ma.getQualifier()) and
|
||||||
this.asExpr() = ma.getArgument(_)
|
this.asExpr() = ma.getArgument(_)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -60,23 +60,19 @@ private class DefaultXssSanitizer extends XssSanitizer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** A configuration that tracks data from a servlet writer to an output method. */
|
/** A configuration that tracks data from a servlet writer to an output method. */
|
||||||
private class XssVulnerableWriterSourceToWritingMethodFlowConfig extends TaintTracking2::Configuration
|
private module XssVulnerableWriterSourceToWritingMethodFlowConfig implements DataFlow::ConfigSig {
|
||||||
{
|
predicate isSource(DataFlow::Node src) { src.asExpr() instanceof XssVulnerableWriterSource }
|
||||||
XssVulnerableWriterSourceToWritingMethodFlowConfig() {
|
|
||||||
this = "XSS::XssVulnerableWriterSourceToWritingMethodFlowConfig"
|
|
||||||
}
|
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node src) {
|
predicate isSink(DataFlow::Node sink) {
|
||||||
src.asExpr() instanceof XssVulnerableWriterSource
|
|
||||||
}
|
|
||||||
|
|
||||||
override predicate isSink(DataFlow::Node sink) {
|
|
||||||
exists(MethodAccess ma |
|
exists(MethodAccess ma |
|
||||||
sink.asExpr() = ma.getQualifier() and ma.getMethod() instanceof WritingMethod
|
sink.asExpr() = ma.getQualifier() and ma.getMethod() instanceof WritingMethod
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private module XssVulnerableWriterSourceToWritingMethodFlow =
|
||||||
|
TaintTracking::Make<XssVulnerableWriterSourceToWritingMethodFlowConfig>;
|
||||||
|
|
||||||
/** A method that can be used to output data to an output stream or writer. */
|
/** A method that can be used to output data to an output stream or writer. */
|
||||||
private class WritingMethod extends Method {
|
private class WritingMethod extends Method {
|
||||||
WritingMethod() {
|
WritingMethod() {
|
||||||
|
|||||||
@@ -18,32 +18,33 @@ import semmle.code.java.dataflow.FlowSources
|
|||||||
private import semmle.code.java.dataflow.ExternalFlow
|
private import semmle.code.java.dataflow.ExternalFlow
|
||||||
import semmle.code.java.security.PathCreation
|
import semmle.code.java.security.PathCreation
|
||||||
import semmle.code.java.security.PathSanitizer
|
import semmle.code.java.security.PathSanitizer
|
||||||
import DataFlow::PathGraph
|
|
||||||
import TaintedPathCommon
|
import TaintedPathCommon
|
||||||
|
|
||||||
class TaintedPathConfig extends TaintTracking::Configuration {
|
module TaintedPathConfig implements DataFlow::ConfigSig {
|
||||||
TaintedPathConfig() { this = "TaintedPathConfig" }
|
predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
|
predicate isSink(DataFlow::Node sink) {
|
||||||
|
|
||||||
override predicate isSink(DataFlow::Node sink) {
|
|
||||||
sink.asExpr() = any(PathCreation p).getAnInput()
|
sink.asExpr() = any(PathCreation p).getAnInput()
|
||||||
or
|
or
|
||||||
sinkNode(sink, ["create-file", "read-file"])
|
sinkNode(sink, ["create-file", "read-file"])
|
||||||
}
|
}
|
||||||
|
|
||||||
override predicate isSanitizer(DataFlow::Node sanitizer) {
|
predicate isBarrier(DataFlow::Node sanitizer) {
|
||||||
sanitizer.getType() instanceof BoxedType or
|
sanitizer.getType() instanceof BoxedType or
|
||||||
sanitizer.getType() instanceof PrimitiveType or
|
sanitizer.getType() instanceof PrimitiveType or
|
||||||
sanitizer.getType() instanceof NumberType or
|
sanitizer.getType() instanceof NumberType or
|
||||||
sanitizer instanceof PathInjectionSanitizer
|
sanitizer instanceof PathInjectionSanitizer
|
||||||
}
|
}
|
||||||
|
|
||||||
override predicate isAdditionalTaintStep(DataFlow::Node n1, DataFlow::Node n2) {
|
predicate isAdditionalFlowStep(DataFlow::Node n1, DataFlow::Node n2) {
|
||||||
any(TaintedPathAdditionalTaintStep s).step(n1, n2)
|
any(TaintedPathAdditionalTaintStep s).step(n1, n2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module TaintedPath = TaintTracking::Make<TaintedPathConfig>;
|
||||||
|
|
||||||
|
import TaintedPath::PathGraph
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the data-flow node at which to report a path ending at `sink`.
|
* Gets the data-flow node at which to report a path ending at `sink`.
|
||||||
*
|
*
|
||||||
@@ -52,13 +53,13 @@ class TaintedPathConfig extends TaintTracking::Configuration {
|
|||||||
* continue to report there; otherwise we report directly at `sink`.
|
* continue to report there; otherwise we report directly at `sink`.
|
||||||
*/
|
*/
|
||||||
DataFlow::Node getReportingNode(DataFlow::Node sink) {
|
DataFlow::Node getReportingNode(DataFlow::Node sink) {
|
||||||
any(TaintedPathConfig c).hasFlowTo(sink) and
|
TaintedPath::hasFlowTo(sink) and
|
||||||
if exists(PathCreation pc | pc.getAnInput() = sink.asExpr())
|
if exists(PathCreation pc | pc.getAnInput() = sink.asExpr())
|
||||||
then result.asExpr() = any(PathCreation pc | pc.getAnInput() = sink.asExpr())
|
then result.asExpr() = any(PathCreation pc | pc.getAnInput() = sink.asExpr())
|
||||||
else result = sink
|
else result = sink
|
||||||
}
|
}
|
||||||
|
|
||||||
from DataFlow::PathNode source, DataFlow::PathNode sink, TaintedPathConfig conf
|
from TaintedPath::PathNode source, TaintedPath::PathNode sink
|
||||||
where conf.hasFlowPath(source, sink)
|
where TaintedPath::hasFlowPath(source, sink)
|
||||||
select getReportingNode(sink.getNode()), source, sink, "This path depends on a $@.",
|
select getReportingNode(sink.getNode()), source, sink, "This path depends on a $@.",
|
||||||
source.getNode(), "user-provided value"
|
source.getNode(), "user-provided value"
|
||||||
|
|||||||
@@ -14,25 +14,26 @@
|
|||||||
import java
|
import java
|
||||||
import semmle.code.java.dataflow.FlowSources
|
import semmle.code.java.dataflow.FlowSources
|
||||||
import semmle.code.java.security.XSS
|
import semmle.code.java.security.XSS
|
||||||
import DataFlow::PathGraph
|
|
||||||
|
|
||||||
class XssConfig extends TaintTracking::Configuration {
|
module XssConfig implements DataFlow::ConfigSig {
|
||||||
XssConfig() { this = "XSSConfig" }
|
predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
|
predicate isSink(DataFlow::Node sink) { sink instanceof XssSink }
|
||||||
|
|
||||||
override predicate isSink(DataFlow::Node sink) { sink instanceof XssSink }
|
predicate isBarrier(DataFlow::Node node) { node instanceof XssSanitizer }
|
||||||
|
|
||||||
override predicate isSanitizer(DataFlow::Node node) { node instanceof XssSanitizer }
|
predicate isBarrierOut(DataFlow::Node node) { node instanceof XssSinkBarrier }
|
||||||
|
|
||||||
override predicate isSanitizerOut(DataFlow::Node node) { node instanceof XssSinkBarrier }
|
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||||
|
|
||||||
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
|
|
||||||
any(XssAdditionalTaintStep s).step(node1, node2)
|
any(XssAdditionalTaintStep s).step(node1, node2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
from DataFlow::PathNode source, DataFlow::PathNode sink, XssConfig conf
|
module XssFlow = TaintTracking::Make<XssConfig>;
|
||||||
where conf.hasFlowPath(source, sink)
|
|
||||||
|
import XssFlow::PathGraph
|
||||||
|
|
||||||
|
from XssFlow::PathNode source, XssFlow::PathNode sink
|
||||||
|
where XssFlow::hasFlowPath(source, sink)
|
||||||
select sink.getNode(), source, sink, "Cross-site scripting vulnerability due to a $@.",
|
select sink.getNode(), source, sink, "Cross-site scripting vulnerability due to a $@.",
|
||||||
source.getNode(), "user-provided value"
|
source.getNode(), "user-provided value"
|
||||||
|
|||||||
@@ -14,19 +14,16 @@
|
|||||||
import java
|
import java
|
||||||
import semmle.code.java.dataflow.FlowSources
|
import semmle.code.java.dataflow.FlowSources
|
||||||
import semmle.code.java.security.ResponseSplitting
|
import semmle.code.java.security.ResponseSplitting
|
||||||
import DataFlow::PathGraph
|
|
||||||
|
|
||||||
class ResponseSplittingConfig extends TaintTracking::Configuration {
|
module ResponseSplittingConfig implements DataFlow::ConfigSig {
|
||||||
ResponseSplittingConfig() { this = "ResponseSplittingConfig" }
|
predicate isSource(DataFlow::Node source) {
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node source) {
|
|
||||||
source instanceof RemoteFlowSource and
|
source instanceof RemoteFlowSource and
|
||||||
not source instanceof SafeHeaderSplittingSource
|
not source instanceof SafeHeaderSplittingSource
|
||||||
}
|
}
|
||||||
|
|
||||||
override predicate isSink(DataFlow::Node sink) { sink instanceof HeaderSplittingSink }
|
predicate isSink(DataFlow::Node sink) { sink instanceof HeaderSplittingSink }
|
||||||
|
|
||||||
override predicate isSanitizer(DataFlow::Node node) {
|
predicate isBarrier(DataFlow::Node node) {
|
||||||
node.getType() instanceof PrimitiveType
|
node.getType() instanceof PrimitiveType
|
||||||
or
|
or
|
||||||
node.getType() instanceof BoxedType
|
node.getType() instanceof BoxedType
|
||||||
@@ -45,8 +42,12 @@ class ResponseSplittingConfig extends TaintTracking::Configuration {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
from DataFlow::PathNode source, DataFlow::PathNode sink, ResponseSplittingConfig conf
|
module ResponseSplitting = TaintTracking::Make<ResponseSplittingConfig>;
|
||||||
where conf.hasFlowPath(source, sink)
|
|
||||||
|
import ResponseSplitting::PathGraph
|
||||||
|
|
||||||
|
from ResponseSplitting::PathNode source, ResponseSplitting::PathNode sink
|
||||||
|
where ResponseSplitting::hasFlowPath(source, sink)
|
||||||
select sink.getNode(), source, sink,
|
select sink.getNode(), source, sink,
|
||||||
"This header depends on a $@, which may cause a response-splitting vulnerability.",
|
"This header depends on a $@, which may cause a response-splitting vulnerability.",
|
||||||
source.getNode(), "user-provided value"
|
source.getNode(), "user-provided value"
|
||||||
|
|||||||
@@ -14,23 +14,24 @@
|
|||||||
import java
|
import java
|
||||||
import semmle.code.java.dataflow.FlowSources
|
import semmle.code.java.dataflow.FlowSources
|
||||||
import semmle.code.java.security.ResponseSplitting
|
import semmle.code.java.security.ResponseSplitting
|
||||||
import DataFlow::PathGraph
|
|
||||||
|
|
||||||
class ResponseSplittingLocalConfig extends TaintTracking::Configuration {
|
module ResponseSplittingLocalConfig implements DataFlow::ConfigSig {
|
||||||
ResponseSplittingLocalConfig() { this = "ResponseSplittingLocalConfig" }
|
predicate isSource(DataFlow::Node source) { source instanceof LocalUserInput }
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node source) { source instanceof LocalUserInput }
|
predicate isSink(DataFlow::Node sink) { sink instanceof HeaderSplittingSink }
|
||||||
|
|
||||||
override predicate isSink(DataFlow::Node sink) { sink instanceof HeaderSplittingSink }
|
predicate isBarrier(DataFlow::Node node) {
|
||||||
|
|
||||||
override predicate isSanitizer(DataFlow::Node node) {
|
|
||||||
node.getType() instanceof PrimitiveType or
|
node.getType() instanceof PrimitiveType or
|
||||||
node.getType() instanceof BoxedType
|
node.getType() instanceof BoxedType
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
from DataFlow::PathNode source, DataFlow::PathNode sink, ResponseSplittingLocalConfig conf
|
module ResponseSplitting = TaintTracking::Make<ResponseSplittingLocalConfig>;
|
||||||
where conf.hasFlowPath(source, sink)
|
|
||||||
|
import ResponseSplitting::PathGraph
|
||||||
|
|
||||||
|
from ResponseSplitting::PathNode source, ResponseSplitting::PathNode sink
|
||||||
|
where ResponseSplitting::hasFlowPath(source, sink)
|
||||||
select sink.getNode(), source, sink,
|
select sink.getNode(), source, sink,
|
||||||
"This header depends on a $@, which may cause a response-splitting vulnerability.",
|
"This header depends on a $@, which may cause a response-splitting vulnerability.",
|
||||||
source.getNode(), "user-provided value"
|
source.getNode(), "user-provided value"
|
||||||
|
|||||||
@@ -31,33 +31,27 @@ class PrintStackTraceMethod extends Method {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ServletWriterSourceToPrintStackTraceMethodFlowConfig extends TaintTracking::Configuration {
|
module ServletWriterSourceToPrintStackTraceMethodFlowConfig implements DataFlow::ConfigSig {
|
||||||
ServletWriterSourceToPrintStackTraceMethodFlowConfig() {
|
predicate isSource(DataFlow::Node src) { src.asExpr() instanceof XssVulnerableWriterSource }
|
||||||
this = "StackTraceExposure::ServletWriterSourceToPrintStackTraceMethodFlowConfig"
|
|
||||||
}
|
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node src) {
|
predicate isSink(DataFlow::Node sink) {
|
||||||
src.asExpr() instanceof XssVulnerableWriterSource
|
|
||||||
}
|
|
||||||
|
|
||||||
override predicate isSink(DataFlow::Node sink) {
|
|
||||||
exists(MethodAccess ma |
|
exists(MethodAccess ma |
|
||||||
sink.asExpr() = ma.getAnArgument() and ma.getMethod() instanceof PrintStackTraceMethod
|
sink.asExpr() = ma.getAnArgument() and ma.getMethod() instanceof PrintStackTraceMethod
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module ServletWriterSourceToPrintStackTraceMethodFlow =
|
||||||
|
TaintTracking::Make<ServletWriterSourceToPrintStackTraceMethodFlowConfig>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A call that uses `Throwable.printStackTrace()` on a stream that is connected
|
* A call that uses `Throwable.printStackTrace()` on a stream that is connected
|
||||||
* to external output.
|
* to external output.
|
||||||
*/
|
*/
|
||||||
predicate printsStackToWriter(MethodAccess call) {
|
predicate printsStackToWriter(MethodAccess call) {
|
||||||
exists(
|
exists(PrintStackTraceMethod printStackTrace |
|
||||||
ServletWriterSourceToPrintStackTraceMethodFlowConfig writerSource,
|
|
||||||
PrintStackTraceMethod printStackTrace
|
|
||||||
|
|
|
||||||
call.getMethod() = printStackTrace and
|
call.getMethod() = printStackTrace and
|
||||||
writerSource.hasFlowToExpr(call.getAnArgument())
|
ServletWriterSourceToPrintStackTraceMethodFlow::hasFlowToExpr(call.getAnArgument())
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,16 +80,15 @@ predicate stackTraceExpr(Expr exception, MethodAccess stackTraceString) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
class StackTraceStringToHttpResponseSinkFlowConfig extends TaintTracking::Configuration {
|
module StackTraceStringToHttpResponseSinkFlowConfig implements DataFlow::ConfigSig {
|
||||||
StackTraceStringToHttpResponseSinkFlowConfig() {
|
predicate isSource(DataFlow::Node src) { stackTraceExpr(_, src.asExpr()) }
|
||||||
this = "StackTraceExposure::StackTraceStringToHttpResponseSinkFlowConfig"
|
|
||||||
}
|
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node src) { stackTraceExpr(_, src.asExpr()) }
|
predicate isSink(DataFlow::Node sink) { sink instanceof InformationLeakSink }
|
||||||
|
|
||||||
override predicate isSink(DataFlow::Node sink) { sink instanceof InformationLeakSink }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module StackTraceStringToHttpResponseSinkFlow =
|
||||||
|
TaintTracking::Make<StackTraceStringToHttpResponseSinkFlowConfig>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A write of stack trace data to an external stream.
|
* A write of stack trace data to an external stream.
|
||||||
*/
|
*/
|
||||||
@@ -109,9 +102,10 @@ predicate printsStackExternally(MethodAccess call, Expr stackTrace) {
|
|||||||
* A stringified stack trace flows to an external sink.
|
* A stringified stack trace flows to an external sink.
|
||||||
*/
|
*/
|
||||||
predicate stringifiedStackFlowsExternally(DataFlow::Node externalExpr, Expr stackTrace) {
|
predicate stringifiedStackFlowsExternally(DataFlow::Node externalExpr, Expr stackTrace) {
|
||||||
exists(MethodAccess stackTraceString, StackTraceStringToHttpResponseSinkFlowConfig conf |
|
exists(MethodAccess stackTraceString |
|
||||||
stackTraceExpr(stackTrace, stackTraceString) and
|
stackTraceExpr(stackTrace, stackTraceString) and
|
||||||
conf.hasFlow(DataFlow::exprNode(stackTraceString), externalExpr)
|
StackTraceStringToHttpResponseSinkFlow::hasFlow(DataFlow::exprNode(stackTraceString),
|
||||||
|
externalExpr)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ import java
|
|||||||
import semmle.code.java.security.Encryption
|
import semmle.code.java.security.Encryption
|
||||||
import semmle.code.java.dataflow.TaintTracking
|
import semmle.code.java.dataflow.TaintTracking
|
||||||
import DataFlow
|
import DataFlow
|
||||||
import PathGraph
|
|
||||||
|
|
||||||
private class ShortStringLiteral extends StringLiteral {
|
private class ShortStringLiteral extends StringLiteral {
|
||||||
ShortStringLiteral() { getValue().length() < 100 }
|
ShortStringLiteral() { getValue().length() < 100 }
|
||||||
@@ -29,24 +28,26 @@ class BrokenAlgoLiteral extends ShortStringLiteral {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class InsecureCryptoConfiguration extends TaintTracking::Configuration {
|
module InsecureCryptoConfiguration implements ConfigSig {
|
||||||
InsecureCryptoConfiguration() { this = "BrokenCryptoAlgortihm::InsecureCryptoConfiguration" }
|
predicate isSource(Node n) { n.asExpr() instanceof BrokenAlgoLiteral }
|
||||||
|
|
||||||
override predicate isSource(Node n) { n.asExpr() instanceof BrokenAlgoLiteral }
|
predicate isSink(Node n) { exists(CryptoAlgoSpec c | n.asExpr() = c.getAlgoSpec()) }
|
||||||
|
|
||||||
override predicate isSink(Node n) { exists(CryptoAlgoSpec c | n.asExpr() = c.getAlgoSpec()) }
|
predicate isBarrier(DataFlow::Node node) {
|
||||||
|
|
||||||
override predicate isSanitizer(DataFlow::Node node) {
|
|
||||||
node.getType() instanceof PrimitiveType or node.getType() instanceof BoxedType
|
node.getType() instanceof PrimitiveType or node.getType() instanceof BoxedType
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module InsecureCryptoFlow = TaintTracking::Make<InsecureCryptoConfiguration>;
|
||||||
|
|
||||||
|
import InsecureCryptoFlow::PathGraph
|
||||||
|
|
||||||
from
|
from
|
||||||
PathNode source, PathNode sink, CryptoAlgoSpec c, BrokenAlgoLiteral s,
|
InsecureCryptoFlow::PathNode source, InsecureCryptoFlow::PathNode sink, CryptoAlgoSpec c,
|
||||||
InsecureCryptoConfiguration conf
|
BrokenAlgoLiteral s
|
||||||
where
|
where
|
||||||
sink.getNode().asExpr() = c.getAlgoSpec() and
|
sink.getNode().asExpr() = c.getAlgoSpec() and
|
||||||
source.getNode().asExpr() = s and
|
source.getNode().asExpr() = s and
|
||||||
conf.hasFlowPath(source, sink)
|
InsecureCryptoFlow::hasFlowPath(source, sink)
|
||||||
select c, source, sink, "Cryptographic algorithm $@ is weak and should not be used.", s,
|
select c, source, sink, "Cryptographic algorithm $@ is weak and should not be used.", s,
|
||||||
s.getValue()
|
s.getValue()
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ import semmle.code.java.security.Encryption
|
|||||||
import semmle.code.java.dataflow.TaintTracking
|
import semmle.code.java.dataflow.TaintTracking
|
||||||
import DataFlow
|
import DataFlow
|
||||||
import semmle.code.java.dispatch.VirtualDispatch
|
import semmle.code.java.dispatch.VirtualDispatch
|
||||||
import PathGraph
|
|
||||||
|
|
||||||
private class ShortStringLiteral extends StringLiteral {
|
private class ShortStringLiteral extends StringLiteral {
|
||||||
ShortStringLiteral() { this.getValue().length() < 100 }
|
ShortStringLiteral() { this.getValue().length() < 100 }
|
||||||
@@ -51,26 +50,28 @@ class StringContainer extends RefType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class InsecureCryptoConfiguration extends TaintTracking::Configuration {
|
module InsecureCryptoConfiguration implements ConfigSig {
|
||||||
InsecureCryptoConfiguration() { this = "InsecureCryptoConfiguration" }
|
predicate isSource(Node n) { n.asExpr() instanceof InsecureAlgoLiteral }
|
||||||
|
|
||||||
override predicate isSource(Node n) { n.asExpr() instanceof InsecureAlgoLiteral }
|
predicate isSink(Node n) { exists(CryptoAlgoSpec c | n.asExpr() = c.getAlgoSpec()) }
|
||||||
|
|
||||||
override predicate isSink(Node n) { exists(CryptoAlgoSpec c | n.asExpr() = c.getAlgoSpec()) }
|
predicate isBarrier(Node n) {
|
||||||
|
|
||||||
override predicate isSanitizer(Node n) {
|
|
||||||
objectToString(n.asExpr()) or
|
objectToString(n.asExpr()) or
|
||||||
not n.getType().getErasure() instanceof StringContainer
|
not n.getType().getErasure() instanceof StringContainer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module InsecureCryptoFlow = TaintTracking::Make<InsecureCryptoConfiguration>;
|
||||||
|
|
||||||
|
import InsecureCryptoFlow::PathGraph
|
||||||
|
|
||||||
from
|
from
|
||||||
PathNode source, PathNode sink, CryptoAlgoSpec c, InsecureAlgoLiteral s,
|
InsecureCryptoFlow::PathNode source, InsecureCryptoFlow::PathNode sink, CryptoAlgoSpec c,
|
||||||
InsecureCryptoConfiguration conf
|
InsecureAlgoLiteral s
|
||||||
where
|
where
|
||||||
sink.getNode().asExpr() = c.getAlgoSpec() and
|
sink.getNode().asExpr() = c.getAlgoSpec() and
|
||||||
source.getNode().asExpr() = s and
|
source.getNode().asExpr() = s and
|
||||||
conf.hasFlowPath(source, sink)
|
InsecureCryptoFlow::hasFlowPath(source, sink)
|
||||||
select c, source, sink,
|
select c, source, sink,
|
||||||
"Cryptographic algorithm $@ may not be secure, consider using a different algorithm.", s,
|
"Cryptographic algorithm $@ may not be secure, consider using a different algorithm.", s,
|
||||||
s.getValue()
|
s.getValue()
|
||||||
|
|||||||
@@ -13,9 +13,9 @@
|
|||||||
|
|
||||||
import java
|
import java
|
||||||
import semmle.code.java.security.SensitiveLoggingQuery
|
import semmle.code.java.security.SensitiveLoggingQuery
|
||||||
import PathGraph
|
import SensitiveLoggerFlow::PathGraph
|
||||||
|
|
||||||
from SensitiveLoggerConfiguration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
|
from SensitiveLoggerFlow::PathNode source, SensitiveLoggerFlow::PathNode sink
|
||||||
where cfg.hasFlowPath(source, sink)
|
where SensitiveLoggerFlow::hasFlowPath(source, sink)
|
||||||
select sink.getNode(), source, sink, "This $@ is written to a log file.", source.getNode(),
|
select sink.getNode(), source, sink, "This $@ is written to a log file.", source.getNode(),
|
||||||
"potentially sensitive information"
|
"potentially sensitive information"
|
||||||
|
|||||||
@@ -15,19 +15,16 @@
|
|||||||
import java
|
import java
|
||||||
import semmle.code.java.dataflow.FlowSources
|
import semmle.code.java.dataflow.FlowSources
|
||||||
import NumericCastCommon
|
import NumericCastCommon
|
||||||
import DataFlow::PathGraph
|
|
||||||
|
|
||||||
private class NumericCastFlowConfig extends TaintTracking::Configuration {
|
module NumericCastFlowConfig implements DataFlow::ConfigSig {
|
||||||
NumericCastFlowConfig() { this = "NumericCastTainted::RemoteUserInputToNumericNarrowingCastExpr" }
|
predicate isSource(DataFlow::Node src) { src instanceof RemoteFlowSource }
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node src) { src instanceof RemoteFlowSource }
|
predicate isSink(DataFlow::Node sink) {
|
||||||
|
|
||||||
override predicate isSink(DataFlow::Node sink) {
|
|
||||||
sink.asExpr() = any(NumericNarrowingCastExpr cast).getExpr() and
|
sink.asExpr() = any(NumericNarrowingCastExpr cast).getExpr() and
|
||||||
sink.asExpr() instanceof VarAccess
|
sink.asExpr() instanceof VarAccess
|
||||||
}
|
}
|
||||||
|
|
||||||
override predicate isSanitizer(DataFlow::Node node) {
|
predicate isBarrier(DataFlow::Node node) {
|
||||||
boundedRead(node.asExpr()) or
|
boundedRead(node.asExpr()) or
|
||||||
castCheck(node.asExpr()) or
|
castCheck(node.asExpr()) or
|
||||||
node.getType() instanceof SmallType or
|
node.getType() instanceof SmallType or
|
||||||
@@ -37,12 +34,14 @@ private class NumericCastFlowConfig extends TaintTracking::Configuration {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
from
|
module NumericCastFlow = TaintTracking::Make<NumericCastFlowConfig>;
|
||||||
DataFlow::PathNode source, DataFlow::PathNode sink, NumericNarrowingCastExpr exp,
|
|
||||||
NumericCastFlowConfig conf
|
import NumericCastFlow::PathGraph
|
||||||
|
|
||||||
|
from NumericCastFlow::PathNode source, NumericCastFlow::PathNode sink, NumericNarrowingCastExpr exp
|
||||||
where
|
where
|
||||||
sink.getNode().asExpr() = exp.getExpr() and
|
sink.getNode().asExpr() = exp.getExpr() and
|
||||||
conf.hasFlowPath(source, sink)
|
NumericCastFlow::hasFlowPath(source, sink)
|
||||||
select exp, source, sink,
|
select exp, source, sink,
|
||||||
"This cast to a narrower type depends on a $@, potentially causing truncation.", source.getNode(),
|
"This cast to a narrower type depends on a $@, potentially causing truncation.", source.getNode(),
|
||||||
"user-provided value"
|
"user-provided value"
|
||||||
|
|||||||
@@ -15,20 +15,15 @@
|
|||||||
import java
|
import java
|
||||||
import semmle.code.java.dataflow.FlowSources
|
import semmle.code.java.dataflow.FlowSources
|
||||||
import NumericCastCommon
|
import NumericCastCommon
|
||||||
import DataFlow::PathGraph
|
|
||||||
|
|
||||||
private class NumericCastFlowConfig extends TaintTracking::Configuration {
|
module NumericCastFlowConfig implements DataFlow::ConfigSig {
|
||||||
NumericCastFlowConfig() {
|
predicate isSource(DataFlow::Node src) { src instanceof LocalUserInput }
|
||||||
this = "NumericCastTaintedLocal::LocalUserInputToNumericNarrowingCastExpr"
|
|
||||||
}
|
|
||||||
|
|
||||||
override predicate isSource(DataFlow::Node src) { src instanceof LocalUserInput }
|
predicate isSink(DataFlow::Node sink) {
|
||||||
|
|
||||||
override predicate isSink(DataFlow::Node sink) {
|
|
||||||
sink.asExpr() = any(NumericNarrowingCastExpr cast).getExpr()
|
sink.asExpr() = any(NumericNarrowingCastExpr cast).getExpr()
|
||||||
}
|
}
|
||||||
|
|
||||||
override predicate isSanitizer(DataFlow::Node node) {
|
predicate isBarrier(DataFlow::Node node) {
|
||||||
boundedRead(node.asExpr()) or
|
boundedRead(node.asExpr()) or
|
||||||
castCheck(node.asExpr()) or
|
castCheck(node.asExpr()) or
|
||||||
node.getType() instanceof SmallType or
|
node.getType() instanceof SmallType or
|
||||||
@@ -37,13 +32,17 @@ private class NumericCastFlowConfig extends TaintTracking::Configuration {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module NumericCastFlow = TaintTracking::Make<NumericCastFlowConfig>;
|
||||||
|
|
||||||
|
import NumericCastFlow::PathGraph
|
||||||
|
|
||||||
from
|
from
|
||||||
DataFlow::PathNode source, DataFlow::PathNode sink, NumericNarrowingCastExpr exp,
|
NumericCastFlow::PathNode source, NumericCastFlow::PathNode sink, NumericNarrowingCastExpr exp,
|
||||||
VarAccess tainted, NumericCastFlowConfig conf
|
VarAccess tainted
|
||||||
where
|
where
|
||||||
exp.getExpr() = tainted and
|
exp.getExpr() = tainted and
|
||||||
sink.getNode().asExpr() = tainted and
|
sink.getNode().asExpr() = tainted and
|
||||||
conf.hasFlowPath(source, sink) and
|
NumericCastFlow::hasFlowPath(source, sink) and
|
||||||
not exists(RightShiftOp e | e.getShiftedVariable() = tainted.getVariable())
|
not exists(RightShiftOp e | e.getShiftedVariable() = tainted.getVariable())
|
||||||
select exp, source, sink,
|
select exp, source, sink,
|
||||||
"This cast to a narrower type depends on a $@, potentially causing truncation.", source.getNode(),
|
"This cast to a narrower type depends on a $@, potentially causing truncation.", source.getNode(),
|
||||||
|
|||||||
@@ -13,9 +13,9 @@
|
|||||||
|
|
||||||
import java
|
import java
|
||||||
import semmle.code.java.security.RequestForgeryConfig
|
import semmle.code.java.security.RequestForgeryConfig
|
||||||
import DataFlow::PathGraph
|
import RequestForgeryFlow::PathGraph
|
||||||
|
|
||||||
from DataFlow::PathNode source, DataFlow::PathNode sink, RequestForgeryConfiguration conf
|
from RequestForgeryFlow::PathNode source, RequestForgeryFlow::PathNode sink
|
||||||
where conf.hasFlowPath(source, sink)
|
where RequestForgeryFlow::hasFlowPath(source, sink)
|
||||||
select sink.getNode(), source, sink, "Potential server-side request forgery due to a $@.",
|
select sink.getNode(), source, sink, "Potential server-side request forgery due to a $@.",
|
||||||
source.getNode(), "user-provided value"
|
source.getNode(), "user-provided value"
|
||||||
|
|||||||
@@ -2,14 +2,10 @@ import java
|
|||||||
import TestUtilities.InlineFlowTest
|
import TestUtilities.InlineFlowTest
|
||||||
import semmle.code.java.security.SensitiveLoggingQuery
|
import semmle.code.java.security.SensitiveLoggingQuery
|
||||||
|
|
||||||
class EnableLegacy extends EnableLegacyConfiguration {
|
|
||||||
EnableLegacy() { exists(this) }
|
|
||||||
}
|
|
||||||
|
|
||||||
class HasFlowTest extends InlineFlowTest {
|
class HasFlowTest extends InlineFlowTest {
|
||||||
override DataFlow::Configuration getTaintFlowConfig() {
|
override predicate hasTaintFlow(DataFlow::Node src, DataFlow::Node sink) {
|
||||||
result instanceof SensitiveLoggerConfiguration
|
SensitiveLoggerFlow::hasFlow(src, sink)
|
||||||
}
|
}
|
||||||
|
|
||||||
override DataFlow::Configuration getValueFlowConfig() { none() }
|
override predicate hasValueFlow(DataFlow::Node src, DataFlow::Node sink) { none() }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,8 @@ class HasFlowTest extends InlineExpectationsTest {
|
|||||||
|
|
||||||
override predicate hasActualResult(Location location, string element, string tag, string value) {
|
override predicate hasActualResult(Location location, string element, string tag, string value) {
|
||||||
tag = "SSRF" and
|
tag = "SSRF" and
|
||||||
exists(RequestForgeryConfiguration conf, DataFlow::Node sink | conf.hasFlowTo(sink) |
|
exists(DataFlow::Node sink |
|
||||||
|
RequestForgeryFlow::hasFlowTo(sink) and
|
||||||
sink.getLocation() = location and
|
sink.getLocation() = location and
|
||||||
element = sink.toString() and
|
element = sink.toString() and
|
||||||
value = ""
|
value = ""
|
||||||
|
|||||||
Reference in New Issue
Block a user