Merge pull request #12886 from atorralba/atorralba/java/path-injection-mad-sinks

Java: Refactor path injection sinks
This commit is contained in:
Tony Torralba
2024-02-09 10:48:49 +01:00
committed by GitHub
21 changed files with 229 additions and 937 deletions

View File

@@ -1,11 +1,13 @@
/**
* DEPRECATED.
*
* Models the different ways to create paths. Either by using `java.io.File`-related APIs or `java.nio.file.Path`-related APIs.
*/
import java
/** Models the creation of a path. */
abstract class PathCreation extends Expr {
/** DEPRECATED: Models the creation of a path. */
abstract deprecated class PathCreation extends Expr {
/**
* Gets an input that is used in the creation of this path.
* This excludes inputs of type `File` and `Path`.
@@ -14,7 +16,7 @@ abstract class PathCreation extends Expr {
}
/** Models the `java.nio.file.Paths.get` method. */
private class PathsGet extends PathCreation, MethodCall {
deprecated private class PathsGet extends PathCreation, MethodCall {
PathsGet() {
exists(Method m | m = this.getMethod() |
m.getDeclaringType() instanceof TypePaths and
@@ -26,7 +28,7 @@ private class PathsGet extends PathCreation, MethodCall {
}
/** Models the `java.nio.file.FileSystem.getPath` method. */
private class FileSystemGetPath extends PathCreation, MethodCall {
deprecated private class FileSystemGetPath extends PathCreation, MethodCall {
FileSystemGetPath() {
exists(Method m | m = this.getMethod() |
m.getDeclaringType() instanceof TypeFileSystem and
@@ -38,7 +40,7 @@ private class FileSystemGetPath extends PathCreation, MethodCall {
}
/** Models the `new java.io.File(...)` constructor. */
private class FileCreation extends PathCreation, ClassInstanceExpr {
deprecated private class FileCreation extends PathCreation, ClassInstanceExpr {
FileCreation() { this.getConstructedType() instanceof TypeFile }
override Expr getAnInput() {
@@ -49,7 +51,7 @@ private class FileCreation extends PathCreation, ClassInstanceExpr {
}
/** Models the `java.nio.file.Path.resolveSibling` method. */
private class PathResolveSiblingCreation extends PathCreation, MethodCall {
deprecated private class PathResolveSiblingCreation extends PathCreation, MethodCall {
PathResolveSiblingCreation() {
exists(Method m | m = this.getMethod() |
m.getDeclaringType() instanceof TypePath and
@@ -65,7 +67,7 @@ private class PathResolveSiblingCreation extends PathCreation, MethodCall {
}
/** Models the `java.nio.file.Path.resolve` method. */
private class PathResolveCreation extends PathCreation, MethodCall {
deprecated private class PathResolveCreation extends PathCreation, MethodCall {
PathResolveCreation() {
exists(Method m | m = this.getMethod() |
m.getDeclaringType() instanceof TypePath and
@@ -81,7 +83,7 @@ private class PathResolveCreation extends PathCreation, MethodCall {
}
/** Models the `java.nio.file.Path.of` method. */
private class PathOfCreation extends PathCreation, MethodCall {
deprecated private class PathOfCreation extends PathCreation, MethodCall {
PathOfCreation() {
exists(Method m | m = this.getMethod() |
m.getDeclaringType() instanceof TypePath and
@@ -93,7 +95,7 @@ private class PathOfCreation extends PathCreation, MethodCall {
}
/** Models the `new java.io.FileWriter(...)` constructor. */
private class FileWriterCreation extends PathCreation, ClassInstanceExpr {
deprecated private class FileWriterCreation extends PathCreation, ClassInstanceExpr {
FileWriterCreation() { this.getConstructedType().hasQualifiedName("java.io", "FileWriter") }
override Expr getAnInput() {
@@ -104,7 +106,7 @@ private class FileWriterCreation extends PathCreation, ClassInstanceExpr {
}
/** Models the `new java.io.FileReader(...)` constructor. */
private class FileReaderCreation extends PathCreation, ClassInstanceExpr {
deprecated private class FileReaderCreation extends PathCreation, ClassInstanceExpr {
FileReaderCreation() { this.getConstructedType().hasQualifiedName("java.io", "FileReader") }
override Expr getAnInput() {
@@ -115,7 +117,7 @@ private class FileReaderCreation extends PathCreation, ClassInstanceExpr {
}
/** Models the `new java.io.FileInputStream(...)` constructor. */
private class FileInputStreamCreation extends PathCreation, ClassInstanceExpr {
deprecated private class FileInputStreamCreation extends PathCreation, ClassInstanceExpr {
FileInputStreamCreation() {
this.getConstructedType().hasQualifiedName("java.io", "FileInputStream")
}
@@ -128,7 +130,7 @@ private class FileInputStreamCreation extends PathCreation, ClassInstanceExpr {
}
/** Models the `new java.io.FileOutputStream(...)` constructor. */
private class FileOutputStreamCreation extends PathCreation, ClassInstanceExpr {
deprecated private class FileOutputStreamCreation extends PathCreation, ClassInstanceExpr {
FileOutputStreamCreation() {
this.getConstructedType().hasQualifiedName("java.io", "FileOutputStream")
}

View File

@@ -8,6 +8,13 @@ private import semmle.code.java.dataflow.ExternalFlow
import semmle.code.java.security.PathSanitizer
private import semmle.code.java.security.Sanitizers
/** A sink for tainted path flow configurations. */
abstract class TaintedPathSink extends DataFlow::Node { }
private class DefaultTaintedPathSink extends TaintedPathSink {
DefaultTaintedPathSink() { sinkNode(this, "path-injection") }
}
/**
* A unit class for adding additional taint steps.
*
@@ -55,7 +62,7 @@ private class TaintPreservingUriCtorParam extends Parameter {
module TaintedPathConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof ThreatModelFlowSource }
predicate isSink(DataFlow::Node sink) { sinkNode(sink, "path-injection") }
predicate isSink(DataFlow::Node sink) { sink instanceof TaintedPathSink }
predicate isBarrier(DataFlow::Node sanitizer) {
sanitizer instanceof SimpleTypeSanitizer or
@@ -76,7 +83,7 @@ module TaintedPathFlow = TaintTracking::Global<TaintedPathConfig>;
module TaintedPathLocalConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof LocalUserInput }
predicate isSink(DataFlow::Node sink) { sinkNode(sink, "path-injection") }
predicate isSink(DataFlow::Node sink) { sink instanceof TaintedPathSink }
predicate isBarrier(DataFlow::Node sanitizer) {
sanitizer instanceof SimpleTypeSanitizer or

View File

@@ -41,28 +41,5 @@ module ZipSlipFlow = TaintTracking::Global<ZipSlipConfig>;
* A sink that represents a file creation, such as a file write, copy or move operation.
*/
private class FileCreationSink extends DataFlow::Node {
FileCreationSink() {
sinkNode(this, "path-injection") and
not isPathCreation(this)
}
}
/**
* Holds if `sink` is a path creation node that doesn't imply a read/write filesystem operation.
* This is to avoid creating new spurious alerts, since `PathCreation` sinks weren't
* previously part of this query.
*/
private predicate isPathCreation(DataFlow::Node sink) {
exists(PathCreation pc |
pc.getAnInput() = sink.asExpr()
or
pc.getAnInput().(Argument).isVararg() and sink.(DataFlow::ImplicitVarargsArray).getCall() = pc
|
// exclude actual read/write operations included in `PathCreation`
not pc.(Call)
.getCallee()
.getDeclaringType()
.hasQualifiedName("java.io",
["FileInputStream", "FileOutputStream", "FileReader", "FileWriter"])
)
FileCreationSink() { sinkNode(this, "path-injection") }
}