Java: Add taint step for InputStream wrappers

This commit is contained in:
Tony Torralba
2023-07-19 11:36:09 +02:00
parent 69ea7d92cd
commit 00e0e5a61a
5 changed files with 140 additions and 1 deletions

View File

@@ -4,6 +4,7 @@
import Member
import semmle.code.java.security.ExternalProcess
private import semmle.code.java.dataflow.DataFlow
private import semmle.code.java.dataflow.FlowSteps
// --- Standard types ---
@@ -177,6 +178,11 @@ class TypeObjectInputStream extends RefType {
TypeObjectInputStream() { this.hasQualifiedName("java.io", "ObjectInputStream") }
}
/** The class `java.io.InputStream`. */
class TypeInputStream extends RefType {
TypeInputStream() { this.hasQualifiedName("java.io", "InputStream") }
}
/** The class `java.nio.file.Paths`. */
class TypePaths extends Class {
TypePaths() { this.hasQualifiedName("java.nio.file", "Paths") }
@@ -197,6 +203,48 @@ class TypeFile extends Class {
TypeFile() { this.hasQualifiedName("java.io", "File") }
}
/**
* A taint step from an update of the `bytes[]` parameter in an override of the `InputStream.read` method
* to a class instance expression of the type extending `InputStream`.
*
* This models how a subtype of `InputStream` could be tainted by the definition of its methods, which will
* normally only happen in anonymous classes.
*/
private class InputStreamWrapperAnonymousStep extends AdditionalTaintStep {
override predicate step(DataFlow::Node n1, DataFlow::Node n2) {
exists(Method m, AnonymousClass wrapper |
m.hasName("read") and
m.getDeclaringType() = wrapper and
wrapper.getASourceSupertype+() instanceof TypeInputStream
|
n1.(DataFlow::PostUpdateNode).getPreUpdateNode().asExpr() = m.getParameter(0).getAnAccess() and
n2.asExpr() = wrapper.getClassInstanceExpr()
)
}
}
/**
* A taint step from an `InputStream` argument of the constructor of an `InputStream` subtype
* to the call of the constructor, only if the argument is assigned to a class field.
*
* This models how it's assumed that an `InputStream` wrapper is tainted by the wrapped stream,
* and is a workaround to low `fieldFlowBranchLimit`s in dataflow configurations.
*/
private class InputStreamWrapperConstructorStep extends AdditionalTaintStep {
override predicate step(DataFlow::Node n1, DataFlow::Node n2) {
exists(ClassInstanceExpr cc, Argument a, AssignExpr ae |
cc.getConstructedType().getASourceSupertype+() instanceof TypeInputStream and
cc.getAnArgument() = a and
cc.getCallee().getParameter(a.getParameterPos()).getAnAccess() = ae.getRhs() and
ae.getDest().(FieldWrite).getField().getType().(RefType).getASourceSupertype*() instanceof
TypeInputStream
|
n1.asExpr() = a and
n2.asExpr() = cc
)
}
}
// --- Standard methods ---
/**
* DEPRECATED: Any constructor of class `java.lang.ProcessBuilder`.

View File

@@ -757,7 +757,7 @@ private predicate baseBound(Expr e, int b, boolean upper) {
or
exists(Method read |
e.(MethodAccess).getMethod().overrides*(read) and
read.getDeclaringType().hasQualifiedName("java.io", "InputStream") and
read.getDeclaringType() instanceof TypeInputStream and
read.hasName("read") and
read.getNumberOfParameters() = 0
|