61

GHOST (CVE-2015-0235) just popped up. How can I quickly check if a system of mine is secure? Ideally with a one line shell command.

According to the ZDNet article "you should then reboot the system". Ideally the test would also indicate this...

the
  • 1,841
  • 2
  • 16
  • 33
  • 2
    I suggest to promote to "canconical question" – usr-local-ΕΨΗΕΛΩΝ Jan 28 '15 at 12:02
  • Great question. Too bad you accepted an answer that, far from being a one-line shell command, requires a full developer toolchain installed. Critical devices like routers mostly don't have gcc. Some devices can't even self-host. – Ben Voigt Jan 29 '15 at 19:58
  • You're right @BenVoigt. I put up a bounty for an answer with a one liner that doesn't require dev tools. – the Jan 30 '15 at 00:05
  • On a device that can't self-host, uClibc and dietlibc are much more likely than glibc. Check to make sure you're really running on glibc before you drag out the cross-compiler. – Jander Feb 04 '15 at 06:28

4 Answers4

71

It appears you can download a tool from the University of Chicago that will let you test your system for the vulnerability.

This does not repair or restart anything it will only tell you if your system is vulnerable.

$ wget https://webshare.uchicago.edu/orgs/ITServices/itsec/Downloads/GHOST.c
$ gcc GHOST.c -o GHOST
$ ./GHOST
[responds vulnerable OR not vulnerable ]

Running this on one of my remote servers I get:

user@host:~# wget https://webshare.uchicago.edu/orgs/ITServices/itsec/Downloads/GHOST.c
--2015-01-27 22:30:46--  https://webshare.uchicago.edu/orgs/ITServices/itsec/Downloads/GHOST.c
Resolving webshare.uchicago.edu (webshare.uchicago.edu)... 128.135.22.61
Connecting to webshare.uchicago.edu (webshare.uchicago.edu)|128.135.22.61|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 1046 (1.0K) [text/x-csrc]
Saving to: `GHOST.c'

100%[============================================>] 1,046       --.-K/s   in 0s      

2015-01-27 22:30:48 (237 MB/s) - `GHOST.c' saved [1046/1046]

user@host:~# gcc GHOST.c -o GHOST
user@host:~# ./GHOST
vulnerable

The source code of that script looks like this next code block but you should inspect the origin code first anyway. As others have pointed out, if you are arbitrarily running code off the internet without knowing what it does then bad things may happen:

/*
 * GHOST vulnerability check
 * http://www.openwall.com/lists/oss-security/2015/01/27/9
 * Usage: gcc GHOST.c -o GHOST && ./GHOST
 */ 

#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);
}

Edit: I've added an ansible playbook here if it's of use to anyone, if you have a large number of systems to test then ansible will allow you to do it quickly.

Also, as per discussion below, if you find your servers are vulnerable and apply available patches, it is highly recommended that you reboot your system.

aaronfay
  • 594
  • 6
  • 7
  • According to the ZDNet article "you should then reboot the system". This test doesn't seem to help with that. Or does it? – the Jan 28 '15 at 00:27
  • @KasperSouren It's worth mentioning the reboot part, but I think it's also natural to do so, because this guarantees things cached in memory etc all get flushed, plus kernel changes usually require this, so on and so forth. It's also worth pointing out that actually solving the problem is beyond the scope of your question. You just asked how to detect the vulnerability. :) –  Jan 28 '15 at 00:30
  • 3
    @KasperSouren Well, yes. If it is vulnerable, apply the patch/upgrade and reboot. – muru Jan 28 '15 at 00:30
  • Well I just want a one liner that can tell me whether my system is secure. This answer is definitely a step in the direction but if someone doesn't reboot after upgrading (a rare thing to do after upgrading a Linux system) this test doesn't help with that and might give a false sense of security. And now I have to go check all my systems to see if `uptime` is very low... – the Jan 28 '15 at 00:34
  • 9
    @KasperSouren What you're asking is frankly a little silly. This answer perfectly answers your question: how do I detect this vulnerability. That's all you asked. Asking for a "one liner" is also a little silly. I ran the test he posted here on all of my servers in under 2 minutes. It's dead simple. Just "shutdown -r now" after you're done....... –  Jan 28 '15 at 00:38
  • 1
    I upgraded, ran the test, didn't reboot. Only came back to this when I found out I had to reboot. This might happen to quite a few people and their servers might be vulnerable and might be hacked despite their false sense of security. So not that silly to get this straight if possible IMHO. – the Jan 28 '15 at 00:52
  • I've added a note in the answer about rebooting for anyone else that might come along. – aaronfay Jan 28 '15 at 02:28
  • @KasperSouren Well, in the Qualys [explanation of the bug](http://www.openwall.com/lists/oss-security/2015/01/27/9), there _is_ a one-liner example, but I cannot vouch for it, as I updated before I was aware of the bug. Search within that page for `/usr/sbin/clockdiff \`python -c "print '0' * $((0x20000-16*1-2*4-1-4))"\``, which is supposed to segfault if vulnerable. May need to execute with root privileges. – Iwillnotexist Idonotexist Jan 28 '15 at 04:39
  • 3
    The `GHOST.c` POC originates from [the original Qualys advisory](http://www.openwall.com/lists/oss-security/2015/01/27/9). – mr.spuratic Jan 28 '15 at 10:02
  • 5
    @KasperSouren a test can tell you that new programs will use a safe version of glibc. However, you may have programs running in the background that started before the upgrade, and therefore have loaded the old version. – Davidmh Jan 28 '15 at 14:06
  • The wget command specified returns: `ERROR: The certificate of ‘webshare.uchicago.edu’ is not trusted. ERROR: The certificate of ‘webshare.uchicago.edu’ hasn't got a known issuer.` – Michael Jan 28 '15 at 16:34
  • 1
    Is your system safe if `GHOST.c` fails to link with: `Undefined symbols for architecture x86_64: "_gethostbyname_r", referenced from: _main in ccwPC2Tn.o ld: symbol(s) not found for architecture x86_64`? – Michael Jan 28 '15 at 16:37
  • 1
    It is not necessary to run the test as root, and I wouldn't take security advice from anyone that does! – Alnitak Jan 28 '15 at 18:33
  • To answer your question about rebooting, it is not specifically required to reboot; if you run the test after patching, it will not report a vulnerability because the executable is linking against the newer non-vulnerable `glibc`. The rationale behind rebooting is that many processes on a Linux server are long-running (web servers, daemons, etc.) and restarting them all one by one is tedious and error-prone. Rebooting does the same and could potentially be faster. – sleblanc Jan 29 '15 at 01:30
  • @Alnitak good point, I've changed the script to a different user. Just because I did doesn't mean you should. – aaronfay Jan 29 '15 at 03:23
  • @aaronfay you've still demonstrated it running as root on your own system. – Alnitak Jan 29 '15 at 09:22
  • 1
    @Alnitak it's my prerogative. If you don't trust my methods, that's yours :) – aaronfay Jan 29 '15 at 19:27
15

PHP one-liner:

php -r '$e="0";for($i=0;$i<2500;$i++){$e="0$e";gethostbyname($e); }'

Python one-liner:

python -c 'import socket;y="0"*50000000;socket.gethostbyname(y)'

If those give you segfaults (yes, a Python segfault, a rare specimen) then you're vulnerable. I don't know if you consider Python a "developer tool" but PHP is a common program to have.

If the target device is a router, I don't know of anything you could do on it that would tell you, except digging into the manufacturer specifications and/or waiting for manufacturer advisories and firmware updates.

the
  • 1,841
  • 2
  • 16
  • 33
Ohnana
  • 4,737
  • 2
  • 23
  • 39
  • Is it possible to combine this with `sudo lsof | grep libc- | grep DEL"`? Provided in another comment, to avoid that people think they're safe while the old libc is still in use. With this addition I'll give out the bounty right away. – the Feb 03 '15 at 08:53
  • It's a shell command,so you can tack things on with &&. And that command is only after you have updated your glibc packages. If you've updated, these one liners will fail. So stuff your update vommamd in between? – Ohnana Feb 03 '15 at 12:34
  • 1
    I used the php one on SUSE 11SP3, and I saw no segfault before or after patching. Any ideas? – Marcin Feb 03 '15 at 15:49
  • @marcin That's interesting. I pulled these from internet sources, and lots of people report segfaulting. Does increasing the loop count do anything? (For what it's worth, the segfault for Python will segfault on some patched systems too... no word on why that's happening.) – Ohnana Feb 03 '15 at 16:10
  • 1
    From playing with the uchicago code, it looks like if you try to overflow by more than 4 bytes or so, gethostbyname() will return an error (EINVAL) instead of overflowing. With C you can control exactly what gets overwritten. With PHP or Python, what gets overwritten might be important and segfault, or it might be nothing; it'll be dependent on the exact build of the system. And the Python segfault on `gethostbyname("0"*50000000)` looks more like a bug in Python to me. (Ghost Python?) – Jander Feb 04 '15 at 04:17
9

aaronfay's answer already covered determining whether your underlying system is vulnerable, but it doesn't detect if there are programs that are still running using the old version of glibc after upgrade. That is, you could upgrade without restarting the affected processes, and the script would report "not vulnerable" even though the old, vulnerable library is still in use.

Here is one way to check if there are any dynamically linked programs still using the old version of glibc:

sudo lsof | grep libc- | grep DEL

If there are results, deleted versions of glibc are in use, and the processes using them may be vulnerable.

Of course, this doesn't cover the case in which glibc was statically linked. The good(?) news is that it's very rare to find glibc statically linked in a binary, both because of the size, and because it presents some other annoyances and difficulties. In the case that you do have programs using a statically compiled glibc (which you almost certainly don't), you would need to recompile them.

Chris Down
  • 347
  • 1
  • 2
  • 11
  • 2
    `lsof +c0 -f -- /usr/lib64/libc-*.so | grep "(deleted)$"` a bit more precise, shows you full names of processes, and looks for linking to files that were deleted. – Marcin Jan 30 '15 at 16:22
-1

If you have an account in Redhat, you can access their 'GHOST detector' at this URL . Its a small shell script that will tell you whether your glibc is vulnerable.

Red Hat has now come back and stated that their detector script is flawed. Note that there is also a concern on RHEL6.6 when using yum --security to patch the vulnerability as it has been missed according to https://bugzilla.redhat.com/show_bug.cgi?id=1186717.

Sreeraj
  • 1,297
  • 1
  • 13
  • 21
  • 2
    The RedHat tool only checks the version of the glibc RPM, and it only knows about RedHat versions (and probably derivatives). It does not actually work on any other OS. – chutz Jan 28 '15 at 14:12
  • 2
    This is also no longer available for download, likely do to the flaws. – Shane Andrie Jan 28 '15 at 15:47