[轉]sendpage漏洞分析 CVE-2009-2692
之前看了《新爆内核高危漏洞sock_sendpage的利用分析的讨论 》这篇帖子,在九贱兄和诸位CUer的指引下,大致弄清了整个漏洞的始末。现与大家分享(引用自我的空间 )。
有什么不足之处还望多多指教~ 内核的BUG 这个BUG首先得从sendfile系统调用说起。 而sendfile就将整个发送过程封装在一个系统调用中,避免了多次系统调用,避免了数据在内核空间和用户空间之间的大量拷贝。 ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count); 虽然这个系统调用接收in和out两个fd,但是有所限制,in只能是普通文件,out只能是socket(这个限制不知道后来的内核版本有没有放宽)。 sendfile系统调用在内核里面是怎么实现的呢?这个还是比较复杂,它在内核里面做了原来要在用户态做的事情:创建一个pipe对象作buffer用、从in_fd中读数据到pipe中、将pipe中的数据写到out_fd、循环直到满足结束条件。 sock_sendpage的代码如下: struct socket *sock; 注意,BUG出现了,调用sock->ops->sendpage之前没有判断这个函数指针是否为NULL。 但是,这里的sock->ops->sendpage可能是NULL吗?搜索内核代码可以发现,并不是每一种类型的socket都会实现 sendpage这个函数。但是大多数没有实现这个函数的socket都将这个函数指针设为sock_no_sendpage(这基本上是一个例行公事的 空函数)。但是,有少数类型的socket却没有设置sock->ops->sendpage(没设置,则默认为NULL),如 PF_PPPOX、PF_BLUETOOTH、等等。(上面链接给出的代码就利用了PF_PPPOX,后来我发现,用PF_BLUETOOTH也能达到一 样的效果,而换用PF_INET之类的却不行。) 利用这个BUG 前面我们看到,内核在sendfile系统调用中,没有判断sock->ops->sendpage是否为空,就对它进行调用,并且sock->ops->sendpage的确可能为空。 如果我们的程序中调用一个值为NULL的函数指针,其结果会怎样?自然是程序崩溃,也仅仅就是崩溃而已。那么,这么个东西是怎么被利用,并实现窃取root身份的呢?让我们逐步解读上面链接给出的代码。 char template[] = "/tmp/padlina.XXXXXX"; 经过前面的介绍,我们可以看到,这里的sendfile将在系统调用中触发对0地址的调用。然而,现在0地址上已经被写下了JMP到kernel_code的指令。 现在的处境 进入sendfile系统调用后,CPU进入内核态。内核态能干任何CPU能干的事情,一般情况下,只有内核代码能在内核态下执行,这是由内核来保证的。 但是现在,内核代码调用了0地址的函数,进入了用户代码kernel_code。于是,程序员可以在他们自己写的kernel_code代码中干任何内核 能干的事情。 然而另一方面,内核代码可以轻松地访问内核的数据结构,因为内核代码是在一块编译的,对象的地址都知道、结构都清楚。而现在程序员写在kernel_code里的代码呢?尽管他们拥有与内核代码一样的访问权限,但是却不知道数据的地址和状态,他们现在是个瞎子。 开始干坏事了 kernel_code函数主要分三个步骤: 1、获取task_struct uint *p = get_current(); 其中get_current的代码如下: __asm__ __volatile__ ( 在内核中,每个进程拥有一个thread_info结构,以及内核栈。这两样东西是分配在两个连续的page中的,并且thread_info结构在前, 栈在后。thread_info结构的第一个元素是task,它是一个指向task_struct结构(即通常所说的进程控制块)的指针。在这个 task_struct结构中就保存着进程的主要信息。 2、拿到了task_struct,要干什么呢?示例代码的目标是修改task_struct中记录的用户信息,以使得这个进程变成是由root启动的进程。 for (i = 0; i < 1024-13; i++) { 回想一下,在main函数中已经获取了用户和用户组ID,并设置到了进程中(设置到进程了task_struct结构中)。于是,搜索 task_struct结构,试图匹配这几个ID。因为在不同版本的内核中,这几个ID放置的位置可能不大相同,但它们出现的顺序总是相同的。 不过这种修改uid的方法在较新版本的内核中已经行不通了,uid、gid这些信息已经不是直接放在task_struct结构中,而是整理到一个叫cred的结构,然后task_struct结构保存了指向对应cred结构的指针。 3、回到用户态 __asm__ __volatile__ ( 这段代码就是将返回地址压在内核栈上,然后iret返回用户态。返回地址被指定到exit_code上,这也是和main编译在一起的一个函数。其代码如下: if (getuid() != 0) { 现在程序已经回到用户态了,调用getuid看看是不是已经成了root。确认无洖,启动shell吧~ 问题的点睛 虽然上面的叙述一口气把这个内核漏洞的来龙去脉讲通了,但是有个重要的细节却一笔代过了。那就是映射0地址的部分,我觉得这才是整个攻击代码的点睛之笔。其代码大致如下: if ((personality(0xffffffff)) != PER_SVR4) { 映射0地址,为什么不是直接的mmap,还要有这样的分支语句呢?personality函数和mprotect函数又是什么意思? int main(void) { 可以看到,在执行之前,也调用了personality函数。 linux内核具有很强的兼容性,不仅可以执行linux下编译的可执行文件,还可以执行在其他操作系统下编译的可执行文件:对于windows等一些操 作系统上的可执行文件,linux通过运行于用户态的虚拟机程序(如wine)来运行;而对于某些类unix系统的可执行文件,linux则可以直接执 行。 上面看到的personality函数就是用来设置“执行域”的(默认的执行域就是linux),而上面的启动代码就通过personality函数将进 程的执行域设置为SVR4(一种较老的类unix系统,System V Release 4)。于是,在映射0地址时将走到调用mprotect函数的分支(personality(0xffffffff)表示获取当前的执行域)。 在我的系统上,如果直接在shell上执行exploit程序(走mmap的分支),mmap会失败。因为在32位linux上,进程地址空间是从 0x08048000开始使用的(依次是可执行代码区、全局数据区、堆、文件映射区、栈),从0地址到0x08048000的空间并不能被映射。 exploit程序之所以能够映射0地址,是因为发现了在SVR4这种执行域下,进程能够映射0地址。确切的说,0地址默认是有映射的存在的,代码只是修改了这个映射的属性。 在linux 2.6.29.4的代码中找到了以下一些内容: binfmt_elf.c:load_elf_binary(),在加载elf格式(linux下最常用的格式)的可执行文件时,有如下代码(针对MMAP_PAGE_ZERO 标记做了特殊处理): 看到作者的注释了吧~ 就这样,0地址被映射了。 一篇分析这个内核BUG的paper: |
[轉]sendpage漏洞分析 CVE-2009-2692的更多相关文章
- [轉]udp_sendmsg空指针漏洞分析 by wzt
udp_sendmsg空指针漏洞分析 by wzt 漏洞描述: 由于Linux ipv4协议栈中udp_sendmsg()函数设计上存在缺陷, 导致struct rtable *rt以空指针形式 ...
- 漏洞分析:CVE 2021-3156
漏洞分析:CVE 2021-3156 漏洞简述 漏洞名称:sudo堆溢出本地提权 漏洞编号:CVE-2021-3156 漏洞类型:堆溢出 漏洞影响:本地提权 利用难度:较高 基础权限:需要普通用户权限 ...
- 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作为内核或者是处理流媒体的工具 ...
- FakeID签名漏洞分析及利用(二)
本文转自:http://blog.csdn.net/l173864930/article/details/38409521 继上一次Masterkey漏洞之后,Bluebox在2014年7月30日又公 ...
- Elasticsearch 核心插件Kibana 本地文件包含漏洞分析(CVE-2018-17246)
不久前Elasticsearch发布了最新安全公告, Elasticsearch Kibana 6.4.3之前版本和5.6.13之前版本中的Console插件存在严重的本地文件包含漏洞可导致拒绝服务攻 ...
- ThinkCMF X2.2.2多处SQL注入漏洞分析
1. 漏洞描述 ThinkCMF是一款基于ThinkPHP+MySQL开发的中文内容管理框架,其中X系列基于ThinkPHP 3.2.3开发,最后更新到2.2.2版本.最近刚好在渗透测试 ...
- 看个AV也中招之cve-2010-2553漏洞分析
试想:某一天,你的基友给你了一个视频文件,号称是陈老师拍的苍老师的老师题材的最新电影.avi,你满心欢喜,在确定文件格式确实为avi格式后,愉快的脱下裤子准备欣赏,打开后却发现什么也没有,而随后你的基 ...
随机推荐
- fiddler 暂停抓包
或者点击左下角 capturing
- 前后端分离使用 Token 登录解决方案
前后端分离使用 Token 登录解决方案:https://juejin.im/post/5b7ea1366fb9a01a0b319612
- 重磅!挑战Oracle,华为将开源 GaussDB 数据库
来源:中关村在线,https://dwz.cn/nHNSOTeN 有消息称在正在进行的鲲鹏计算产业论坛上,华为宣布将开源其GaussDB数据库. GaussDB数据库是今年5月15日华为公布的分布式数 ...
- python面试题之请谈谈.pyc文件和.py文件的不同之处
虽然这两种文件均保存字节代码,但.pyc文件是Python文件的编译版本,它有平台无关的字节代码,因此我们可以在任何支持.pyc格式文件的平台上执行它.Python会自动生成它以优化性能(加载时间,而 ...
- 封装一个Js 对象 生成Json
<script src="~/Content/Scripts/jquery-1.11.3.min.js"></script> <script> ...
- dotNET面试(三)
1.简述 private. protected. public. internal 修饰符的访问权限.private : 私有成员, 在类的内部才可以访问 ,也就是类内部的函数等成员可以访问.prot ...
- 轻量级Spring定时任务(Spring-task)
Spring3.0以后自主开发的定时任务工具,spring-task,可以将它比作一个轻量级的Quartz,而且使用起来很简单,除spring相关的包外不需要额外的包,而且支持注解和配置文件两种形式. ...
- Centos 7安装的一些事项
一.Wifi无法连接 ip addr 显示:unmanaged, plugin missing 先连有线网yum install -y NetworkManager-wifi systemctl re ...
- java -jar 中文乱码
java -Dfile.encoding=utf-8 -jar demo.jar 添加编码即可
- mac系统下安装和启动nginx
1.在线安装 localhost:nginx-1.17.1 mhx$ sudo brew install nginx 2.查看是否安装成功 localhost:nginx-1.17.1 mhx$ ng ...