免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: 独孤九贱
打印 上一主题 下一主题

新爆内核高危漏洞sock_sendpage的利用分析的讨论 [复制链接]

论坛徽章:
0
41 [报告]
发表于 2009-08-20 11:14 |只看该作者

回复 #40 albeta 的帖子

PER_SVR4以及MAP_ZERO了,不用再mmap了,只需要mprotect修改一下权限即可。

论坛徽章:
0
42 [报告]
发表于 2009-08-20 23:55 |只看该作者
我还是有些不明白:
这个代码最关键的是
mmap(0x0, 0x1000, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_ANONYMOUS, 0, 0)

MAP_FIXED的作用就是强行映射到指定的addr的位置。
MAP_ANONYMOUS将忽略 fd和offset参数。

疑问一:

既然没有传入fd,那么到底把哪个文件或者内存映射到了地址0呢?
难道是内核空间的内存?

疑问二:
return sock->ops->sendpage(sock, page, offset, size, flags);
在内核空间执行时应该看到的是进程的全部4G空间。
这个跳转到0地址执行,这个0地址指的是进程的虚拟地址0吗?

如果是进程空间的虚拟地址0,那么为什么不直接在进程的虚拟地址0直接写入jmp指令呢?
到底为什么要作mmap呢?

疑问三:
sock->ops->sendpage
到底在什么情况下是NULL呢?难道内核的sendpage就不能用吗?
还是只有
socket(PF_PPPOX, SOCK_DGRAM, 0)才会导致sendpage指针为NULL呢?

[ 本帖最后由 emmoblin 于 2009-8-21 00:00 编辑 ]

论坛徽章:
0
43 [报告]
发表于 2009-08-21 00:24 |只看该作者

回复 #42 emmoblin 的帖子

1、这里的mmap应该就相当于malloc时,libc做的mmap一样(malloc大块内存的时候),就是把0地址的空间分配给用户;
2、不做mmap的话,虚拟地址空间的0地址是没有分配的,没有对应的vma,缺页异常会导致程序被杀死;
3、sock->ops->sendpage是NULL也是内核BUG之一。不少类型的socket都没有sendfile这个函数,但是它们大多数都会使用sock_no_sendpage来代替一下,并不会留空。但是PF_PPPOX却留的是NULL,我发现PF_BLUETOOTH也是一样的效果,而PF_INET之类的却不行;

论坛徽章:
0
44 [报告]
发表于 2009-08-21 00:38 |只看该作者
谢谢kouu,明白多了。

也就是使用mmap在0地址分配一段空间,然后就可以在此空间写入代码了。

但是这样都行,难道mmap可以随便指定一个地址吗?
比如我指定0x50000000,正好这个地址是有用的,那岂不是破坏了这段内存?
程序还不跑乱了?

[ 本帖最后由 emmoblin 于 2009-8-21 00:49 编辑 ]

论坛徽章:
0
45 [报告]
发表于 2009-08-21 10:19 |只看该作者

回复 #44 emmoblin 的帖子

按我的理解,mmap就是在mm上加一个vma。如果这个vma与现有的vma有重叠,如果其属性一样的话,mmap应该是可以成功的,并且新老两个vma被合并成一个。否则mmap会失败。
另外,mmap的地址参数多数情况下只是个参考,内核不一定map到给定的地址上,实际map的地址会通过返回值给出。但是本例中mmap使用了MAP_FIXED参数,应该就是不允许内核map到其他地址了,map不成功则直接返回失败。

论坛徽章:
0
46 [报告]
发表于 2009-08-21 17:14 |只看该作者
感谢分享。

论坛徽章:
0
47 [报告]
发表于 2009-08-23 10:37 |只看该作者

回复 #45 kouu 的帖子

那我觉得内核mmap的时候应该避免映射到0地址。及时用了FIXED参数。
这样就利用不了NULL跳转到0地址执行的漏洞了

论坛徽章:
0
48 [报告]
发表于 2009-08-23 11:37 |只看该作者
原帖由 emmoblin 于 2009-8-23 10:37 发表
那我觉得内核mmap的时候应该避免映射到0地址。及时用了FIXED参数。
这样就利用不了NULL跳转到0地址执行的漏洞了

原帖由 kouu 于 2009-8-19 14:58 发表
不过我感觉内核应该限制一下对0地址的分配(任何vma都不能包含0地址),因为习惯上很多情况下都把NULL看成是非法的了。


:wink: 同感, 呵呵

论坛徽章:
0
49 [报告]
发表于 2009-08-26 10:07 |只看该作者

回复 #34 bobozhang 的帖子

http://www.milw0rm.com/exploits/9479

milw0rm上的一个exploit中有一段解释,来支持这个观点:
        /*
        ** By calling iret after pushing a register into kernel stack,
        ** We don't have to go back to ring3(user mode) privilege level. dont worry. :-}
        **
        ** kernel_code() function will return to its previous status which means before sendfile() system call,
        ** after operating upon a ring0(kernel mode) privilege level.
        ** This will enhance the viablity of the attack code even though each kernel can have different CS and DS address.
        */

论坛徽章:
0
50 [报告]
发表于 2009-08-26 14:00 |只看该作者

回复 #49 CUDev 的帖子

按我的理解,在kernel_code中return,并不是直接返回到用户态去的。
sendfile系统调用有自己的流程:创建一个pipe作缓冲用、从in_fd读数据到pipe、将pipe的数据写到out_fd、循环直到满足条件……
存在漏洞的sock_sendpage函数是在“将pipe的数据写到out_fd”这个阶段,从kernel_code返回也就是退出这个阶段。

这里有两个问题:
1、kernel_code返回值是void,但是原本的sock->ops->sendpage是有ssize_t返回值的,于是kernel_code返回后,上层调用者将在栈中得到一个假的返回值;
2、kernel_code返回后,循环会退出吗(sendfile完毕 或 出错)?(可以看到,#49的链接中,用户态调用sendfile时的count参数值为2,但LZ的例子中这个值是PAGE_SIZE,可能是为了退出循环);

如果以上两个问题处理不当,直接从kernel_code返回可能是有问题的。如果没有问题,那么可能是巧合、或者是作者精心考虑过的。


另外,#49 链接给出的代码中,通过一个栈变量where的地址来找到tast_struct,感觉确实比用汇编来取ESP好~
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP