@@ -16,15 +16,16 @@ import DataFlow::PathGraph
1616
1717private class MethodFileSystemFileCreation extends Method {
1818 MethodFileSystemFileCreation ( ) {
19- getDeclaringType ( ) instanceof TypeFile and
20- hasName ( [ "mkdir" , "mkdirs" , "createNewFile" ] )
19+ this . getDeclaringType ( ) instanceof TypeFile and
20+ this . hasName ( [ "mkdir" , "mkdirs" , "createNewFile" ] )
2121 }
2222}
2323
2424abstract private class FileCreationSink extends DataFlow:: Node { }
2525
2626/**
27- * Sink for tainted `File` having a file or directory creation method called on it.
27+ * The qualifier of a call to one of `File`'s file-creating or directory-creating methods,
28+ * treated as a sink by `TempDirSystemGetPropertyToCreateConfig`.
2829 */
2930private class FileFileCreationSink extends FileCreationSink {
3031 FileFileCreationSink ( ) {
@@ -36,7 +37,8 @@ private class FileFileCreationSink extends FileCreationSink {
3637}
3738
3839/**
39- * Sink for if tained File/Path having some `Files` method called on it that creates a file or directory.
40+ * The argument to a call to one of `Files` file-creating or directory-creating methods,
41+ * treated as a sink by `TempDirSystemGetPropertyToCreateConfig`.
4042 */
4143private class FilesFileCreationSink extends FileCreationSink {
4244 FilesFileCreationSink ( ) {
@@ -45,8 +47,8 @@ private class FilesFileCreationSink extends FileCreationSink {
4547}
4648
4749/**
48- * Captures all of the vulnerable methods on `Files` that create files/directories without explicitly
49- * setting the permissions.
50+ * A call to a `Files` method that create files/directories without explicitly
51+ * setting the newly-created file or directory's permissions.
5052 */
5153private class FilesVulnerableCreationMethodAccess extends MethodAccess {
5254 FilesVulnerableCreationMethodAccess ( ) {
@@ -57,13 +59,34 @@ private class FilesVulnerableCreationMethodAccess extends MethodAccess {
5759 m .hasName ( [ "write" , "newBufferedWriter" , "newOutputStream" ] )
5860 or
5961 m .hasName ( [ "createFile" , "createDirectory" , "createDirectories" ] ) and
60- getNumArgument ( ) = 1
62+ this .getNumArgument ( ) = 1
63+ or
64+ m .hasName ( "newByteChannel" ) and
65+ this .getNumArgument ( ) = 2
6166 )
6267 }
6368}
6469
6570/**
66- * A call to `java.io.File::createTempFile` where the the system temp dir sinks to the last argument.
71+ * A call to a `File` method that create files/directories with a specific set of permissions explicitly set.
72+ * We can safely assume that any calls to these methods with explicit `PosixFilePermissions.asFileAttribute`
73+ * contains a certain level of intentionality behind it.
74+ */
75+ private class FilesSanitiznignCreationMethodAccess extends MethodAccess {
76+ FilesSanitiznignCreationMethodAccess ( ) {
77+ exists ( Method m |
78+ m = this .getMethod ( ) and
79+ m .getDeclaringType ( ) .hasQualifiedName ( "java.nio.file" , "Files" )
80+ |
81+ m .hasName ( [ "createFile" , "createDirectory" , "createDirectories" ] ) and
82+ this .getNumArgument ( ) = 2
83+ )
84+ }
85+ }
86+
87+ /**
88+ * The temp directory argument to a call to `java.io.File::createTempFile`,
89+ * treated as a sink by `TempDirSystemGetPropertyToCreateConfig`.
6790 */
6891private class FileCreateTempFileSink extends FileCreationSink {
6992 FileCreateTempFileSink ( ) {
@@ -80,50 +103,73 @@ private class TempDirSystemGetPropertyToCreateConfig extends TaintTracking::Conf
80103 source .asExpr ( ) instanceof MethodAccessSystemGetPropertyTempDirTainted
81104 }
82105
106+ /**
107+ * Find dataflow from the temp directory system property to the `File` constructor.
108+ * Examples:
109+ * - `new File(System.getProperty("java.io.tmpdir"))`
110+ * - `new File(new File(System.getProperty("java.io.tmpdir")), "/child")`
111+ */
83112 override predicate isAdditionalTaintStep ( DataFlow:: Node node1 , DataFlow:: Node node2 ) {
84113 isAdditionalFileTaintStep ( node1 , node2 )
85114 }
86115
87116 override predicate isSink ( DataFlow:: Node sink ) { sink instanceof FileCreationSink }
117+
118+ override predicate isSanitizer ( DataFlow:: Node sanitizer ) {
119+ exists ( FilesSanitiznignCreationMethodAccess sanitisingMethodAccess |
120+ sanitizer .asExpr ( ) = sanitisingMethodAccess .getArgument ( 0 )
121+ )
122+ }
88123}
89124
125+ // Below this, configuration for tracking single-method calls that are vulnerable.
126+ /**
127+ * A MethodAccess against a method that creates a temporary file or directory in a shared temporary directory.
128+ */
90129abstract class MethodAccessInsecureFileCreation extends MethodAccess {
91130 /**
92- * Docstring describing the file system type (ie. file, directory, etc ...) returned .
131+ * Gets the type of entity created (e.g. ` file`, ` directory`, ...).
93132 */
94- abstract string getFileSystemType ( ) ;
133+ abstract string getFileSystemEntityType ( ) ;
95134}
96135
97136/**
98- * Insecure calls to `java.io.File:: createTempFile`.
137+ * An insecure call to `java.io.File. createTempFile`.
99138 */
100139class MethodAccessInsecureFileCreateTempFile extends MethodAccessInsecureFileCreation {
101140 MethodAccessInsecureFileCreateTempFile ( ) {
102141 this .getMethod ( ) instanceof MethodFileCreateTempFile and
103142 (
143+ // `File.createTempFile(string, string)` always uses the default temporary directory
104144 this .getNumArgument ( ) = 2
105145 or
106- // Vulnerablilty exists when the last argument is `null`
107- getArgument ( 2 ) instanceof NullLiteral
146+ // The default temporary directory is used when the last argument of `File.createTempFile(string, string, File)` is `null`
147+ DataFlow :: localExprFlow ( any ( NullLiteral n ) , getArgument ( 2 ) )
108148 )
109149 }
110150
111- override string getFileSystemType ( ) { result = "file" }
151+ override string getFileSystemEntityType ( ) { result = "file" }
112152}
113153
154+ /**
155+ * The `com.google.common.io.Files.createTempDir` method.
156+ */
114157class MethodGuavaFilesCreateTempFile extends Method {
115158 MethodGuavaFilesCreateTempFile ( ) {
116159 getDeclaringType ( ) .hasQualifiedName ( "com.google.common.io" , "Files" ) and
117160 hasName ( "createTempDir" )
118161 }
119162}
120163
164+ /**
165+ * A call to the `com.google.common.io.Files.createTempDir` method.
166+ */
121167class MethodAccessInsecureGuavaFilesCreateTempFile extends MethodAccessInsecureFileCreation {
122168 MethodAccessInsecureGuavaFilesCreateTempFile ( ) {
123169 getMethod ( ) instanceof MethodGuavaFilesCreateTempFile
124170 }
125171
126- override string getFileSystemType ( ) { result = "directory" }
172+ override string getFileSystemEntityType ( ) { result = "directory" }
127173}
128174
129175/**
@@ -157,6 +203,6 @@ where
157203 // Note this message has no "$@" placeholder, so the "system temp directory" template parameter below is not used.
158204 message =
159205 "Local information disclosure vulnerability due to use of " +
160- source .getNode ( ) .asExpr ( ) .( MethodAccessInsecureFileCreation ) .getFileSystemType ( ) +
206+ source .getNode ( ) .asExpr ( ) .( MethodAccessInsecureFileCreation ) .getFileSystemEntityType ( ) +
161207 " readable by other local users."
162208select source .getNode ( ) , source , sink , message , source .getNode ( ) , "system temp directory"
0 commit comments