CVE-2015-0235:Linux glibc高危漏洞的检测及修复方法
这几天复习运维知识,也没怎么关注业界新闻,可等我一关注,又“捅娄子”了,Linux 继上次CVE-2014-6271漏洞爆发以来,再次爆发一个严重漏洞:CVE-2015-0235-Linux glibc 高危漏洞,正在使用 Linux 系统的个人或企业,看到消息请立即修复!
下面是我转载的检测和修复方法,我个人服务器 Centos 6.5 已成功修复:
一、漏洞概述
2015/01/28【CVE 2015-0235: GNU glibc gethostbyname 缓冲区溢出漏洞 】全面爆发,该漏洞的产生是 Qualys 公司在进行内部代码审核时,发现了一个在 GNU C 库(glibc)中存在的 __nss_hostname_digits_dots 函数导致的缓冲区溢出漏洞。这个 bug 可以通过 gethostbyname *()函数来触发,本地和远程均可行。该漏洞(幽灵漏洞)造成了远程代码执行,攻击者可以利用此漏洞远程获取系统进程当前的权限。
幽灵漏洞是 Linux glibc 库上出现的一个严重的安全问题,他可以让攻击者在不了解系统的任何情况下远程获取操作系统的控制权限。目前他的 CVE 编号为 CVE-2015-0235。
什么是 glibc
glibc 是 GNU 发布的 libc 库,即 c 运行库。glibc 是 linux 系统中最底层的 api,几乎其它任何运行库都会依赖于 glibc。glibc 除了封装 linux 操作系统所提供的系统服务外,它本身也提供了许多其它一些必要功能服务的实现。glibc 囊括了几乎所有的 UNIX 通行的标准。
出现了什么漏洞
代码审计公司 Qualys 的研究人员在 glibc 库中的 __nss_hostname_digits_dots()函数中发现了一个缓冲区溢出的漏洞,这个 bug 可以经过 gethostbyname*()函数被本地或者远程的触发。应用程序主要使用 gethostbyname*()函数发起 DNS 请求,这个函数会将主机名称转换为 ip 地址。
更多的细节可以从下面的视频中看到(一堆鸟语,听不懂): [youku]XODgxMTg1NDY4[/youku]
漏洞危害
这个漏洞造成了远程代码执行,攻击者可以利用此漏洞获取系统的完全控制权。
漏洞证明
在我们的测试中,我们编写了一个 POC,当我们发送一封精心构造的电子邮件给服务器后,我们便可以获得远程 Linux 服务器的 shell,这绕过了目前在 32 位和 64 位系统的所有保护(如 ASLR,PIE 和 NX)。
我们能做什么?
给操作系统及时打补丁,我们(Qualys)已与 Linux 发行商紧密合作,会及时发布补丁。
为什么叫做 GHOST?
因为他通过 GetHOST 函数触发。
哪些版本和操作系统受影响?
第一个受影响的版本是 GNU C 库的 glibc-2.2,2000 年 11 月 10 号发布。我们已找出多种可以减轻漏洞的方式。我们发现他在 2013 年 5 月 21 号(在 glibc-2.17 和 glibc-2.18 发布之间)已经修复。不幸的是他们不认为这是个安全漏洞。从而导致许多稳定版本和长期版本暴露在外,其中包括 Debian 7 (wheezy),Red Hat Enterprise,Linux 6 & 7,CentOS 6 & 7,Ubuntu 12.04 等。
以上内容摘自:360 安全播报平台
二、检测方法
检测方法 1【RedHat 官方检测方法】:
ghost_check.sh 源码(张戈亲测:推荐使用这种方法来测试更加准确!):
#!/bin/bash
vercomp () {
if [[ $1 == $2 ]]
then
return 0
fi
local IFS=.
local i ver1=($1) ver2=($2)
# fill empty fields in ver1 with zeros
for ((i=${#ver1[@]}; i<${#ver2[@]}; i++))
do
ver1[i]=0
done
for ((i=0; i<${#ver1[@]}; i++))
do
if [[ -z ${ver2[i]} ]]
then
# fill empty fields in ver2 with zeros
ver2[i]=0
fi
if ((10#${ver1[i]} > 10#${ver2[i]}))
then
return 1
fi
if ((10#${ver1[i]} < 10#${ver2[i]}))
then
return 2
fi
done
return 0
}
glibc_vulnerable_version=2.17
glibc_vulnerable_revision=54
glibc_vulnerable_version2=2.5
glibc_vulnerable_revision2=122
glibc_vulnerable_version3=2.12
glibc_vulnerable_revision3=148
echo "Vulnerable glibc version <=" $glibc_vulnerable_version"-"$glibc_vulnerable_revision
echo "Vulnerable glibc version <=" $glibc_vulnerable_version2"-"$glibc_vulnerable_revision2
echo "Vulnerable glibc version <=" $glibc_vulnerable_version3"-1."$glibc_vulnerable_revision3
glibc_version=$(rpm -q glibc | awk -F"[-.]" '{print $2"."$3}' | sort -u)
if [[ $glibc_version == $glibc_vulnerable_version3 ]]
then
glibc_revision=$(rpm -q glibc | awk -F"[-.]" '{print $5}' | sort -u)
else
glibc_revision=$(rpm -q glibc | awk -F"[-.]" '{print $4}' | sort -u)
fi
echo "Detected glibc version" $glibc_version" revision "$glibc_revision
vulnerable_text=$"This system is vulnerable to CVE-2015-0235. <https://access.redhat.com/security/cve/CVE-2015-0235>
Update the glibc and ncsd packages on your system using the packages released with the following:
yum install glibc"
if [[ $glibc_version == $glibc_vulnerable_version ]]
then
vercomp $glibc_vulnerable_revision $glibc_revision
elif [[ $glibc_version == $glibc_vulnerable_version2 ]]
then
vercomp $glibc_vulnerable_revision2 $glibc_revision
elif [[ $glibc_version == $glibc_vulnerable_version3 ]]
then
vercomp $glibc_vulnerable_revision3 $glibc_revision
else
vercomp $glibc_vulnerable_version $glibc_version
fi
case $? in
0) echo "$vulnerable_text";;
1) echo "$vulnerable_text";;
2) echo "Not Vulnerable.";;
esac
检测方法 2【简单的检测方法】:
/usr/sbin/clockdiff `python -c "print '0' * $((0x10000-16*1-2*4-1-4))"`
检测方法 3【二进制检测方法】:
ghost.c 源码:
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.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] = ' ';
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);
}
三、修复方法
①、在线修复方案
CentOS, Red Hat, Fedora 等系列衍生版本(RHN 建议):
yum update glibc
Debian, Ubuntu 等系列衍生版本:
apt-get clean && apt-get update && apt-get upgrade
②、离线修复方案
I. Centos6.5 离线补丁
先检查本地 glibc 包安装了哪些相关包
rpm -qa|grep glibc
然后,到阿里源下载对应版本
cd /usr/local/src
cat > update.txt << EOF
http://mirrors.aliyun.com/centos/6.6/updates/x86_64/Packages/glibc-2.12-1.149.el6_6.5.i686.rpm
http://mirrors.aliyun.com/centos/6.6/updates/x86_64/Packages/glibc-2.12-1.149.el6_6.5.x86_64.rpm
http://mirrors.aliyun.com/centos/6.6/updates/x86_64/Packages/glibc-common-2.12-1.149.el6_6.5.x86_64.rpm
http://mirrors.aliyun.com/centos/6.6/updates/x86_64/Packages/glibc-devel-2.12-1.149.el6_6.5.x86_64.rpm
http://mirrors.aliyun.com/centos/6.6/updates/x86_64/Packages/glibc-headers-2.12-1.149.el6_6.5.x86_64.rpm
EOF
进行后台断点下载补丁包
wget -b -i update.txt -c
使用 yum 本地安装
yum localinstall glibc-*
或是 rpm 安装
rpm -ivUh glibc-*
II. Red Had 系列衍生版本
使用方法:参考上文【Centos6.5 离线补丁】的修补方法。
离线包下载地址:
http://mirrors.aliyun.com/centos/7/updates/x86_64/Packages/glibc-2.17-55.el7_0.5.i686.rpm
http://mirrors.aliyun.com/centos/7/updates/x86_64/Packages/glibc-2.17-55.el7_0.5.x86_64.rpm
四、修复检测
①、ghost_check.sh 脚本检测
②、ghost.c 脚本检测
注意:打好补丁后必须立即重启操作系统,否则会造成应用业务无法使用。
五、参考来源
redhat 官方:https://access.redhat.com/articles/1332213 redhat 官方补丁介绍: https://rhn.redhat.com/errata/RHSA-2015-0090.html https://rhn.redhat.com/errata/RHSA-2015-0092.html ubuntu 官方补丁介绍: http://www.ubuntu.com/usn/usn-2485-1/
- Spring集成RabbitMQ-必须知道的几个概念
- Spring读书笔记——bean创建(上)
- 15:21爆出的小程序功能升级,你还要对小程序观望吗?
- 如何解决分布式系统中的跨时区问题[原理篇]
- 什么是区块链:块的结构
- Spring读书笔记——bean创建(下)
- 当区块链遇上传统行业 我们的生活和工作会改变吗?
- 如何设计开发好一个 HTTP API?
- [WCF权限控制]基于Windows用户组的授权方式[下篇]
- Spring读书笔记——bean解析
- 10个大数据误区,看看你中了几个?
- 从数据到代码——通过代码生成机制实现强类型编程[上篇]
- Spring读书笔记——bean加载
- Java8-初识Lambda
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 原来sqlite3_get_table() 是这样抓取数据的!!!
- 【tensorflow2.0】中阶api--模型、损失函数、优化器、数据管道、特征列等
- 最短路径Dijkstra算法的简单实现
- django-表单之获取表单信息(二)
- 【tensorflow2.0】高阶api--主要为tf.keras.models提供的模型的类接口
- django-表单之模型表单(三)
- sqlite3数据库封装 - 动态链接库
- 【tensorflow2.0】张量的结构操作
- 指针*和引用&的区别使用
- django-表单之手动渲染(五)
- django-表单之模型表单渲染(六)
- 【tensorflow2.0】张量的数学运算
- django-表单之数据保存(七)
- 用C++跟你聊聊“中介者模式”
- 【tensorflow2.0】AutoGraph的使用规范