AndroidアプリにおけるDBファイルの正しい使い方

CodeZine / 2012年3月29日 14時0分

 AndroidアプリにはSQLiteを使用する方法がいくつか用意されていますが、これらの挙動を十分に理解していないと思わぬ脆弱性を作りこんでしまう可能性があります。本稿ではこのバックグラウンドと正しい使い方のガイドラインを紹介します。

■はじめに

 Androidアプリケーションを作成する上でSQLiteを使用してデータベースを扱うことは多々あります。データの永続化や検索といった処理を容易に実装することができるので、多くのアプリケーションで使用されています。しかし、AndroidにはSQLiteを使用するための方法が以下のようにいくつか用意され、それぞれファイル作成時のパーミッションの挙動が異なっています。

SQLiteDatabase#openOrCreateDatabaseを使用して作成する Context#openOrCreateDatabaseを使用して作成する SQLiteOpenHelperクラスを使用して作成する  もし、開発者がこれら方法の挙動を十分に理解していない場合、知らずのうちに脆弱性を作り込んでしまいます。

 実際に、いくつかのアプリケーションではSQLiteDatabase#openOrCreateDatabaseを起因とするファイルパーミッションに関する脆弱性が発見されています。

 Androidのアプリケーションは、基本的に他のアプリケーションで管理されているファイルにはアクセスできません。しかし、方法によっては他のアプリケーションからもアクセスできるファイルが作成されてしまいます。今回はこれらDBファイルを作成する方法について、それぞれDBファイルのパーミッションはどのようになっているのか、その挙動について解説します。

■SQLiteDatabase#openOrCreateDatabase

 まず、SQLiteDatabase#openOrCreateDatabaseですが、以下のサンプルコードではdatabasesディレクトリ以下にapp.dbというファイル名でDBファイルが作成されます。

SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(new File( "/data/data/" + getContext().getPackageName() + "/databases/", "app.db"), null);
 作成されたDBファイルのパーミッションを確認すると644となっており、他のアプリケーションからもアクセスできるようになっています。では、実際にこのメソッドの内部ではどのようなことが行われているのでしょうか。

 openOrCreateDatabaseメソッドの内部ではopenDatabaseメソッドが呼ばれています。

SQLiteDatabase#openOrCreateDatabaseの中身
/** * Equivalent to openDatabase(path, factory, CREATE_IF_NECESSARY). */ public static SQLiteDatabase openOrCreateDatabase(String path, CursorFactory factory) { return openDatabase(path, factory, CREATE_IF_NECESSARY); } 省略 ... public static SQLiteDatabase openDatabase(String path, CursorFactory factory, int flags) { return openDatabase(path, factory, flags, new DefaultDatabaseErrorHandler()); } 省略 ... public static SQLiteDatabase openDatabase(String path, CursorFactory factory, int flags, DatabaseErrorHandler errorHandler) { SQLiteDatabase sqliteDatabase = openDatabase(path, factory, flags, errorHandler, (short) 0 /* the main connection handle */); 省略 ... private static SQLiteDatabase openDatabase(String path, CursorFactory factory, int flags, DatabaseErrorHandler errorHandler, short connectionNum) { SQLiteDatabase db = new SQLiteDatabase(path, factory, flags, errorHandler, connectionNum); try { if (Log.isLoggable(TAG, Log.DEBUG)) { Log.i(TAG, "opening the db : " + path); } // Open the database. db.dbopen(path, flags); db.setLocale(Locale.getDefault());
 openDatabaseメソッドではネイティブメソッドのdbopenが呼ばれ、その中でSQLiteの関数の一つであるsqlite3_open_v2関数を使用してDBファイルが作成されるようになっています。

android_database_SQLiteDatabase.cppの中身
/* public native void dbopen(String path, int flags, String locale); */ static void dbopen(JNIEnv* env, jobject object, jstring pathString, jint flags) { 省略 ... err = sqlite3_open_v2(path8, &handle, sqliteFlags, NULL); if (err != SQLITE_OK) { LOGE("sqlite3_open_v2(\"%s\", &handle, %d, NULL) failed ", path8, sqliteFlags);
 この付近のコードを確認する限り、作成されるファイルのパーミッションを設定したり変更したりという処理は見当たりません。よってデフォルトのumaskで作成され、その結果、ファイルのパーミッションは644になっているのではないかと推測します。



■関連記事
AndroidアプリにおけるDBファイルの正しい使い方
YOLPで挑戦~「マクドナルドはどこだ」アプリをHTML5で作る!
Google App Engine for JavaでMySQLを使ってみる
YOLPで挑戦~Android向け簡易道のり測定アプリを30分で作る!
OSSのERP「ADempiere」と他のOSSを連携する

■記事全文へ

CodeZine

この記事に関連するニュース

トピックスRSS

ランキング