Shellshock turned every CGI script into a shell

bash parses an environment variable whose value begins with () { as a function definition, and until last week it carried on executing whatever followed the closing brace. Anything that puts untrusted input into an environment variable and then starts bash — which is precisely what CGI does with every request header — was a remote shell.

# the test everybody ran on 24 September
env x='() { :;}; echo vulnerable' bash -c 'echo test'
# vulnerable        <- a patched bash prints only 'test'
# test

apt-get update && apt-get install --only-upgrade bash
dpkg -l bash | tail -1

# then find what could reach it: CGI, and anything shelling out
# from inside a request
grep -rl 'cgi-bin|ScriptAlias|fastcgi_pass' /etc/nginx /etc/apache2
grep -rn 'system(|exec(|shell_exec(|passthru(' /var/www --include='*.php'

Two things made this worse than the description suggests. The first patch on 24 September was incomplete and a second bug was public within two days, so “we patched on Wednesday” was not an answer — the version had to be checked again on Friday, and again after that. And the exposure was much wider than CGI: a DHCP client puts server-supplied strings into the environment before running bash hooks, and any PHP calling system() or mail() on a box where /bin/sh is bash inherits the same path. The durable lesson is not about bash. It is that an environment variable is an input like any other, and that a process boundary is not a validation boundary — the same shape of bug is available to anything passing attacker-controlled strings through putenv and exec.