-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Java: CWE-200: Temp directory local information disclosure vulnerability
- Loading branch information
1 parent
768e519
commit d53d77c
Showing
11 changed files
with
260 additions
and
3 deletions.
There are no files selected for viewing
72 changes: 72 additions & 0 deletions
72
java/ql/src/Security/CWE/CWE-200/TempDirLocalInformationDisclosure1.ql
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
/** | ||
* @name Temporary Directory Local information disclosure | ||
* @description Detect local information disclosure via the java temporary directory | ||
* @kind problem | ||
* @problem.severity warning | ||
* @precision very-high | ||
* @id java/local-information-disclosure | ||
* @tags security | ||
* external/cwe/cwe-200 | ||
*/ | ||
|
||
import TempDirUtils | ||
|
||
/** | ||
* All `java.io.File::createTempFile` methods. | ||
*/ | ||
class MethodFileCreateTempFile extends Method { | ||
MethodFileCreateTempFile() { | ||
this.getDeclaringType() instanceof TypeFile and | ||
this.hasName("createTempFile") | ||
} | ||
} | ||
|
||
class TempDirSystemGetPropertyToAnyConfig extends TaintTracking::Configuration { | ||
TempDirSystemGetPropertyToAnyConfig() { this = "TempDirSystemGetPropertyToAnyConfig" } | ||
|
||
override predicate isSource(DataFlow::Node source) { | ||
source.asExpr() instanceof MethodAccessSystemGetPropertyTempDir | ||
} | ||
|
||
override predicate isSink(DataFlow::Node source) { any() } | ||
|
||
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { | ||
isAdditionalFileTaintStep(node1, node2) | ||
} | ||
} | ||
|
||
abstract class MethodAccessInsecureFileCreation extends MethodAccess { } | ||
|
||
/** | ||
* Insecure calls to `java.io.File::createTempFile`. | ||
*/ | ||
class MethodAccessInsecureFileCreateTempFile extends MethodAccessInsecureFileCreation { | ||
MethodAccessInsecureFileCreateTempFile() { | ||
this.getMethod() instanceof MethodFileCreateTempFile and | ||
( | ||
this.getNumArgument() = 2 or | ||
getArgument(2) instanceof NullLiteral or | ||
// There exists a flow from the 'java.io.tmpdir' system property to this argument | ||
exists(TempDirSystemGetPropertyToAnyConfig config | | ||
config.hasFlowTo(DataFlow::exprNode(getArgument(2))) | ||
) | ||
) | ||
} | ||
} | ||
|
||
class MethodGuavaFilesCreateTempFile extends Method { | ||
MethodGuavaFilesCreateTempFile() { | ||
getDeclaringType().hasQualifiedName("com.google.common.io", "Files") and | ||
hasName("createTempDir") | ||
} | ||
} | ||
|
||
class MethodAccessInsecureGuavaFilesCreateTempFile extends MethodAccessInsecureFileCreation { | ||
MethodAccessInsecureGuavaFilesCreateTempFile() { | ||
getMethod() instanceof MethodGuavaFilesCreateTempFile | ||
} | ||
} | ||
|
||
from MethodAccessInsecureFileCreation methodAccess | ||
select methodAccess, | ||
"Local information disclosure vulnerability due to use of file or directory readable by other local users." |
48 changes: 48 additions & 0 deletions
48
java/ql/src/Security/CWE/CWE-200/TempDirLocalInformationDisclosure2.ql
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
/** | ||
* @name Temporary Directory Local information disclosure | ||
* @description Detect local information disclosure via the java temporary directory | ||
* @kind path-problem | ||
* @problem.severity warning | ||
* @precision very-high | ||
* @id java/local-information-disclosure | ||
* @tags security | ||
* external/cwe/cwe-200 | ||
*/ | ||
|
||
import TempDirUtils | ||
import DataFlow::PathGraph | ||
|
||
private class MethodFileSystemCreation extends Method { | ||
MethodFileSystemCreation() { | ||
getDeclaringType() instanceof TypeFile and | ||
( | ||
hasName("mkdir") or | ||
hasName("createNewFile") | ||
) | ||
} | ||
} | ||
|
||
private class TempDirSystemGetPropertyToCreateConfig extends TaintTracking::Configuration { | ||
TempDirSystemGetPropertyToCreateConfig() { this = "TempDirSystemGetPropertyToCreateConfig" } | ||
|
||
override predicate isSource(DataFlow::Node source) { | ||
source.asExpr() instanceof MethodAccessSystemGetPropertyTempDir | ||
} | ||
|
||
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { | ||
isAdditionalFileTaintStep(node1, node2) | ||
} | ||
|
||
override predicate isSink(DataFlow::Node sink) { | ||
exists (MethodAccess ma | | ||
ma.getMethod() instanceof MethodFileSystemCreation and | ||
ma.getQualifier() = sink.asExpr() | ||
) | ||
} | ||
} | ||
|
||
from DataFlow::PathNode source, DataFlow::PathNode sink, TempDirSystemGetPropertyToCreateConfig conf | ||
where conf.hasFlowPath(source, sink) | ||
select source.getNode(), source, sink, | ||
"Local information disclosure vulnerability from $@ due to use of file or directory readable by other local users.", source.getNode(), | ||
"system temp directory" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
import java | ||
import semmle.code.java.dataflow.FlowSources | ||
|
||
class MethodAccessSystemGetPropertyTempDir extends MethodAccessSystemGetProperty { | ||
MethodAccessSystemGetPropertyTempDir() { this.hasCompileTimeConstantGetPropertyName("java.io.tmpdir") } | ||
} | ||
|
||
/** | ||
* Find dataflow from the temp directory system property to the `File` constructor. | ||
* Examples: | ||
* - `new File(System.getProperty("java.io.tmpdir"))` | ||
* - `new File(new File(System.getProperty("java.io.tmpdir")), "/child")` | ||
*/ | ||
private predicate isTaintedFileCreation(Expr expSource, Expr exprDest) { | ||
exists(ConstructorCall construtorCall | | ||
construtorCall.getConstructedType() instanceof TypeFile and | ||
construtorCall.getArgument(0) = expSource and | ||
construtorCall = exprDest | ||
) | ||
} | ||
|
||
/** | ||
* Any `File` methods that | ||
*/ | ||
private class TaintFollowingFileMethod extends Method { | ||
TaintFollowingFileMethod() { | ||
getDeclaringType() instanceof TypeFile and | ||
( | ||
hasName("getAbsoluteFile") or | ||
hasName("getCanonicalFile") | ||
) | ||
} | ||
} | ||
|
||
private predicate isTaintFollowingFileTransformation(Expr expSource, Expr exprDest) { | ||
exists(MethodAccess fileMethodAccess | | ||
fileMethodAccess.getMethod() instanceof TaintFollowingFileMethod and | ||
fileMethodAccess.getQualifier() = expSource and | ||
fileMethodAccess = exprDest | ||
) | ||
} | ||
|
||
predicate isAdditionalFileTaintStep(DataFlow::Node node1, DataFlow::Node node2) { | ||
isTaintedFileCreation(node1.asExpr(), node2.asExpr()) or | ||
isTaintFollowingFileTransformation(node1.asExpr(), node2.asExpr()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
22 changes: 22 additions & 0 deletions
22
java/ql/test/query-tests/security/CWE-200/semmle/tests/Files.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package com.google.common.io; | ||
|
||
import java.io.File; | ||
|
||
public class Files { | ||
/** Maximum loop count when creating temp directories. */ | ||
private static final int TEMP_DIR_ATTEMPTS = 10000; | ||
|
||
public static File createTempDir() { | ||
File baseDir = new File(System.getProperty("java.io.tmpdir")); | ||
String baseName = System.currentTimeMillis() + "-"; | ||
|
||
for (int counter = 0; counter < TEMP_DIR_ATTEMPTS; counter++) { | ||
File tempDir = new File(baseDir, baseName + counter); | ||
if (tempDir.mkdir()) { | ||
return tempDir; | ||
} | ||
} | ||
throw new IllegalStateException("Failed to create directory within " + TEMP_DIR_ATTEMPTS + " attempts (tried " | ||
+ baseName + "0 to " + baseName + (TEMP_DIR_ATTEMPTS - 1) + ')'); | ||
} | ||
} |
1 change: 1 addition & 0 deletions
1
...l/test/query-tests/security/CWE-200/semmle/tests/TempDirLocalInformationDisclosure1.qlref
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Security/CWE/CWE-200/TempDirLocalInformationDisclosure1.ql |
1 change: 1 addition & 0 deletions
1
...l/test/query-tests/security/CWE-200/semmle/tests/TempDirLocalInformationDisclosure2.qlref
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Security/CWE/CWE-200/TempDirLocalInformationDisclosure2.ql |
50 changes: 50 additions & 0 deletions
50
java/ql/test/query-tests/security/CWE-200/semmle/tests/Test.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
|
||
import java.io.File; | ||
import com.google.common.io.Files; | ||
|
||
public class Test { | ||
|
||
void vulnerableFileCreateTempFile() { | ||
File temp = File.createTempFile("random", "file"); | ||
} | ||
|
||
void vulnerableFileCreateTempFileNull() { | ||
File temp = File.createTempFile("random", "file", null); | ||
} | ||
|
||
void vulnerableFileCreateTempFileTainted() { | ||
File tempDir = new File(System.getProperty("java.io.tmpdir")); | ||
File temp = File.createTempFile("random", "file", tempDir); | ||
} | ||
|
||
void vulnerableFileCreateTempFileChildTainted() { | ||
File tempDirChild = new File(new File(System.getProperty("java.io.tmpdir")), "/child"); | ||
File temp = File.createTempFile("random", "file", tempDirChild); | ||
} | ||
|
||
void vulnerableFileCreateTempFileCanonical() { | ||
File tempDir = new File(System.getProperty("java.io.tmpdir")).getCanonicalFile(); | ||
File temp = File.createTempFile("random", "file", tempDir); | ||
} | ||
|
||
void vulnerableFileCreateTempFileAbsolute() { | ||
File tempDir = new File(System.getProperty("java.io.tmpdir")).getAbsoluteFile(); | ||
File temp = File.createTempFile("random", "file", tempDir); | ||
} | ||
|
||
void safeFileCreateTempFileTainted() { | ||
/* Creating a temporary directoy in the current user directory is not a vulnerability. */ | ||
File currentDirectory = new File(System.getProperty("user.dir")); | ||
File temp = File.createTempFile("random", "file", currentDirectory); | ||
} | ||
|
||
void vulnerableGuavaFilesCreateTempDir() { | ||
File tempDir = Files.createTempDir(); | ||
} | ||
|
||
void vulnerableFileCreateTempFileMkdirTainted() { | ||
File tempDirChild = new File(System.getProperty("java.io.tmpdir"), "/child"); | ||
tempDirChild.mkdir(); | ||
} | ||
|
||
} |