So while most of the world was going crazy reading all the news about ShellShock – the weakness in the GNU bash shell tool used by versions of the Linux operating system around the world – I was locked away in a customer software development workshop all day.
When I finally came out, a lot of the hubbub had died down after it had been announced that several of the security equipment vendors had apparently issued IPS rules and signatures that might catch the pesky thing.
Of course the difficulty with Shell Shock is that we’re all still coming to terms with the fact that rather than this being a clearly scoped remote network vulnerability in a poorly implemented network service, or even an impractical protocol design, the weakness actually affects the basic interprocess communication systems inherent within the UNIX – Linux – operating system.
In contrast to the usual security vulnerabilities seen, we can’t simply audit the version of the network software involved to tell if we’re affected – we have to actually understand how the network software does what it does to achieve its effects, and whether it makes use of the underlying operating system shell and how its network interactions might influence that.
Because of these complexities, determining exact scope of vulnerability is significantly difficult. As I write, security experts suggest that the following network services and protocols may have potential exposure:
- web servers: via the CGI interface which will invoke the system shell to create dynamic pages.
- SNMP daemons: if they are extended to provide an SNMP MIV view on custom components by invoking the system shell
- DHCP clients: network interface configuration implemented through system shell
Restricted SSH servers: command invocation can be abused
However, there’s no guarantee of the completeness of that list, and determining whether a specific situation might cause exposure is an expensive activity.
Should we breathe a sigh of relief, then, when the security appliance vendors publish IPS rules? The respected Vulnerability Research Team who source rules for Sourcefire and Cisco amongst others, published four rules which focus on the web server CGI situation and look for the explicit attempt which has been seen in the wild.
But in contrast to, say, the Heartbleed problem which was a clear case of a protocol violation that a network security device could be programmed to spot, Shell-Shock is much harder. It’s quite trivial, for example, for someone in possession of the VRT rules to modify the commonly available exploits so that the literal IPS rule match fails, but the semantics of the network exchange result in the same exposure.
So what’s the answer? There seem to be various patches available to repair bash, but some have called into question the effectiveness of these patches. Others have suggested abandoning the bash shell as the system default and use more modern alternatives such as dash.
For those not able to make such significant changes to the fundamental parts of the operating system shell, however, there is an alternative method to protect certain network apps using Linux’s comprehensive dynamic linking technology:
Given a network application that might invoke system shell commands, it’s possible to trap attempts by that application to set environment variables – which are the crux of the weakness – and vet the modifications against a regular expression. If the attempted environmental variables look sane and match the regular expression, the operation is permitted, but if the environmental variables don’t match, then the operation is denied.
This can be considered a kind-of UNIX inter-process communication firewall in policing the communications between the essential components of a UNIX-based solution.
Inspired by Fabio Busatto’s libkeeaplive package, which enables network applications to transparently make use of implicit socket keepalives with modifications, I can present, without warranty, libbunker.so (Shellshock? Sorry!) – a framework for policing the environmental variables communicated between UNIX processes:
/* * Simple wrapper around setenv in order to police * environment setting operations so that downstream * bash shells cannot be subverted into running arbitrary * code. adamc 26-Sep-2014. * * Inspired by Fabio Busatto's libkeepalive * * # compile like this: * linux# gcc -shared -o libbunker.so -ldl bunker.c * linux# cp libbunker.so /usr/lib * * # protect apps like this: * linux$ LD_PRELOAD=/usr/lib/libbunker.so /usr/local/bin/my-network-app */ #ifndef RTLD_NEXT # define _GNU_SOURCE #endif #include <dlfcn.h> #include <errno.h> #include <stdlib.h> #include <strings.h> #include <sys/types.h> #include <regex.h> int setenv(const char *name, const char *value, int overwrite); int setenv(const char *name, const char *value, int overwrite) { int (*libc_setenv)(const char*, const char*, int overwrite); int result; regex_t re; *(void **)(&libc_setenv) = dlsym(RTLD_NEXT, "setenv"); if(dlerror()) { errno = EACCES; return -1; } /* Ensure the value of the variables contains only letters, * numbers and selected characters. You may need to modify this * if it is too restrictive. */ result = regcomp(&re, "^[0-9a-z\\ \\_\\-\\:\\,]+$", REG_EXTENDED|REG_ICASE); if (result!=0) { errno = EINVAL; return -1; } result = regexec(&re, value, 0, NULL, 0); regfree(&re); if (result!=0) { errno = EINVAL; return -1; } return libc_setenv(name, value, overwrite); }