Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: added that filekey() attribute only available on POSIX

...

This code is still vulnerable to a time-of-check, time-of-use (TOCTOU) race condition. For example, an attacker can replace the regular file with a file link or device file after the code has completed its checks but before it opens the file.

Noncompliant Code Example (POSIX, Java SE 7: Check-Use-Check)

This noncompliant code example performs the necessary checks and then opens the file. After opening the file, it performs a second check to make sure that the file has not been moved and that the file opened is the same file that was checked. This reduces the chance that an attacker has changed the file between checking and then opening the file. In both checks, the file's fileKey attribute is examined. This serves as a unique key for identifying files and is a more reliable indicator of the file's identity than its path name.

...

Returns an object that uniquely identifies the given file, or null if a file key is not available. On some platforms or file systems it is possible to use an identifier, or a combination of identifiers to uniquely identify a file. Such identifiers are important for operations such as file tree traversal in file systems that support symbolic links or file systems that allow a file to be an entry in more than one directory. On UNIX file systems, for example, the device ID and inode are commonly used for such purposes.

The file key returned by this method can only be guaranteed to be unique if the file system and files remain static. Whether a file system re-uses identifiers after a file is deleted is implementation dependent and consequently unspecified.

File keys returned by this method can be compared for equality and are suitable for use in collections. If the file system and files remain static, and two files are the same with non-null file keys, then their file keys are equal.

As noted in the documentation, the FileKey cannot be used if it is not available. The fileKey() method returns null on Windows. Consequently this solution is only available on POSIX systems (actually any systems where fileKey() does not return null).

Code Block
bgColor#ffcccc
String filename = /* provided by user */;
Path path = new File(filename).toPath();
try {
  BasicFileAttributes attr = Files.readAttributes(
      path, BasicFileAttributes.class, LinkOption.NOFOLLOW_LINKS);
  Object fileKey = attr.fileKey();

  // Check
  if (!attr.isRegularFile()) {
    System.out.println("Not a regular file");
    return;
  }
  // other necessary checks

  // Use
  try (InputStream in = Files.newInputStream(path)) {

    // Check
    BasicFileAttributes attr2 = Files.readAttributes(
        path, BasicFileAttributes.class, LinkOption.NOFOLLOW_LINKS
    );
    Object fileKey2 = attr2.fileKey();
    if (!fileKey.equals(fileKey2)) {
      System.out.println("File has been tampered with");
    }

    // read file
  };
} catch (IOException x) {
  // handle error
}

...

<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="6eb3afc3898c3510-003f4f52-4940433c-b1089880-a2a570be0d1fa1f193292cae"><ac:plain-text-body><![CDATA[

[[API 2006

AA. References#API 06]]

Class File, methods createTempFile, delete, deleteOnExit

]]></ac:plain-text-body></ac:structured-macro>

<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="65719424126b1e5b-179251fb-41a64e66-b63e967f-23dd08400420566ecb451168"><ac:plain-text-body><![CDATA[

[[Darwin 2004

AA. References#Darwin 04]]

11.5, Creating a Transient File

]]></ac:plain-text-body></ac:structured-macro>

<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="ddcad7b529f535b0-d34568f3-40044bd9-9e1aa122-caf6d236bb119ba580c7b47a"><ac:plain-text-body><![CDATA[

[[Garfinkel 1996

AA. References#Garfinkel 96]]

Section 5.6, Device Files

]]></ac:plain-text-body></ac:structured-macro>

<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="6f3965378e4157f0-4759bdab-415541dd-81138d64-cfdbe48d45038218aa236c29"><ac:plain-text-body><![CDATA[

[[Howard 2002

AA. References#Howard 02]]

Chapter 11, Canonical Representation Issues

]]></ac:plain-text-body></ac:structured-macro>

<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="8fbaf9778bea3d02-bd07994b-48f64511-a3ad81bf-bc34c3ad346a098761714c1e"><ac:plain-text-body><![CDATA[

[[J2SE 2011

AA. References#J2SE 11]]

The try-with-resources Statement

]]></ac:plain-text-body></ac:structured-macro>

<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="f4f638ace9a36685-08f01e0e-4f154abe-8753bfb7-0f6d35ce2e8b4078be237578"><ac:plain-text-body><![CDATA[

[[Open Group 2004

AA. References#Open Group 04]]

[open()

http://www.opengroup.org/onlinepubs/009695399/functions/open.html]

]]></ac:plain-text-body></ac:structured-macro>

<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="5ed76ac48f030d46-05494602-421f4b3c-9e9dbdfe-3b5e3fcf44147353d00f7951"><ac:plain-text-body><![CDATA[

[[SDN 2008

AA. References#SDN 08]]

Bug IDs 4171239, 4405521, 4635827, 4631820

]]></ac:plain-text-body></ac:structured-macro>

<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="60de4cf7a1b851f2-07fb3c63-45b0402c-962b9033-a1d9940ceab059df693dec3c"><ac:plain-text-body><![CDATA[

[[Secunia 2008

AA. References#Secunia 08]]

[Secunia Advisory 20132

http://secunia.com/advisories/20132/]

]]></ac:plain-text-body></ac:structured-macro>

...