2011年5月4日水曜日

Android JNI でのファイルの取扱と脆弱性

日本Androidの会 セキュリティ部で私が投稿した内容を纏めます。(^^;

事の発端はSkypeの脆弱性が指摘された件は、SQLiteのパーミッションに問題があったことから始まっています。
#パーミッションが開放されたとしても暗号化されていればまだ良かったのですがね。

「kaito」さんも指摘されていますように、一般的なAndroid APIを利用してファイルを作成する場合には、other権限で読み書きできるパーミッションが付与されることは無いからです。

「kaito」さんの解析成果によりSkype同梱されている「libpcmhost.so」が問題であるとの推測されましたので、JNI側でファイルを作成するとどうなるかを調査しました。

JNI側で一般的な入出力関数である「fopen」「open」の2つを調査しました。ファイルの中身は問題ではありませんので、単なるファイルをopenしcloseすることでファイルを生成させるというものです。ソースサンプルは以下の通り。

#include <stdio.h>
#include <fcntl.h>
#include <jni.h>
#include <android/log.h>

#define DEBUG 1
#if DEBUG
# define DebugLogInfo(...) ((void)__android_log_print(ANDROID_LOG_INFO, "TestOpen", __VA_ARGS__))
#else
# define DebugLogInfo(...) do{}while(0)
#endif

JNIEXPORT jint JNICALL Java_jp_co_anaheim_1eng_MainActivity_testOpen (JNIEnv *env, jobject thiz)
{
//fopen関数は最も一般的
FILE *fp;
fp = fopen( "/data/data/jp.co.anaheim_eng/testfile0.txt", "w+" );
if( fp == NULL ) {
DebugLogInfo("File cannot open error.");
return 1;
}
fclose(fp);

//open関数でパーミッションを指定しない状態で実行
int fd;
fd = open("/data/data/jp.co.anaheim_eng/testfile1.txt", O_CREAT | O_RDWR);
if (fd == -1) {
DebugLogInfo("testfile1.txt File cannot open error.");
return 1;
}
close(fd);

//ここは敢えてパーミッションを666に設定している
fd = open("/data/data/jp.co.anaheim_eng/testfile2.txt", O_CREAT | O_RDWR, 0666);
if (fd == -1) {
DebugLogInfo("testfile2.txt File cannot open error.");
return 1;
}
close(fd);

return 0;
}

このソースをJavaから呼び出して見た結果は以下の通り。

エミュレータはこの結果になるが、ひょっとすれば実機なら変わるかも?ってことでAndroid 2.3.3搭載している開発標準端末であるNexus Sで実行してみた。結果は以下の通り。
#ちなみに私のNexus Sはroot化していませんので。


Skypeの脆弱性はパーミッションを意識しない状態というか、AndroidのNativeで作成されるパーミッションを調査しなかっただけなのだろう。解決方法は?というと、open関数であれば適切なパーミッションを付与させれば良い。その他の場合には自分でパーミッションを設定させる命令を追加すれば良いだけ。

#include <sys/stat.h>

//パーミッションとして660に設定した
if (chmod("/data/data/jp.co.anaheim_eng/testfile0.txt", S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP) != 0) {
DebugLogInfo("File cannot change chmod.");
return 1;
}

この処理を追加して実行した結果が以下の通りとなる。


<雑感>
Android NativeであるNDKを利用してファイル操作を行った場合には特にパーミッションを注意しなければならいと思う。因みにUbuntu上でfopenを利用した場合のパーミッションは644になっているので、666のAndroidはややどうかなぁって気はする。
デフォルトパーミッションはJavaと同様に660にして欲しい気もするのだが、最低でも664 or 644になっていることを望みます。

root化された端末では、パーミッションによるセキュリティ担保が出来るということは期待しない方が良いから暗号化等の配慮が必要にはなる。であるとするとJNIで666となるパーミッションの標準もこのままでも良いのかも?って気がしないでもないなぁ。(^^;

0 件のコメント:

コメントを投稿