Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 7f46640

Browse files
committed
Consider calls to setReadable(false, false) then setReadable(true, true) to be safe
1 parent a6596ea commit 7f46640

3 files changed

Lines changed: 68 additions & 12 deletions

File tree

java/ql/src/Security/CWE/CWE-200/TempDirLocalInformationDisclosure.ql

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -197,14 +197,17 @@ class InsecureMethodPseudoConfiguration extends DataFlow::Configuration {
197197

198198
from DataFlow::PathNode source, DataFlow::PathNode sink, string message
199199
where
200-
any(TempDirSystemGetPropertyToCreateConfig conf).hasFlowPath(source, sink) and
201-
message =
202-
"Local information disclosure vulnerability from $@ due to use of file or directory readable by other local users."
203-
or
204-
any(InsecureMethodPseudoConfiguration conf).hasFlowPath(source, sink) and
205-
// Note this message has no "$@" placeholder, so the "system temp directory" template parameter below is not used.
206-
message =
207-
"Local information disclosure vulnerability due to use of " +
208-
source.getNode().asExpr().(MethodAccessInsecureFileCreation).getFileSystemEntityType() +
209-
" readable by other local users."
200+
(
201+
any(TempDirSystemGetPropertyToCreateConfig conf).hasFlowPath(source, sink) and
202+
message =
203+
"Local information disclosure vulnerability from $@ due to use of file or directory readable by other local users."
204+
or
205+
any(InsecureMethodPseudoConfiguration conf).hasFlowPath(source, sink) and
206+
// Note this message has no "$@" placeholder, so the "system temp directory" template parameter below is not used.
207+
message =
208+
"Local information disclosure vulnerability due to use of " +
209+
source.getNode().asExpr().(MethodAccessInsecureFileCreation).getFileSystemEntityType() +
210+
" readable by other local users."
211+
) and
212+
not isPermissionsProtectedTempDirUse(sink.getNode())
210213
select source.getNode(), source, sink, message, source.getNode(), "system temp directory"

java/ql/src/Security/CWE/CWE-200/TempDirUtils.qll

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,8 @@ private predicate isFileConstructorArgument(Expr expSource, Expr exprDest) {
5959
*/
6060
private class TaintFollowingFileMethod extends Method {
6161
TaintFollowingFileMethod() {
62-
getDeclaringType() instanceof TypeFile and
63-
hasName(["getAbsoluteFile", "getCanonicalFile"])
62+
this.getDeclaringType() instanceof TypeFile and
63+
this.hasName(["getAbsoluteFile", "getCanonicalFile"])
6464
}
6565
}
6666

@@ -80,3 +80,50 @@ predicate isAdditionalFileTaintStep(DataFlow::Node node1, DataFlow::Node node2)
8080
isFileConstructorArgument(node1.asExpr(), node2.asExpr()) or
8181
isTaintPropagatingFileTransformation(node1.asExpr(), node2.asExpr())
8282
}
83+
84+
/**
85+
* A method call to `java.io.File::setReadable`.
86+
*/
87+
private class FileSetRedableMethodAccess extends MethodAccess {
88+
FileSetRedableMethodAccess() {
89+
exists(Method m | this.getMethod() = m |
90+
m.getDeclaringType() instanceof TypeFile and
91+
m.hasName("setReadable")
92+
)
93+
}
94+
95+
predicate isCallWithArguments(boolean arg1, boolean arg2) {
96+
this.isCallWithArgument(0, arg1) and this.isCallToSecondArgumentWithValue(arg2)
97+
}
98+
99+
private predicate isCallToSecondArgumentWithValue(boolean value) {
100+
this.getMethod().getNumberOfParameters() = 1 and value = true
101+
or
102+
isCallWithArgument(1, value)
103+
}
104+
105+
private predicate isCallWithArgument(int index, boolean arg) {
106+
DataFlow::localExprFlow(any(CompileTimeConstantExpr e | e.getBooleanValue() = arg),
107+
this.getArgument(index))
108+
}
109+
}
110+
111+
/**
112+
* Hold's if temporary directory's use is protected if there is an explicit call to
113+
* `setReadable(false, false)`, then `setRedabale(true, true)`.
114+
*/
115+
predicate isPermissionsProtectedTempDirUse(DataFlow::Node sink) {
116+
exists(FileSetRedableMethodAccess setReadable1, FileSetRedableMethodAccess setReadable2 |
117+
setReadable1.isCallWithArguments(false, false) and
118+
setReadable2.isCallWithArguments(true, true)
119+
|
120+
exists(DataFlow::Node setReadableNode1, DataFlow::Node setReadableNode2 |
121+
setReadableNode1.asExpr() = setReadable1.getQualifier() and
122+
setReadableNode2.asExpr() = setReadable2.getQualifier()
123+
|
124+
DataFlow::localFlow(sink, setReadableNode1) and // Flow from sink to setReadable(false, false)
125+
DataFlow::localFlow(sink, setReadableNode2) and // Flow from sink to setReadable(true, true)
126+
DataFlow::localFlow(setReadableNode1, setReadableNode2) // Flow from setReadable(false, false) to setReadable(true, true)
127+
)
128+
)
129+
}

java/ql/test/query-tests/security/CWE-200/semmle/tests/Test.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,4 +263,10 @@ void vulnerableFileCreateDirectories() throws IOException {
263263
// TO MAKE SAFE REWRITE TO:
264264
Files.createDirectories(tempDirChild.toPath(), PosixFilePermissions.asFileAttribute(EnumSet.of(PosixFilePermission.OWNER_READ, PosixFilePermission.OWNER_WRITE)));
265265
}
266+
267+
void safeFileCreationWithPermissions() throws IOException {
268+
File tempFile = File.createTempFile("temp", "file.txt");
269+
tempFile.setReadable(false, false);
270+
tempFile.setReadable(true, true);
271+
}
266272
}

0 commit comments

Comments
 (0)