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:
Tony Torralba
2022-10-19 11:22:04 +02:00
committed by GitHub
11 changed files with 361 additions and 0 deletions

View File

@@ -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.
}
}

View File

@@ -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>

View File

@@ -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"