Chinaunix首页 | 论坛 | 博客
  • 博客访问: 325086
  • 博文数量: 78
  • 博客积分: 1322
  • 博客等级: 中尉
  • 技术积分: 680
  • 用 户 组: 普通用户
  • 注册时间: 2010-04-14 13:24
文章分类
文章存档

2012年(20)

2011年(55)

2010年(3)

分类:

2011-12-23 08:44:57

    本系列的文章将系统的介绍Linux内核NULL指针引发的BUG的相关内容,共分为四篇。本人希望将该BUG的相关信息系统的整理起来,以遍对分析Linux下漏洞的发现和挖掘进行总结。

    该系列的四篇文章所包含的很多内容都是转载过来的,每篇文章都注明了引用的出处。但是本人同时也在相关的内容上做了一些关键性的、个人的理解和看法。四篇文章的标题和简介如下:

第一篇:Linux内核NULL指针引发的BUG(一)--介绍
   本篇是BUG的简单介绍,实际上已经包含了如果用户态如何利用该BUG来攻击系统。
第二篇:Linux内核NULL指针引发的BUG(二)--剖析
   转载kouu兄系统分析的利用该BUG从普通用户获取root用户权限的实现。
第三篇:Linux内核NULL指针引发的BUG(三)--源码
   整个利用Linux NULL指针BUG的源码以及个人的分析和总结。
第四篇:Linux内核NULL指针引发的BUG(四)--对SElinux的看法
   转载SElinux Team开发人员对SElinux安全性的分析。
  【警告:本文中列出的代码仅限于学习和研究使用。任何用于非法用途的,请自行承担责任。】

      本文欢迎自由转载,但请标明出处,并保证本文的完整性。
     
作者:Godbach
    Blog:http://Godbach.cublog.cn
     
日期:2010/01/13

Linux NULL pointer dereference due to incorrect proto_ops initializations

Linux NULL pointer dereference due to incorrect proto_ops initializations
------------------------------------------------------------------------

In the Linux kernel, each socket has an associated struct of operations
called proto_ops which contain pointers to functions implementing various features, such as accept, bind, shutdown, and so on.

If an operation on a particular socket is unimplemented, they are expected to point the associated function pointer to predefined stubs, for example if the "accept" operation is undefined it would point to sock_no_accept(). However, we have found that this is not always the case and some of these pointers are left uninitialized.

This is not always a security issue, as the kernel validates the pointers at the call site, such as this example from sock_splice_read:

static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
                    struct pipe_inode_info *pipe, size_t len,
                unsigned int flags)
{
    struct socket *sock = file->private_data;

    if (unlikely(!sock->ops->splice_read))
        return -EINVAL;

    return sock->ops->splice_read(sock, ppos, pipe, len, flags);
}

【Godbach注】上面的代码就是内核中常见的,调用函数指针指向的函数之前,先判断该指针的有效性。如果是合法的指针,则调用其指向的函数。当然,如果所有的proto_ops结构都对函数指针进行初始化,使其指向一个有效的函数,那么这里不进行指针有效性的判断也是可以的。

But we have found an example where this is not the case; the sock_sendpage() routine does not validate the function pointer is valid before dereferencing it, and therefore relies on the correct initialization of the proto_ops structure.

We have identified several examples where the initialization is incomplete:

- The SOCKOPS_WRAP macro defined in include/linux/net.h, which appears correct   at first glance, was actually affected. This includes PF_APPLETALK, PF_IPX, PF_IRDA, PF_X25 and PF_AX25 families.

- Initializations were missing in other protocols, including PF_BLUETOOTH, PF_IUCV, PF_INET6 (with IPPROTO_SCTP), PF_PPPOX and PF_ISDN. 

【Godbach注】但是sock_sendpage函数指针解引用的时候并没有检查其合法性。而且在诸如协议族PF_BLUETOOTH, PF_IUCV, PF_INET6 (protocol IPPROTO_SCTP), PF_PPPOX 和 PF_ISDN的proto_ops中并为未始化sendpage函数指针,默认的为NULL。这就导致这几个协议对应的socket传输中,一旦内核态执行到sendpage函数,肯定会出现对NULL指针的解引用。这就引起了Linux内核态NULL指针BUG,并在满足一定前提下,可以被恶意代码利用。

--------------------
Affected Software
------------------------

All Linux 2.4/2.6 versions since May 2001 are believed to be affected:

- Linux 2.4, from 2.4.4 up to and including 2.4.37.4
- Linux 2.6, from 2.6.0 up to and including 2.6.30.4

--------------------
Consequences
--------------------

This issue is easily exploitable for local privilege escalation. In order to exploit this, an attacker would create a mapping at address zero containing code to be executed with privileges of the kernel, and then trigger a vulnerable operation using a sequence like this:

/* ... */
    int fdin = mkstemp(template);
    int fdout = socket(PF_PPPOX, SOCK_DGRAM, 0);

    unlink(template);

    ftruncate(fdin, PAGE_SIZE);

    sendfile(fdout, fdin, NULL, PAGE_SIZE);
/* ... */

Please note, sendfile() is just one of many ways to cause a sendpage
operation on a socket.

Successful exploitation will lead to complete attacker control of the system.

【Godbach注】上面的示例代码就是触发内核态访问sendpage函数指针,由于其指向NULL,因此这段代码就可以引起内核态访问NULL指针,出现Oops。如果用户态将0地址(通常NULL为0)设置为可执行,那么内核代码就会顺利的执行0地址的指令。如果0地址被恶意注入了修改当前进程ID的代码,那么当前进程就有可能从普通用户的身份变为root用户。

-------------------
Mitigation
-----------------------

Recent kernels with mmap_min_addr support may prevent exploitation if
the sysctl vm.mmap_min_addr is set above zero. However, administrators
should be aware that LSM based mandatory access control systems, such
as SELinux, may alter this functionality.

It should also be noted that all kernels up to 2.6.30.2 are vulnerable to published attacks against mmap_min_addr. 

【Godbach注】这里提到了虽然内核存在该BUG,但是如果不允许用户态映射0地址的话,这个BUG还是无法被利用的,这个可以通过设置sysctl变量vm.mmap_min_addr大于0来实现。但是一些基于强制访问控制的Linux安全模块,比如SElinux,有可能修改这个变量,进而使0地址仍然可以映射。如果禁用了SElinux的话,该BUG就不能被利用了。因此,有人据此认为SElinux弱化了系统的安全。我会在该系列的第四篇文章中转载SElinux Team的开发人员的看法,进一步了解SElinux。

-------------------
Solution
-----------------------

Linus committed a patch correcting this issue on 13th August 2009.


-------------------
Credit
-----------------------

This bug was discovered by Tavis Ormandy and Julien Tinnes of the Google
Security Team.

--
-------------------------------------
tavisosdf.lonestar.org | finger me for my gpg key.
-------------------------------------------------------

引用链接:

阅读(2433) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~