Android adb setuid提权漏洞

去年的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/<pid>/cmdline,根据其是否等于”/sbin/adb”来判断是否adb进程。

接下来,fork了一个新的进程(:109),父进程退出,而子进程继续。接下来,在113行创建一个管道。

if

(fork() > 0)

    exit(0);

 

setsid();

pipe(pepe);

重头戏发生在下面的122到138行,代码如下:

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的第918行,我们可以看到如下代码:

/*
then switch user and group to "shell" */

if

(setgid(AID_SHELL) != 0) {

    exit(1);

}

if

(setuid(AID_SHELL) != 0) {

    exit(1);

}

这已经是漏洞修补以后的代码。在漏洞最初被发现时,代码如下:

/*
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),其中有如下说明:

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_src>/bionic/libc/unistd/setuid.c,实际上引用了一个外部符号__setuid,这个符号在<android_src>/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行,其中一部分代码如下:

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下的安全问题,很多并非全新的,而且个人判断将来还会有大量漏洞、恶意代码产生于传统思路,而作用于新的平台。面对这一新的平台,我们是否能抢先于攻击者做好防范准备,是一个需要我们思考和实践的问题。

时间: 2024-11-08 19:09:45

Android adb setuid提权漏洞的相关文章

Android提权漏洞CVE-2014-7920&amp;CVE-2014-7921分析

 Android提权漏洞CVE-2014-7920&CVE-2014-7921分析 没羽@阿里聚安全 这是Android mediaserver的提权漏洞,利用CVE-2014-7920和CVE-2014-7921实现提权,从0权限提到media权限,其中CVE-2014-7921影响Android 4.0.3及以后的版本,CVE-2014-7920影响Android 2.2及以后的版本.Google直到Android5.1才修复这2个漏洞.该漏洞[1]披露过程如下: 2016年1月24日漏洞作

CVE-2017-7494紧急预警:Samba蠕虫级提权漏洞,攻击代码已在网上扩散

本文讲的是CVE-2017-7494紧急预警:Samba蠕虫级提权漏洞,攻击代码已在网上扩散,昨天晚上,开源软件Samba官方发布安全公告,称刚刚修复了软件内一个已有七年之久的严重漏洞(CVE-2017-7494),可允许攻击者远程控制受影响的Linux和Unix机器. Samba是什么 Samba是计算设备的基石级协议SMB的开源实现,被广泛应用在Linux.Unix.IBM System 390.OpenVMS等各类操作系统中,提供文件共享和打印服务. 漏洞影响范围 自2010年3月1日后发

本月补丁星期二活动已修复Google发现的Windows 10提权漏洞

在本月的补丁星期二活动中,微软如约修复了此前Google公开的安全漏洞.在本月活动中,该漏洞补丁被标记为"重要",主要内容为修复了多个提权漏洞,此外还公布了6个关键级别漏洞和8个其他"重要"级别漏洞,包括IE浏览器和Edge浏览器的累积更新. Windows部门总负责人Myerson承认来自Google的两名安全研究人员找到该漏洞,不过Windows 10周年更新用户不受这个缺陷影响.此外他还表示俄罗斯黑客团队Strontium已经利用Google公开的漏洞对特定目

Debian Ubuntu Root权限受到威胁 Tomcat本地提权漏洞CVE-2016-1240 请安全运维尽快升级

2016年9月30日,legalhackers.com网站发布了一个关于Tomcat漏洞的公告,所涉及漏洞的编号为CVE-2016-1240.Debian系统的Linux上管理员通常利用apt-get进行包管理,debian包的一个初始化脚本中存在漏洞,会让deb包安装程序自动执行启动脚本,脚本位置/etc/init.d/tomcatN 攻击者可以在拥有Tomcat低权限的情况下,利用该漏洞获得系统的root权限.受影响的系统包括Debian和ubuntu,其他使用debian包的系统也可能会受

关于Tomcat本地提权漏洞情况的通报

本文讲的是关于Tomcat本地提权漏洞情况的通报,近日,互联网上披露了关于Tomcat启动脚本存在本地提权漏洞(CNNVD-201609-410)的情况.在基于deb安装格式的操作系统(如Debian.Ubuntu等)下,使用Tomcat安装包生成的初始化脚本存在此漏洞,具有普通用户权限的攻击者可利用该漏洞修改主机任意文件,在Tomcat重启后可进一步提升权限至超级管理员以完全控制服务器.目前,相关操作系统厂商已修复该漏洞. 一.漏洞简介 Apache Tomcat是美国阿帕奇(Apache)软

绿盟科技发布Linux内核本地提权漏洞威胁预警通告 这个漏洞9年才被修复

Linux内核出现本地提权漏洞 CVE-2016-5195 事件引发业界关注.绿盟科技发布Linux内核本地提权漏洞威胁预警通告,通告将该漏洞定义为中级,这意味着该漏洞影响范围可控,危害程度可控,利用难度较高,绿盟科技将实施7*8小时内部应急跟踪,72小时内完成技术分析.产品升级和防护方案. 通告全文如下 Linux内核的内存子系统在处理写时拷贝(Copy-on-Write,缩写为COW)时存在条件竞争漏洞,导致可以破坏私有只读内存映射.一个低权限的本地用户能够利用此漏洞获取其他只读内存映射的写

绿盟科技网络安全威胁周报2017.08 关注Linux本地提权漏洞 CVE-2017-6074

绿盟科技发布了本周安全通告,周报编号NSFOCUS-17-08,绿盟科技漏洞库本周新增42条,其中高危22条.本次周报建议大家关注 Linux本地提权漏洞 CVE-2017-6074 .目前漏洞修复补丁已出,强烈建议用户对受影响的系统进行更新.. 焦点漏洞 Linux本地提权漏洞 NSFOCUS ID  35977 CVE ID  CVE-2017-6074 受影响版本 Redhat.Debian.OpenSUSE和Ubuntu等主流Linux发行版本 漏洞点评 Linux内核的DCCP协议实现

Intel多款产品远程管理技术AMT出现本地及远程提权漏洞CVE-2017-5689 攻击者可以获得高级权限

当地时间5月1日(北京时间5月2日上午),英特尔(Intel)官方发布安全公告,公告表明Intel旗下产品英特尔主动管理技术(AMT),英特尔标准可管理性(ISM)和英特尔小型企业技术版本中的固件版本6.x,7.x,8.x 9.x,10 .x,11.0,11.5和11.6存在提权漏洞,可以使无特权攻击者获取这些产品的高级管理功能权限,CVE编号:CVE-2017-5689. 普通用户基于Intel的PC不受影响. 参考链接: https://www.us-cert.gov/ncas/curren

Xen 修复了一个有7年历史的高危提权漏洞

Xen项目修复了一个有7年历史的高危提权漏洞.该漏洞允许恶意的半虚拟化客户机管理员提升权限,完全控制宿主机系统.使用 Xen保护敏感资源的安全桌面系统Qubes OS的研究人员认为, 它可能是至今发现的影响Xen虚拟化管理系统的最严重bug.在披露漏洞前,Xen项目提前通知了多家使用Xen的云计算服务商,其中包括 Linode和亚马逊AWS,Linode建议用户重启实例,但亚马逊表示不需要重启.今天的云计算服务很少使用Xen的半虚拟化模式,它被认为已经死亡. 文章转载自 开源中国社区[https