Wednesday, January 28, 2015

How To Patch and Protect Linux Server Against the Glibc GHOST Vulnerability # CVE-2015-0235

How To Patch and Protect Linux Server Against the Glibc GHOST Vulnerability # CVE-2015-0235


Avery serious security problem has been found in the GNU C Library (Glibc) called GHOST.  How can I fix GHOST vulnerability and protect my Linux server against the attack?  How do I verify that my server has been fixed against the Glibc GHOST vulnerability?

A very serious security problem has been found and patched in the GNU C Library called Glibc.  It was announced on 27th January 2015.

What is the GHOST security bug?

Tutorial details
DifficultyEasy (rss)
Root privilegesYes
RequirementsLinux+reboot required
Estimated completion time10m

From the RHEL bugzilla:
A heap-based buffer overflow was found in __nss_hostname_digits_dots(), which is used by the gethostbyname() and gethostbyname2() glibc function call. A remote attacker could use this flaw to execute arbitary code with the permissions of the user running the application.
A mailing list entry with more details, including in-depth analysis and exploit vectors is here.

What C library (Glibc) version does my Linux system use?

The easiest way to check the version number is to run the following command:
ldd --version
 
Sample outputs from RHEL/CentOS Linux v6.6:
ldd (GNU libc) 2.12
Copyright (C) 2010 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Written by Roland McGrath and Ulrich Drepper.
Sample outputs from Ubuntu Linux 12.04.5 LTS:
ldd (Ubuntu EGLIBC 2.15-0ubuntu10.9) 2.15
Copyright (C) 2012 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Written by Roland McGrath and Ulrich Drepper.
Sample outputs from Debian Linux v7.8:
ldd (Debian EGLIBC 2.13-38+deb7u6) 2.13
Copyright (C) 2011 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Written by Roland McGrath and Ulrich Drepper.

A list of affected Linux distros

  • RHEL (Red Hat Enterprise Linux) version 5.x, 6.x and 7.x
  • CentOS Linux version 5.x, 6.x & 7.x
  • Ubuntu Linux version 10.04, 12.04 LTS
  • Debian Linux version 7.x
  • Linux Mint version 13.0
  • Fedora Linux version 19 or older
  • SUSE Linux Enterprise 11 and older (also OpenSuse Linux 11 or older versions).
  • Arch Linux glibc version <= 2.18-1

GHOST vulnerability check

You can test or reproduce the bug using the following C code:
/* ghosttest.c:  GHOST vulnerability tester */
/* Credit: http://www.openwall.com/lists/oss-security/2015/01/27/9 */
#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] = '\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);
}
 
Compile and run it as follows:
$ gcc ghosttest.c -o ghosttest
$ ./ghosttest
Sample outputs from patched Debian v7.8 server:
not vulnerable
Sample outputs from unpatched Ubuntu 12.04 LTS server:
vulnerable

How do list packages/applications depends upon vulnerable Glibc?

Type the following lsof command:
lsof | grep libc | awk '{print $1}' | sort | uniq
Sample outputs from my Debian Linux v7.x nas:
Fig.01: Linux find all the services/applications that rely on the GNU C libraries (Glibc) command
Fig.01: Linux find all the services/applications that rely on the GNU C libraries (Glibc) command

Fix the GHOST vulnerability on a CentOS/RHEL/Fedora/Scientific Linux

Type the following yum command as the root user:
sudo yum clean all
sudo yum update
Finally, reboot RHEL/SL/Fedora/CentOS Linux server by typing the following command:
### Sysadmin should plan on updating as soon as possible or use maintenance reboot window ##
sudo reboot
Sample outputs:
Fig.02 Fix the GHOST vulnerability on a CentOS/RHEL/Fedora/Scientific Linux
Fig.02 Fix the GHOST vulnerability on a CentOS/RHEL/Fedora/Scientific Linux

Fix the GHOST vulnerability on a Ubuntu Linux

Type the following apt-get command as the root user:
sudo apt-get clean
sudo apt-get update
sudo apt-get dist-upgrade
Finally, reboot Ubuntu Linux server by typing the following command:
sudo reboot
Sample outputs:
Fig.03: Fix the GHOST vulnerability on a Ubuntu Linux LTS
Fig.03: Fix the GHOST vulnerability on a Ubuntu Linux LTS

Fix the GHOST vulnerability on a Debian Linux

Type the following apt-get command as the root user:
sudo apt-get clean
sudo apt-get update
sudo apt-get dist-upgrade
Finally, reboot Debian Linux server by typing the following command:
sudo reboot
Sample session:
Gif 01: Fix the GHOST vulnerability on a Debian Linux server
Gif 01: Fix the GHOST vulnerability on a Debian Linux server

How can I verify that my Linux system no longer vulnerable after the reboot?

Method #1: The easiest way to check vulnerability and/or confirm remediation is to run the following command to verify that you are running an updated version of Glibc:
$ ldd --version
Method #2: Run the instructions given in the previous section called GHOST vulnerability check (generic method for all Linux based systems).
Method #3: If you are RHN subscriber see the Red Hat Access Lab: GHOST tool (only for RHEL/CentOS/SL systems:
#!/bin/bash
# rhel-GHOST-test.sh -  GHOST vulnerability tester. Only for CentOS/RHEL based servers.  #
# Credit : Red Hat, Inc - https://access.redhat.com/labs/ghost/ #
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>
Please refer to <https://access.redhat.com/articles/1332213> for remediation steps"
 
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
 
Sample outputs from patched RHEL v6.8 server:
bash rhel-GHOST-test.sh
Vulnerable glibc version <= 2.17-54
Vulnerable glibc version <= 2.5-122
Vulnerable glibc version <= 2.12-1.148
Detected glibc version 2.12 revision 149
Not Vulnerable.

No comments: