By using the
ContentProvider.openFile() method, you can provide a facility for another application to access your application data (file). Depending on the implementation of
ContentProvider, use of the method can lead to a directory traversal vulnerability. Therefore, when exchanging a file through a content provider, the path should be canonicalized before it is used.
This rule is an Android specific instance of IDS01-J. Normalize strings before validating them) and IDS02-J. Canonicalize path names before validating them.
Noncompliant Code Example 1
This noncompliant code example tries to retrieve the last segment from the path
paramUri, which is supposed to denote a file name, by calling
android.net.Uri.getLastPathSegment(). The file is accessed in the pre-configured parent directory
However, when the path is URL encoded, it may denote a file in an unintended directory which is outside of the pre-configured parent directory.
From Android 4.3.0_r2.2, the method
Uri.getPathSegments() internally (see: Cross Reference: Uri.java):
A part of the method
Uri.getPathSegments() is as follows:
Uri.getPathSegments() first acquires a path by calling
getEncoded(), then divides the path into segments using "/" as a separator. Any segment that is encoded will be URL decoded by the
If a path is URL encoded, the separator character will be "%2F" instead of "/" and
getLastPathSegment() may not properly return the last segment of the path, which will be a surprise to the user of the method. Moreover, the design of this API directly enables a directory traversal vulnerability.
Uri.getPathSegments() method decoded a path before making it into segments, the URL encoded path could be properly processed. Unfortunately, this is not the case and users should not pass a path to
Uri.getLastPathSegment() before decoding it.
Noncompliant Code Example 2
This noncompliant code example attempts to fix the first noncompliant code example by calling
Uri.getLastPathSegment() twice. The first call is intended for URL decoding and the second call is to obtain the string the developer wanted.
For example, consider what happens when the following URL encoded strings is passed to the content provider:
The first call of
Uri.getLastPathSegment() will return the following string:
The string is converted to a Uri object by
Uri.parse(), which is passed to the second call of
Uri.getLastPathSegment(). The resulting string will be:
The string is used to create a file object. However, if an attacker could supply a string which cannot be decoded by the first call of the
Uri.getLastPathSegment(), the last path segment may not be retrieved. An attacker can create such a string by using the technique called double encoding:
(See [OWASP 2009] Double Encoding for more information.)
For example, the following double encoded string will circumvent the fix.
The first call of
Uri.getLastPathSegment() will decode "%25" to "%" and return the string:
When this string is passed to the second Uri.getLastPathSegment(), "%2E" and "%2F" will be decoded and the result will be:
which makes directory traversal possible.
As a mitigation to the directory traversal attack in this example, it is not enough to only decode the strings. The decoded path must be checked to make sure that the path is under the intended directory.
Proof of Concept
The following malicious code can exploit the vulnerable application that contains the first noncompliant code example:
Proof of Concept (Double Encoding)
The following malicious code can exploit the vulnerable application that contains the second noncompliant code example:
In the following compliant solution, a path is decoded by
Uri.decode() before use. Also, after the File object is created, the path is canonicalized by calling
File.getCanonicalPath() and checked that it is included in
By using the canonicalized path, directory traversal will be mitigated even when a doubly-encoded path is supplied.
Applications should ensure that any URL received by a content provider is canonicalized to avoid a directory traversal attack.
This rule is special case of IDS01-J. Normalize strings before validating them) and IDS02-J. Canonicalize path names before validating them.
Failing to canonicalize a path received by a content provider may lead to a directory traversal vulnerability which could result in the release of sensitive data or in the malicious corruption of data.
Automatic detection of the receipt of a URL is straightforward. It should also be feasible to automatically check whether the path has been canonicalized. However, if it has not, manual intervention would be required.
- JVN#78601526 GREE for Android vulnerable to directory traversal