Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Code Block
bgColor#ccccff
public static boolean isInSecureDir(Path file) {
  return isInSecureDir(file, null);
}
public static boolean isInSecureDir(Path file, UserPrincipal user) {
   return isInSecureDir(file, user, 5);
}

/**
 * Indicates whether file lives in a secure directory relative
 * to the program's user
 * @param file Path to test
 * @param user User to test. If null, defaults to current user
 * @param symlinkDepth Number of symbolic links allowed
 * @return true if file's directory is secure.
 */
public static boolean isInSecureDir(Path file, UserPrincipal user,
                                    int symlinkDepth) {
  if (!file.isAbsolute()) {
    file = file.toAbsolutePath();
  } if (symlinkDepth <=0) {
      // Too many levels of symbolic links
      return false;
    }

  // Get UserPrincipal for specified user and superuser
  FileSystem fileSystem =
      Paths.get(file.getRoot().toString()).getFileSystem();
  UserPrincipalLookupService upls = 
      fileSystem.getUserPrincipalLookupService();
  UserPrincipal root = null;
  try {
    root = upls.lookupPrincipalByName("root");
    if (user == null) {
      user = upls.lookupPrincipalByName(System.getProperty("user.name"));
    }
    if (root == null || user == null) {
      return false;
    }
  } catch (IOException x) {
    return false;
  }

  // If any parent dirs (from root on down) are not secure,
  // dir is not secure
  for (int i = 1; i <= file.getNameCount(); i++) {
    Path partialPath = Paths.get(file.getRoot().toString(),
                                 file.subpath(0, i).toString());

    try {
      if (Files.isSymbolicLink(partialPath)) {
        if (!isInSecureDir(Files.readSymbolicLink(partialPath),)) {
                           user, symlinkDepth - 1)) {
          // Symbolic link, linked-to dir not secure
          return false;
        }
      } else {
        UserPrincipal owner = Files.getOwner(partialPath);
        if (!user.equals(owner) && !root.equals(owner)) {
          // dir owned by someone else, not secure
          return false;
        }
        PosixFileAttributes attr =
            Files.readAttributes(partialPath, PosixFileAttributes.class);
        Set<PosixFilePermission> perms = attr.permissions();
        if (perms.contains(PosixFilePermission.GROUP_WRITE) ||
            perms.contains(PosixFilePermission.OTHERS_WRITE)) {
          // Someone else can write files, not secure
          return false;
        }
      }
    } catch (IOException x) {
      return false;
    }
  }

  return true;
}

...

Performing operations on files in shared directories can result in DoS attacks. If the program has elevated privileges, privilege escalation exploits are possible.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

FIO00-J

Medium

Unlikely

Medium

P4

L3

Related Guidelines

Android Implementation Details

On Android, the SD card ( /sdcard or /mnt/sdcard ) is shared among multiple applications, so sensitive files should not be stored on the SD card (see DRD00-J. Do not store sensitive information on external storage (SD card)).

Bibliography

[API 2014]

Class FileLock
   Methods createTempFile
   Method delete
   Method deleteOnExit

[Darwin 2004]

Section 11.5, "Creating a Transient File"

[Garfinkel 1996]

Section 5.6, "Device Files"

[Howard 2002]

Chapter 11, "Canonical Representation Issues"

[J2SE 2011]

"The try-with-resources Statement"

[JDK Bug 2015]

Bug JDK-4171239
Bug JDK-4405521 
Bug JDK-4631820

[Open Group 2004]

open()

[Secunia 2008]

Secunia Advisory 20132

...


...