c语言 最短字符串:Android adb setuid提权漏洞的分析|逆向区::逆向分析
来源:百度文库 编辑:中财网 时间:2024/05/05 12:45:11
去年的Android adb setuid提权漏洞被用于各类root刷机,漏洞发现人Sebastian Krahmer公布的利用工具RageAgainstTheCage(rageagainstthecage-arm5.bin)被用于z4root等提权工具、Trojan.Android.Rootcager等恶意代码之中。下面我们来分析这一漏洞的产生原因。
The Android Exploid Crew小组在后来发布了一份PoC代码:rageagainstthecage.c。从这份代码开始着手。
在main(:72)函数中,首先获取了RLIMIT_NPROC的值(:83),这个值是Linux内核中定义的每个用户可以运行的最大进程数。
然后,调用find_adb()函数(:94)来搜索Android系统中adb进程的PID,具体而言,该函数读取每个进程对应的文件的/proc//cmdline,根据其是否等于”/sbin/adb”来判断是否adb进程。
接下来,fork了一个新的进程(:109),父进程退出,而子进程继续。接下来,在113行创建一个管道。
rageagainstthecage.c
代码:复制代码
新建一个进程后,在子进程之中,exploit代码不断地fork()(:125),而新的子进程不断退出,从而产生大量的僵尸进程(占据shell用户的进程数)。最终,进程数达到上限,fork()返回小于0,于是打印当前已经创建多少子进程,并向管道输入一个字符(:131)。
在这里,管道的作用是和(:122)fork出来的父进程同步,该进程在141行read这一管道,因而阻塞直至僵尸进程已经达到上限(:131)。
进一步的,exploit杀掉adb进程,并在系统检测到这一现象并重启一个adb之前,再一次fork(),将前一个adb留下的进程空位占据。最后,在152行,exploit调用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
代码:复制代码
这已经是漏洞修补以后的代码。在漏洞最初被发现时,代码如下:
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手册(man 2 setuid),其中有如下说明:
man 2 setuid
代码:
RETURN 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/syscalls/__setuid.S中定义,最终是一个%eax=$__NR_setuid32,%ebx=uid的int 0×80中断。
因为只是要分析原理,我们不再鏖战于Android,转而看向Linux内核。
在最新的kernel2.6中,setuid()位于kernel/sys.c的682行,其中,在697行,一切正常的情况下,它会调用set_user()来完成用户切换。
set_user()实现于同一文件的587行,其中一部分代码如下:
kernel/sys.c
代码:复制代码
含义很明显,当目标用户的进程数达到上限,那系统就不能再将一个进程分配给它,因而返回-EAGEIN。然后再setuid()中,直接跳过后面的代码,而返回错误。
至此,整个漏洞的原理已经分析完毕。整理如下:
1、在Android的shell用户下,制造大量的僵尸进程,直至达到shell用户的进程数上限RLIMIT_NPROC;
2、kill当前系统中的adb进程,并再次占据其进程位置以保持达到上限;
3、系统会在一段时间后重启一个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下的安全问题,很多并非全新的,而且个人判断将来还会有大量漏洞、恶意代码产生于传统思路,而作用于新的平台。面对这一新的平台,我们是否能抢先于攻击者做好防范准备,是一个需要我们思考和实践的问题。
The Android Exploid Crew小组在后来发布了一份PoC代码:rageagainstthecage.c。从这份代码开始着手。
在main(:72)函数中,首先获取了RLIMIT_NPROC的值(:83),这个值是Linux内核中定义的每个用户可以运行的最大进程数。
然后,调用find_adb()函数(:94)来搜索Android系统中adb进程的PID,具体而言,该函数读取每个进程对应的文件的/proc/
接下来,fork了一个新的进程(:109),父进程退出,而子进程继续。接下来,在113行创建一个管道。
rageagainstthecage.c
代码:复制代码
- if (fork() > 0)
- exit(0);
- setsid();
- pipe(pepe);[/coe]
- 重头戏发生在下面的122到138行,代码如下:
- rageagainstthecage.c
- 代码:[code]
- if (fork() == 0) {
- close(pepe[0]);
- for (;;) {
- if ((p = fork()) == 0) {
- exit(0);
- } else if (p < 0) {
- if (new_pids) {
- printf("\n[+] Forked %d childs.\n", pids);
- new_pids = 0;
- write(pepe[1], &c, 1);
- close(pepe[1]);
- }
- } else {
- ++pids;
- }
- }
- }
新建一个进程后,在子进程之中,exploit代码不断地fork()(:125),而新的子进程不断退出,从而产生大量的僵尸进程(占据shell用户的进程数)。最终,进程数达到上限,fork()返回小于0,于是打印当前已经创建多少子进程,并向管道输入一个字符(:131)。
在这里,管道的作用是和(:122)fork出来的父进程同步,该进程在141行read这一管道,因而阻塞直至僵尸进程已经达到上限(:131)。
进一步的,exploit杀掉adb进程,并在系统检测到这一现象并重启一个adb之前,再一次fork(),将前一个adb留下的进程空位占据。最后,在152行,exploit调用wait_for_root_adb(),等待系统重启一个adb,这个新建的adb就会具有root权限。
为什么在shell用户的进程数达到上限RLIMIT_NPROC以后,新建的adb会具有root权限?我们来看adb的源码。
在
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手册(man 2 setuid),其中有如下说明:
man 2 setuid
代码:
RETURN 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()定义于
因为只是要分析原理,我们不再鏖战于Android,转而看向Linux内核。
在最新的kernel2.6中,setuid()位于kernel/sys.c的682行,其中,在697行,一切正常的情况下,它会调用set_user()来完成用户切换。
set_user()实现于同一文件的587行,其中一部分代码如下:
kernel/sys.c
代码:复制代码
- 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用户的进程数上限RLIMIT_NPROC;
2、kill当前系统中的adb进程,并再次占据其进程位置以保持达到上限;
3、系统会在一段时间后重启一个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下的安全问题,很多并非全新的,而且个人判断将来还会有大量漏洞、恶意代码产生于传统思路,而作用于新的平台。面对这一新的平台,我们是否能抢先于攻击者做好防范准备,是一个需要我们思考和实践的问题。
paranoid android中文歌词
radiohead 的 Paranoid Android 中文翻译
adb.exe是什么进程
Trojan.Spy.Agent.adb Trojan.Spy.Agent.xx Trojan.Spy.Agent.adb Trojan.Spy.Agent.adb 如何杀
Trojan.DL.VB.adb是什么病毒?
进程里的adb.exe是什么东西
Trojan.spy.agent.adb这个病毒为什么总杀不掉???
acid android的menbers除了yuki外谁可以给我介绍一下?
哪里可以下到acid android的歌恳求拜托了我要疯了!!!!
请叫高手,帮我连下数据库,想把save.asp与message.adb库的m.adb表连接?
请问高手为什么我的数据库不能插入记录啊?想把save.asp与message.adb库的m.adb表连接,代码如下
波导E868支持ADB格式铃声,请帮忙告诉我到哪里下载呀?谢谢了!
Trojan.Spy.Agent.adb 我中了这样的病毒现在怎么办啊!杀不掉啊!
矩形ABCD中,BD=2AB求角ADB的度数,若AD=3,求S矩形ABCD
在ΔABC中,AD平分<BAC,BD=CD。证ΔADB全等于ΔADC
在RT三角形ABC中,角BAC是直角,AB=AC,AD=DC,AE垂直于BD于N.求证:角ADB=角CDF
在三角形ABC中,AD平分角BAC,角C等于角DAC,角ADB等于84度,则角B等于多少度?
在RtΔABC中,锐角A的平分线与锐角B的邻补角的平分线相交于点D,求证:∠ADB=45°
在Rt△ABC中,锐角A的角平分线与锐角B的邻补角的平分线相交与点D,则∠ADB=?
在Rt△ABC中,锐角A的角平分线与锐角B的邻补角的平分线相交与点D,则∠ADB=??
梯形的BD平分角ABC,角ADB=角ABD,若角C=70度,求角ADC的度数.
已知:角ABD=角ACD=60度,角ADB=90度-1/2角BDC。求证:三角形ABC是等腰三角形
如图,在四边形ABCD中,BC=BD=CD,∠ADB=90°,COS∠ABD=4/5,求SΔABD:SΔBCD
已知△ABC的BC边上的点,且CD=AB,∠ADB=∠BAD,AE是△ABD的中线,试说明:AC=2AE(过程)