...
File identification is less of an issue if applications maintain their files in secure directories, where they can only be accessed only by the owner of the file and (possibly) by a system administrator (see FIO00-J. Do not operate on files in shared directories).
...
In this noncompliant code example, the programmer attempts to ensure that the file opened for reading is the same as the file previously opened for writing by calling the method isSameFile()
.:
Code Block | ||
---|---|---|
| ||
//Identify a file by its path String filename = "..."; Path file1 = Paths.get(filename); // Open the file for writing BufferedWriter bw = new BufferedWriter( new OutputStreamWriter(Files.newOutputStream(file1))); bw.write(...); // Close the file bw.close(); /* * A race condition here allows for an attacker to switch * out the file for another */ // Reopen the file for reading Path file2 = Paths.get(filename); if (!Files.isSameFile(file1, file2)) { System.out.println("File tampered with"); // Deal withHandle error } BufferedReader br = new BufferedReader( new InputStreamReader(Files.newInputStream(file2))); String line; while ((line = br.readLine()) != null) { System.out.println(line); } // Close the file br.close(); |
...
This compliant solution checks the creation and last modified times of the files to ensure that the file opened for reading is the same file as the file that was written.:
Code Block | ||
---|---|---|
| ||
//Identify a file by its path String filename = "..."; Path file1 = Paths.get(filename); // Open the file for writing BufferedWriter bw = new BufferedWriter( new OutputStreamWriter(Files.newOutputStream(file1))); bw.write(...); // Close the file bw.close(); /* * A race condition here allows for an attacker to switch * out the file for another */ // Reopen the file for reading Path file2 = Paths.get(filename); BasicFileAttributes attr1 = Files.readAttributes(file1, BasicFileAttributes.class); BasicFileAttributes attr2 = Files.readAttributes(file2, BasicFileAttributes.class); FileTime creation1 = attr1.creationTime(); FileTime modified1 = attr1.lastModifiedTime(); FileTime creation2 = attr2.creationTime(); FileTime modified2 = attr2.lastModifiedTime(); if ( (!creation1.equals(creation2)) || (!modified1.equals(modified2)) ) { System.out.println("File tampered with"); // Deal withHandle error } BufferedReader br = new BufferedReader( new InputStreamReader(Files.newInputStream(file2))); String line; while ((line = br.readLine()) != null) { System.out.println(line); } // Close the file br.close(); |
...
In environments that support the fileKey
attribute, a more reliable approach is to check that the fileKey
attributes of the two files are the same, as shown in this compliant solution.:
Code Block | ||
---|---|---|
| ||
//Identify a file by its path String filename = "..."; Path file1 = Paths.get(filename); // Open the file for writing BufferedWriter bw = new BufferedWriter( new OutputStreamWriter(Files.newOutputStream(file1))); bw.write(...); // Close the file bw.close(); /* * A race condition here allows for an attacker to switch * out the file for another */ // Reopen the file for reading Path file2 = Paths.get(filename); BasicFileAttributes attr1 = Files.readAttributes(file1, BasicFileAttributes.class); BasicFileAttributes attr2 = Files.readAttributes(file2, BasicFileAttributes.class); Object key1 = attr1.fileKey(); Object key2 = attr2.fileKey(); if ( !key1.equals(key2) ) { System.out.println("File tampered with"); // DealHandle with error } BufferedReader br = new BufferedReader( new InputStreamReader(Files.newInputStream(file2))); String line; while ((line = br.readLine()) != null) { System.out.println(line); } // Close the file br.close(); |
...
Bibliography
...