April 17, 2014

Android版CamiAppにおけるContent Providerのアクセス制限不備の脆弱性 (CVE-2014-1986)

CamiAppとは、コクヨS&Tが提供している専用のノートをこのアプリで撮影すると傾きなどを自動で補正してデータ化して管理してくれるアプリ。Android版とiOS版のアプリが提供されているが、Android版でアクセス制限不備の脆弱性が見つかり修正された。重要なことなのでもう一度、現在公開されているバージョンは修正済み

対象バージョンのCamiAppを見てみると、AndroidManifest.xmlは次のようになっている。

<provider android:authorities="jp.co.kokuyost.CamiApp.Data.CamiDBProvider" android:name=".Data.CamiDBProvider"></provider>

provider要素にandroid:exported属性が付いていない。ということは、この属性値はデフォルト値が使用されることになる。

provider要素のandroid:exported属性のデフォルト値は、android:minSdkVersion属性またはandroid:targetSdkVersion属性の値で次のように変わる。

  • android:minSdkVersion属性またはandroid:targetSdkVersion属性の値が16以下の場合、true
  • android:minSdkVersion属性またはandroid:targetSdkVersion属性の値が17以上の場合、false

GoogleのAPI Guidesの該当箇所には次のように記述されている。

The default value is “true” for applications that set either android:minSdkVersion or android:targetSdkVersion to “16” or lower. For applications that set either of these attributes to “17” or higher, the default is “false”.

CamiAppのAndroidManifest.xmlをもう一度確認してみると

<uses-sdk android:minsdkversion="7"></uses-sdk>

このようにandroid:minSdkVersion属性が7となっている。その結果、provider要素のandroid:exported属性のデフォルト値はtrueになる。android:exported属性の値がtrueになるということは、このContentProviderは公開されることになり、他のアプリから自由にアクセスできる。

例えば、次のようなContentProviderに接続してデータを追加するごく普通のコードで、CamiAppにデータを追加する事ができる。

String sURI = "content://jp.co.kokuyost.CamiApp.Data.CamiDBProvider";
ContentValues cVals = new ContentValues();
cVals.put("uuid", "11111111");
cVals.put("title", "ここはタイトル");
cVals.put("comment", "ここはコメント");
getContentResolver().insert(Uri.parse(sURI + "/note"), cVals);

また、同じようにデータを削除するごくごく普通の次のようなコードで、CamiAppのデータを削除できる。

String sURI = "content://jp.co.kokuyost.CamiApp.Data.CamiDBProvider";
getContentResolver().delete(Uri.parse(sURI + "/note_tag"), null, null);
getContentResolver().delete(Uri.parse(sURI + "/note"), null, null);
getContentResolver().delete(Uri.parse(sURI + "/tag"), null, null);

他のアプリと連携してデータのやり取りを行うためにContentProviderを公開しているわけでは無いと思うので、脆弱性だったということになる。

ちなみに修正されたバージョンのCamiAppのAndroidManifest.xmlを確認してみると次のようになっている。

<provider android:authorities="jp.co.kokuyost.CamiApp.Data.CamiDBProvider" android:exported="false" android:name=".Data.CamiDBProvider"></provider>

android:exported属性が付いてfalseが設定されている。結果、ContentProviderは非公開になり他のアプリからアクセス出来ないように修正されていることが確認できる。

しかし、API Level 8以下ではandroid:exported属性が無視され値がfalseでも他のアプリからアクセスできるという話があり、この修正だけでは不十分なような気もする。

ただ、API Level 8以下の環境で実際に使用しているユーザがどれだけいるのかという疑問もあり、検証はしていない。

© 2014-2017 magiauk.