mirror of
https://github.com/github/codeql.git
synced 2025-12-21 03:06:31 +01:00
Merge pull request #10223 from atorralba/atorralba/unsafe-content-resolver
Java: New Android query to detect unsafe content URI resolution
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
import android.content.ContentResolver;
|
||||
import android.net.Uri;
|
||||
|
||||
public class Example extends Activity {
|
||||
public void onCreate() {
|
||||
// BAD: Externally-provided URI directly used in content resolution
|
||||
{
|
||||
ContentResolver contentResolver = getContentResolver();
|
||||
Uri uri = (Uri) getIntent().getParcelableExtra("URI_EXTRA");
|
||||
InputStream is = contentResolver.openInputStream(uri);
|
||||
copyToExternalCache(is);
|
||||
}
|
||||
// BAD: input URI is not normalized, and check can be bypassed with ".." characters
|
||||
{
|
||||
ContentResolver contentResolver = getContentResolver();
|
||||
Uri uri = (Uri) getIntent().getParcelableExtra("URI_EXTRA");
|
||||
String path = uri.getPath();
|
||||
if (path.startsWith("/data"))
|
||||
throw new SecurityException();
|
||||
InputStream is = contentResolver.openInputStream(uri);
|
||||
copyToExternalCache(is);
|
||||
}
|
||||
// GOOD: URI is properly validated to block access to internal files
|
||||
{
|
||||
ContentResolver contentResolver = getContentResolver();
|
||||
Uri uri = (Uri) getIntent().getParcelableExtra("URI_EXTRA");
|
||||
String path = uri.getPath();
|
||||
java.nio.file.Path normalized =
|
||||
java.nio.file.FileSystems.getDefault().getPath(path).normalize();
|
||||
if (normalized.startsWith("/data"))
|
||||
throw new SecurityException();
|
||||
InputStream is = contentResolver.openInputStream(uri);
|
||||
copyToExternalCache(is);
|
||||
}
|
||||
}
|
||||
|
||||
private void copyToExternalCache(InputStream is) {
|
||||
// Reads the contents of is and writes a file in the app's external
|
||||
// cache directory, which can be read publicly by applications in the same device.
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>
|
||||
When an Android application wants to access data in a content provider, it uses the <code>ContentResolver</code>
|
||||
object. <code>ContentResolver</code>s communicate with an instance of a class that implements the
|
||||
<code>ContentProvider</code> interface via URIs with the <code>content://</code> scheme.
|
||||
|
||||
The authority part (the first path segment) of the URI, passed as parameter to the <code>ContentResolver</code>,
|
||||
determines which content provider is contacted for the operation. Specific operations that act on files also
|
||||
support the <code>file://</code> scheme, in which case the local filesystem is queried instead.
|
||||
|
||||
If an external component, like a malicious or compromised application, controls the URI for a
|
||||
<code>ContentResolver</code> operation, it can trick the vulnerable application into accessing its own private
|
||||
files or non-exported content providers. The attacking application might be able to get access to the file by forcing it to be copied to a public directory, like
|
||||
external storage, or tamper with the contents by making the application overwrite the file with unexpected data.
|
||||
</p>
|
||||
</overview>
|
||||
<recommendation>
|
||||
<p>
|
||||
If possible, avoid using externally-provided data to determine the URI for a <code>ContentResolver</code> to use.
|
||||
If that is not an option, validate that the incoming URI can only reference trusted components, like an allow list
|
||||
of content providers and/or applications, or alternatively make sure that the URI does not reference private
|
||||
directories like <code>/data/</code>.
|
||||
</p>
|
||||
</recommendation>
|
||||
<example>
|
||||
<p>
|
||||
This example shows three ways of opening a file using a <code>ContentResolver</code>. In the first case, externally-provided
|
||||
data from an intent is used directly in the file-reading operation. This allows an attacker to provide a URI
|
||||
of the form <code>/data/data/(vulnerable app package)/(private file)</code> to trick the application into reading it and
|
||||
copying it to the external storage. In the second case, an insufficient check is performed on the externally-provided URI, still
|
||||
leaving room for exploitation. In the third case, the URI is correctly validated before being used, making sure it does not reference
|
||||
any internal application files.
|
||||
</p>
|
||||
<sample src="UnsafeContentUriResolution.java" />
|
||||
</example>
|
||||
<references>
|
||||
<li>
|
||||
Android developers:
|
||||
<a href="https://developer.android.com/guide/topics/providers/content-provider-basics">Content provider basics</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://developer.android.com/reference/android/content/ContentResolver">The ContentResolver class</a>
|
||||
</li>
|
||||
</references>
|
||||
</qhelp>
|
||||
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* @name Uncontrolled data used in content resolution
|
||||
* @description Resolving externally-provided content URIs without validation can allow an attacker
|
||||
* to access unexpected resources.
|
||||
* @kind path-problem
|
||||
* @problem.severity warning
|
||||
* @security-severity 7.5
|
||||
* @precision high
|
||||
* @id java/android/unsafe-content-uri-resolution
|
||||
* @tags security
|
||||
* external/cwe/cwe-441
|
||||
* external/cwe/cwe-610
|
||||
*/
|
||||
|
||||
import java
|
||||
import semmle.code.java.security.UnsafeContentUriResolutionQuery
|
||||
import DataFlow::PathGraph
|
||||
|
||||
from DataFlow::PathNode src, DataFlow::PathNode sink
|
||||
where any(UnsafeContentResolutionConf c).hasFlowPath(src, sink)
|
||||
select sink.getNode(), src, sink,
|
||||
"This ContentResolver method that resolves a URI depends on a $@.", src.getNode(),
|
||||
"user-provided value"
|
||||
Reference in New Issue
Block a user