Skip to content

commons-io: org.apache.commons.io.FileUtils::mkdirs vulnerable to directory hijacking vulnerability

High
JLLeitschuh published GHSA-4jxc-934w-gvpr May 26, 2023

Package

maven commons-io:commons-io (Maven)

Affected versions

< 2.12.0

Patched versions

None

Description

Impact

If org.apache.commons.io.FileUtils::mkdirs is used to create a directory in a directory shared between multiple users, and another local user has created the directory with wider permissions, this method will not fail, as it is documented it should.

This can lead to information disclosure, and directory hijacking.

Vulnerability

The org.apache.commons.io.FileUtils::mkdirs is the following:

/**
 * Calls {@link File#mkdirs()} and throws an exception on failure.
 *
 * @param directory the receiver for {@code mkdirs()}, may be null.
 * @return the given file, may be null.
 * @throws IOException if the directory was not created along with all its parent directories.
 * @throws IOException if the given file object is not a directory.
 * @throws SecurityException See {@link File#mkdirs()}.
 * @see File#mkdirs()
 */
private static File mkdirs(final File directory) throws IOException {
    if ((directory != null) && (!directory.mkdirs() && !directory.isDirectory())) {
        throw new IOException("Cannot create directory '" + directory + "'.");
    }
    return directory;
}

In particular, the documented behaviour "Calls {@link File#mkdirs()} and throws an exception on failure." is not guaranteed. If another local user creates the directory prior to the call to org.apache.commons.io.FileUtils::mkdirs, the method will not throw an exception.

This is because (!directory.mkdirs() && !directory.isDirectory()) becomes (!false && !true) becomes (true && false) becomes false which means the documented, guaranteed IOException will not be thrown.

This vulnerability is particularly present if this method is used to create a directory within a temporary directory. On Unix-like systems, the system temporary directory is shared between all users. If an attacker has prior knowledge of the directory that will be created by this method call, they can pre-create this directory with wider permissions giving them the ability to fully manipulate the contents of the directory. An attacker can also block program flow (create a DOS) by pre-creating a directory that will be passed to org.apache.commons.io.FileUtils::mkdirs but do so with restricted permissions that prevent later logic from reading/writing from this directory.

Patches

This vulnerability was not fixed in code. The documentation was updated to reflect the true behaviour of the method.

Workarounds

Don't pass any files to org.apache.commons.io.FileUtils::mkdirs where any parent is shared between multiple users.

References

The documentation was fixed to reflect the current behaviour:

Severity

High

CVSS overall score

This score calculates overall vulnerability severity from 0 to 10 and is based on the Common Vulnerability Scoring System (CVSS).
/ 10

CVSS v3 base metrics

Attack vector
Local
Attack complexity
Low
Privileges required
None
User interaction
None
Scope
Unchanged
Confidentiality
High
Integrity
High
Availability
High

CVSS v3 base metrics

Attack vector: More severe the more the remote (logically and physically) an attacker can be in order to exploit the vulnerability.
Attack complexity: More severe for the least complex attacks.
Privileges required: More severe if no privileges are required.
User interaction: More severe when no user interaction is required.
Scope: More severe when a scope change occurs, e.g. one vulnerable component impacts resources in components beyond its security scope.
Confidentiality: More severe when loss of data confidentiality is highest, measuring the level of data access available to an unauthorized user.
Integrity: More severe when loss of data integrity is the highest, measuring the consequence of data modification possible by an unauthorized user.
Availability: More severe when the loss of impacted component availability is highest.
CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

CVE ID

No known CVE

Credits