包括Linux不支持在线升级替换内核在内, 还有这个CASE, 还是不如AIX啊.
http://www.ksyun.com/indexNotice/info/2015/2185.html#80b8ba67-599d-4f7d-a0e3-196dcc238f03
一、漏洞背景
代码审计公司Qualys的研究人员在glibc库中的__nss_hostname_digits_dots()函数中发现了一个缓冲区溢出的漏洞,这个bug可以经过gethostbyname*()函数被本地或者远程的触发。
1)通过gethostbyname()函数或gethostbyname2()函数,将可能产生一个堆上的缓冲区溢出。经由gethostbyname_r()或gethostbyname2_r(),则会触发调用者提供的缓冲区溢出(理论上说,调用者提供的缓冲区可位于堆,栈,.data节和.bss节等。但是,我们实际操作时还没有看到这样的情况)。
2)漏洞产生时至多sizeof(char* )个字节可被覆盖(注意是char*指针的大小,即32位系统上为4个字节,64位系统为8个字节)。但是payload中只有数字( '0 '...' 9') ,点( “.”) ,和一个终止空字符('\0' ) 可用。
3)尽管有这些限制,我们依然可以执行任意的代码。
二、影响范围
该漏洞影响glibc库版本2.2-2.17的Linux操作系统
操作系统类型包括
CentOS 6 & 7
Debian 7
Red Hat Enterprise Linux 6 & 7
Ubuntu 10.04 & 12.04
各Linux发行版
三、漏洞测试
1、编译以下测试代码
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <gnu/libc-version.h>
#define CANARY "in_the_coal_mine"
struct {
char buffer[1024];
char canary[sizeof(CANARY)];
} temp = { "buffer", CANARY };
int main(void) {
struct hostent resbuf;
struct hostent *result;
int herrno;
int retval;
/*** strlen (name) = size_needed - sizeof (*host_addr) - sizeof (*h_addr_ptrs) - 1; ***/
size_t len = sizeof(temp.buffer) - 16*sizeof(unsigned char) - 2*sizeof(char *) - 1;
char name[sizeof(temp.buffer)];
memset(name, '0', len);
name[len] = '\0';
retval = gethostbyname_r(name, &resbuf, temp.buffer, sizeof(temp.buffer), &result, &herrno);
if (strcmp(temp.canary, CANARY) != 0) {
puts("vulnerable");
exit(EXIT_SUCCESS);
}
if (retval == ERANGE) {
puts("not vulnerable");
exit(EXIT_SUCCESS);
}
puts("should not happen");
exit(EXIT_FAILURE);
}
测试结果:
四、漏洞修复
更新是在glibc包中,但是这个库会被很多运行中的服务使用。在更新之后,每个服务都要重启一下。要找到所有依赖glibc的服务,请使用如下命令,它会显示所有打开的文件(lsof),然后找到引用glibc库的文件。
$ lsof | grep libc | awk '{print $1}' | sort | uniq
最安全的办法是重启所有你上面用lsof找到的服务。当然也可以重启服务器。建议如果机器或服务不是对外开放访问的, 还是别升glibc了。优先升级重启对外开放的服务器,如Web和Mail等等。
目前,Debian和Ubuntu,以及CentOS已经提供补丁更新,你可以通过如下方式升级。
Debian/Ubuntu升级方法:
#apt?-get update
#apt-get install libc6
RHEL/CentOS升级方法:
#yum update glibc
如果有开放网络端口的服务太多, 还不如重启, 例如
# lsof | grep libc | awk '{print $1}' | sort | uniq
abrtd
atd
auditd
automount
awk
bash
certmonge
crond
csvlog_up
cupsd
dbus-daem
grep
hald
hald-addo
hald-runn
init
irqbalanc
lsof
master
mcelog
mingetty
pickup
postgres
qmgr
rpcbind
rpc.statd
rsyslogd
sleep
snmpd
sort
sshd
udevd
uniq
xinetd