Android adb setuidの権利ホールの分析(転)

5619 ワード

原文:http://blog.claudxiao.net/2011/04/android-adb-setuid/
昨年のAndroid adb setuidは、様々なrootブラシに使用されており、脆弱性発見者Sebastian Krahmerが公表した利用ツールRageAgainstThe Cageは、z 4 rootなどの権利主張ツール、Trojan.Android.Rootcagerなどの悪意あるコードに使用されています。この脆弱性の発生原因を分析します。
The Android Exploid Crewグループは、ポストPoCコード:ragegainstthecage.c.をリリースしました。このコードから始めます。
main(:72)関数では、まずRLIMIT_を取得しました。NPROCの値(:83)は、Linuxカーネルで定義されているユーザごとに実行できる最大プロセス数です。
そして、find_を呼び出しますadb()関数(:94)は、AndroidシステムにおけるadbプロセスのPIDを検索し、具体的には、各プロセスに対応するファイルの/proc/cmdlineを読み取り、これが「/sbin/adb」に等しいかどうかを判断する。
続いて、forkは新しいプロセス(109)を行い、親プロセスは終了し、子プロセスは続く。次に、113行にパイプを作成します。
ragegainstthe cage.cif(fork() > 0)    exit(0);  setsid();pipe(pepe);マンダリンは下記の122から138行で発生します。コードは以下の通りです。
ragegainstthe cage.cif(fork() == 0) {    close(pepe[0]);    for(;;) {        if((p = fork()) == 0) {            exit(0);        } elseif(p < 0) {            if(new_pids) {                printf("
[+] Forked %d childs.
"
, pids);                new_pids = 0;                write(pepe[1], &c, 1);                close(pepe[1]);            }        } else{            ++pids;        }    }}新しいプロセスを作成した後、サブプロセスの中で、exploidコードは絶えずfork(:125)しますが、新しいサブプロセスはどんどん終了して、大量のゾンビプロセス(shellユーザを占有するプロセス数)が発生します。最終的にプロセス数が上限に達し、fork()は0以下に戻り、現在どれぐらいのサブプロセスが作成されているかを印刷して、パイプに文字を入力します。
ここでは、パイプラインの役割は、(122)forkからの親プロセスと同期しており、このプロセスは141行のreadであるため、ゾンビプロセスが上限に達しているまでブロックされる(131)。
さらに、exploidはadbプロセスを殺し、システムがこの現象を検出して、adbを再起動する前に、もう一度fork()して、前のadbが残したプロセスの空き領域を占有する。最後に、152行で、exploilはwait_を呼び出します。for_root_adb()は、システムが一つのadbを再起動するのを待つと、この新しいadbはroot権限を持つ。
なぜshellユーザーのプロセス数が上限のRLIMIT_に達したのですか?NPROC以降は、新規のadbにroot権限がありますか?私たちはadbのソースコードを見に来ました。
system/core/adb/adb.cの918行目には、下記のコードが見られます。
android_src/system/core/adb/adb.c/* then switch user and group to "shell" */if(setgid(AID_SHELL) != 0) {    exit(1);}if(setuid(AID_SHELL) != 0) {    exit(1);}これは既に手抜かり補修後のコードです。脆弱性が最初に発見された場合、コードは以下の通りです。
android_src/system/core/adb/adb.c/* then switch user and group to "shell" */setgid(AID_SHELL);setuid(AID_SHELL);簡単に言えば、setuid()関数の戻り値は確認されていませんでした。実際には、この前に、adb.cのコードは全部root権限で実行され、部分初期化作業を完了します。この行では、setuid()を呼び出してユーザーをrootからshellに切り替えるが、setuid()ではshellユーザープロセス数が上限RLIMIT_に達している。NPROCの場合、失敗しますので、adb.cは引き続きrootとして動作します。エラーはありません。
私たちはsetuid()のまんがマニュアル(man 2 setuid)を見にきましたが、その中には以下のような説明があります。
マン2 setuidRETURN VALUE       On  success,  zero is returned.  On error, -1 is returned, and errno is       set appropriately.  ERRORS       EAGAIN The uid does not match the current uid and  uid  brings  process              over its RLIMIT_NPROC resource limit.setuidはエラーが発生する可能性があり、uidでのプロセス数がRLIMIT_を超えることが見られます。NPROC限界時に、EAGAINエラーが発生します。
Androidのソースコードの中で、setuid()は/bionic/libc/unistd/setuid.cと定義されていますが、実際には外部の記号を引用しています。setuid、この記号は/bionic/libc/arch_xxx/sysscalls/_usetuid.Sで定義されていますが、最終的には%eax=$uNR_セットID 32,%ebx=uidのint 0×80中断します
原理を分析するだけなので、私たちはAndroidでの苦闘をやめて、Linuxカーネルを見ます。
最新のケネル2.6で、setuid()はケネル/sys.ccの682行にあります。そのうち、697行で、すべて正常な場合、set_を呼び出します。ユーザー切り替えを完了するためにuser()を使用します。
setuser()は同じファイルの587行に実装され、その一部のコードは以下の通りである。
ケネル/sys.if(atomic_read(&new_user->processes) >= rlimit(RLIMIT_NPROC) &&        new_user != INIT_USER) {    free_uid(new_user);    return-EAGAIN;}目標ユーザーのプロセス数が上限に達したら、システムはもう一つのプロセスを割り当てられなくなり、したがって-EAGEINに戻るという意味がはっきりしています。そしてsetuid()では、後のコードをそのままスキップしてエラーを返します。
この時点で、全体の脆弱性の原理は分析されました。整理は以下の通りです
1、Androidのshellユーザーの下で、shellユーザのプロセス数が上限に達するまで大量のゾンビプロセスを作る。NPROC;
2、キル現在のシステムにおけるadbプロセスは、再びそのプロセス位置を占めて上限を保持する。
3、システムはしばらくの時間後に1つのadbプロセスを再起動します。このプロセスは最初はrootユーザーで、少量の初期化作業を完了した後、setuid()を呼び出してshellユーザーに切り替えます。
4、この時点でshellユーザのプロセス数は上限に達していますので、setuid()は失敗して-1に戻り、ユーザの変更が完了していません。adbはまだroot権限です。
5、adbはsetuid()の戻り値を確認せず、後続の作業を継続しているため、root権限を持つadbプロセスが発生し、ユーザーとの次のステップの対話に利用できる。
実際に、setuidはターゲットユーザーのプロセス数でRLIMIT_に達しています。NPROCの限界時にはエラーを返します。この問題が発生する可能性のある安全上の潜在的な危険は早くて2000年までさかのぼります。2006年には、この符号化問題を本格的に利用する穴が開いた(CVE-2006-2607)。
したがって、これは全く新しい抜け穴ではない。私たちはいくつかの結論を出すことができます。
1、関数の戻り値はいつも無視されているオブジェクトです。getuid()は永遠に失敗しないので、プログラマはsetuid()も失敗しないと思うかもしれません。少なくとも遭遇したことがないので、戻り値のチェックを無視しました。システム関数の呼び出しが失敗するかどうかをチェックするのは常識ですが、また面倒くさいことです。手間を省くために無視すれば問題が発生する可能性があります。
2、Androidにおける安全問題の多くは、全く新しいものではなく、個人的には将来にも多くの脆弱性や悪意のあるコードが伝統的な考え方から生まれ、新しいプラットフォームに作用すると判断しています。この新しいプラットフォームに直面して、攻撃者より先に攻撃者を先にして予防準備をすることができますか?
転載先:https://www.cnblogs.com/tingzi/archive/2012/08/29/2662426.html