Shou Jiao Dance · 2014/12/12 10:37

0 x00 science


Content providers are used to store and retrieve data and make it accessible to all applications. They are the only way to share data between applications; It does not include common storage areas that are accessible to all Android packages. Android loads a lot of content providers for common data types (audio, video, images, personal contact information, and so on). You can see some listed in the Android. provider package. You can also query what data these providers contain. Of course, for some sensitive content providers, permissions must be obtained to read this data.

If you want to expose your own data, you have two options: you can create your own ContentProvider (a ContentProvider subclass) or you can add data to an existing provider, provided that a ContentProvider exists that controls the same type of data and you have read and write permissions.

0x01 Knowledge Points


Reference: developer.android.com/guide/topic…

Content URIs

The Content URI is a URI that identifies the data in a provider. The Content URI contains the symbolic name of the entire provider (its authority) and the name pointing to a table (a path). When you call a client-side method to operate on a table in a provider, the content URI pointing to the table is one of the arguments.

A. The standard prefix indicates that the data is controlled by A content provider. It will not be modified.

B. Permission part of URI; It identifies the content provider. For third-party applications, this should be a full class name (lowercase) to ensure uniqueness. Permissions are declared in the permission attribute of an element:

    <provider name=".TransportationProvider"
      authorities="com.example.transportationprovider"
      . . .  >
Copy the code

C. The path used to determine the request data type. This can be 0 or more section lengths. If the content provider exposes only one data type (for example, only trains), this section can be left out. If the provider exposes several types, including subtypes, it can be multiple segment lengths — for example, provide the four possible values of “land/bus”, “land/train”, “Sea /ship”, and” Sea /submarine”.

D. The ID of the particular record being requested, if any. This is the _ID value of the requested record. If the request is not limited to a single record, the segment and trailing slash are ignored:

    content://com.example.transportationprovider/trains
Copy the code

ContentResolver

The methods of ContentResolver provide basic “CRUD” functionality for storing data

#! java getIContentProvider() Returns the Binder object for this provider. delete(Uri uri, String selection, String[] selectionArgs) -----abstract A request to delete one or more rows. insert(Uri uri, ContentValues values) Implement this to insert a new row. query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) Receives a query request from a client in a local process, and returns a Cursor. update(Uri uri, ContentValues values, String selection, String[] selectionArgs) Update a content URI. openFile(Uri uri, String mode) Open a file blob associated with a content URI.Copy the code

Sql injection

SQL statement stitching

#! String mSelectionClause = "var = "+ mUserInput; mSelectionClause = "var =" + mUserInput;Copy the code

Parameterized query

#! String mSelectionClause = "var =?" ;Copy the code

permissions

The following element requests read permission on the user’s dictionary:

<uses-permission android:name="android.permission.READ_USER_DICTIONARY">
Copy the code

Apply for some permission protectionLevel=” Dangerous”

<uses-permission android:name="com.huawei.dbank.v7.provider.DBank.READ_DATABASE"/>

<permission android:name="com.huawei.dbank.v7.provider.DBank.READ_DATABASE" android:protectionLevel="dangerous"></permission>
Copy the code

android:protectionLevel

Normal: default value. Low risk permission, as long as the application can be used, installation does not need user confirmation.

Dangerous: Permissions such as WRITE_SETTING and SEND_SMS are risky because they can be used to reconfigure devices or incur phone charges. Use this protectionLevel to identify some permissions that users may be concerned about. Android will warn the user about these permissions when installing the program, and the behavior may vary depending on the Android version or the mobile device being installed.

Signature: These permissions are granted only to programs that use the same key as this program to sign.

SignatureOrSystem: Similar to signature, except that programs in the system also need to be qualified to access them. This allows custom Android applications to be granted permissions, and this level of protection helps integrate the system build process.

API

The default default of the exported property is false in api-17 (android4.2) and above.

Contentprovider cannot be declared private in android2.2 (api-8).

<! -- *** POINT 1 *** Do not (Cannot) implement Private Content Provider in Android 2.2 (API Level 8) or earlier. --> <uses-sdk android:minSdkVersion="9" android:targetSdkVersion="17" />Copy the code

The key way to

  • public void addURI (String authority, String path, int code)
  • public static String decode (String s)
  • public ContentResolver getContentResolver()
  • public static Uri parse(String uriString)
  • public ParcelFileDescriptor openFile (Uri uri, String mode)
  • public final Cursor query(Uri uri, String[] projection,String selection, String[] selectionArgs, String sortOrder)
  • public final int update(Uri uri, ContentValues values, String where,String[] selectionArgs)
  • public final int delete(Uri url, String where, String[] selectionArgs)
  • public final Uri insert(Uri url, ContentValues values)

0x02 Content Provider category


In my opinion, private, public and in-house are almost sufficient.

0x03 Security Suggestion


  1. MinSdkVersion not less than 9
  2. Private Content Provider Settings exported= “false” for data not provided to external apps to avoid component exposure.
  3. Use parameterized queries to avoid injection
  4. Internal apps exchange data using Content Provid and set protectionLevel= signature to verify signatures
  5. Exposed Content providers ensure that sensitive data is not stored
  6. Uri.decode() before use ContentProvider.openFile()
  7. Pay attention to permission protection when providing asset files

0x04 Test Method


1. Decomcompile check the androidmanifest.xml (Drozer scan) file to locate whether the Content provider is exported, whether permissions are configured, and determine the authority

#! bash drozer: run app.provider.info -a cn.etouch.ecalendarCopy the code

2, decompilation search path, keyword addURI, hook API dynamic monitoring recommended to use Zjdroid

3, Determine the authority and path according to the business to write POC, use drozer, use the small tool Content Provider Helper, adb shell // do not have the corresponding permission error

#! Bash the adb shell:  adb shell content query --uri <URI> [--user <USER_ID>] [--projection <PROJECTION>] [--where <WHERE>] [--sort <SORT_ORDER>] content query --uri content://settings/secure --projection name:value --where "name='new_setting'" --sort "name ASC" adb shell content insert --uri content://settings/secure --bind name:s:new_setting --bind value:s:new_value adb shell content update --uri content://settings/secure --bind value:s:newer_value --where "name='new_setting'" adb shell content delete --uri content://settings/secure --where "name='new_setting'"Copy the code
#! Bash drozer: run the app. The provider. Query the content: / / a telephony/carriers/preferapn - verticalCopy the code

0 x05 case


Case 1: Direct exposure

  • WooYun: Shenda Youni has your Sensitive information leaked on Android (readable user local messages)
  • WooYun: Sina Weibo Android app local information leakage
  • WooYun: Shanda Qidian reading Android client token and other sensitive user information leakage
  • WooYun: Lax browser restrictions can lead to fraud attacks
  • WooYun: Sogou mobile browser privacy leak and homepage tampering bug in one (requires malicious apps on the phone)
  • WooYun: Coolpad S6 traffic monitoring bypass (stealing traffic is not a problem)
  • WooYun: Coolpad most secure mobile phone S6 notification bar management permission bypass

Case 2: Access by permission

  • WooYun: Sensitive information leaked on Android (readable user local messages)
  • WooYun: The Content Provider component of huawei web disks may leak user information
  • WooYun: Privacy leakage caused by renren client permissions

Case 3: openFile file traversal

  • WooYun: Arbitrary file reading vulnerability of the Content Provider component on the Android client
  • WooYun: Any private file data can be stolen by a local third party
  • WooYun: 58 Android client remote file write vulnerability

Override openFile method

Error # 1:

#! java private static String IMAGE_DIRECTORY = localFile.getAbsolutePath(); public ParcelFileDescriptor openFile(Uri paramUri, String paramString) throws FileNotFoundException { File file = new File(IMAGE_DIRECTORY, paramUri.getLastPathSegment());  return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY); }Copy the code

Error # 2: uri.parse ()

#! java private static String IMAGE_DIRECTORY = localFile.getAbsolutePath(); public ParcelFileDescriptor openFile(Uri paramUri, String paramString) throws FileNotFoundException { File file = new File(IMAGE_DIRECTORY, Uri.parse(paramUri.getLastPathSegment()).getLastPathSegment()); return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY); }Copy the code

POC1:

#! java String target = "content://com.example.android.sdk.imageprovider/data/" + ".. %2F.. %2F.. %2Fdata%2Fdata%2Fcom.example.android.app%2Fshared_prefs%2FExample.xml"; ContentResolver cr = this.getContentResolver(); FileInputStream fis = (FileInputStream)cr.openInputStream(Uri.parse(target)); byte[] buff = new byte[fis.available()]; in.read(buff);Copy the code

POC2: double encode

#! java String target = "content://com.example.android.sdk.imageprovider/data/" + "%252E%252E%252F%252E%252E%252F%252E%252E%252Fdata%252Fdata%252Fcom.example.android.app%252Fshared_prefs%252FExample.xml "; ContentResolver cr = this.getContentResolver(); FileInputStream fis = (FileInputStream)cr.openInputStream(Uri.parse(target)); byte[] buff = new byte[fis.available()]; in.read(buff);Copy the code

Uri.decode()

#! java private static String IMAGE_DIRECTORY = localFile.getAbsolutePath(); public ParcelFileDescriptor openFile(Uri paramUri, String paramString) throws FileNotFoundException { String decodedUriString = Uri.decode(paramUri.toString()); File file = new File(IMAGE_DIRECTORY, Uri.parse(decodedUriString).getLastPathSegment()); if (file.getCanonicalPath().indexOf(localFile.getCanonicalPath()) ! = 0) { throw new IllegalArgumentException(); } return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY); }Copy the code

0 x06 reference


www.securecoding.cert.org/confluence/…

www.jssec.org/dl/android_…

Developer.android.com/intl/zh-cn/…

0x07 Related reading

Zone.wooyun.org/content/150…

drops.wooyun.org/tips/2997