You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 16 Next »

Many filesystems provide access to their files to multiple users, and not all of the users are trustworthy. These filesystems generally use a privileges and permissions system to prevent untrusted users from accessing sensitive files. When a new file is created, the access permissions of the file immediately dictate who may access or operate on the file. If a program creates a file with insufficiently restrictive access permissions, an attacker may read or modify the file before the program is able modify the permissions. Consequently, any file created by a program must be created with access permissions that prevent untrusted users from accessing or modifying the file.

Java provides several methods for creating files. Furthermore, several classes, such as FileOutputStream can create files in their constructors. Prior to Java 1.7, these methods were unable to specify access permissions when creating files. In these cases, the problem of making sure the file is not created with insufficient permissions falls outside the program and must be handled by anyone executing the program.

Java 1.7 new I/O facility (java.nio) provides a rich set of classes for managing file access permissions. Furthermore, many of the methods and constructors that create files accept an argument allowing the program to specify initial permissions of the file. If a file might otherwise be accessable to untrusted users, a Java 1.7 program must create the file with sufficiently restrictive access permissions.

Noncompliant Code Example

The constructors for FileOutputStream and FileWriter do not allow the programmer to explicitly specify file access permissions. This applies to Java 1.7, as well as previous versions of Java.

In this noncompliant code example, if the constructor creates a new file, which is accessible by untrusted users, the access permissions are implementation-defined, and are likely to grant untrusted users the ability to read or modify the file.

Writer out = new FileWriter("file");

Implementation Details (POSIX)

On POSIX systems, the default permissions of a file upon creation are specified by the umask [[Open Group 2004]]. A umask is associated with each process, and is inherited by any processes created by that process. Furthermore, POSIX provides system calls to modify the umask; consequently the umask of a program can not be trusted to be sufficient if the program is invoked by an untrusted user. Unfortunately, Java does not provide any mechanism to access or modify the umask of a Java program, and therefore any Java method or constructor that creates a file without specifying explicit permissions will create the file with permissions set by the umask, which may be insufficiently restrictive.

Compliant Solution

Since Java 1.6 and earlier provide no mechanism for specifying default permissions upon file creations, the problem must be solved outside of the Java program. This can be accomplished by using native code and JNI. In POSIX, it can also be done by allowing the Java program to be invoked only via a batch script that set a sufficiently restrictive umask.

Compliant Solution (Java 1.7, POSIX)

The Files.newByteChannel() method allows a file to be created with specific permissions. This method is platform-independent, but the actual permissions are platform-specific. The following compliant solution illustrates sufficiently restrictive permissions for POSIX platforms.

Path file = new File("file").toPath();

// Throw exception rather than overwrite existing file
Set<OpenOption> options = new HashSet<OpenOption>();
options.add(StandardOpenOption.CREATE_NEW);
options.add(StandardOpenOption.APPEND);

// File permissions should be that only user may read/write file
Set<PosixFilePermission> perms = PosixFilePermissions.fromString("rw-------");
FileAttribute<Set<PosixFilePermission>> attr = PosixFilePermissions.asFileAttribute(perms);

try (SeekableByteChannel sbc = Files.newByteChannel(file, options, attr)) {
  // write data
};

Exceptions

FIO03-EX0: If a file is created inside a directory that is both secure and unreadable by untrusted users, then that file may be created with the default access permissions. See FIO07-J. Do not create temporary files in shared directories for the definition of a secure directory. This could be the case if, for example, the entire filesystem is trusted, or is accessible only to trusted users.

FIO03-EX1: Files that do not contain sensitive information need not be created with specific access permissions.

Risk Assessment

The ability to determine if an existing file has been opened or a new file has been created provides greater assurance that a file other than the intended file is not acted upon.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

FIO03-J

medium

probable

high

P4

L3

Automated Detection

TODO

Related Guidelines

CERT C++ Secure Coding Standard: FIO06-CPP. Create files with appropriate access permissions

CERT C Secure Coding Standard: FIO06-C. Create files with appropriate access permissions

MITRE CWE: CWE-279, "Incorrect Execution-Assigned Permissions"

MITRE CWE: CWE-276, "Incorrect Default Permissions"

MITRE CWE: CWE-732, "Incorrect Permission Assignment for Critical Resource"

Bibliography

[[API 2006]]
[[CVE]]
[[J2SE 2011]]
[[OpenBSD]]
[[Open Group 2004]] "The open function," and "The umask function"
[[Viega 2003]] Section 2.7, "Restricting Access Permissions for New Files on UNIX"
[[Dowd 2006]] Chapter 9, "UNIX 1: Privileges and Files"


FIO02-J. Do not assume that read() has filled all the elements of an array      12. Input Output (FIO)      FIO04-J. Do not open non-regular files when accessing regular files

  • No labels