After reading about the latest bash vulnerability, I was wondering how Tavis Ormandy's exploit works. How does (a)=>\ work?

He posted:

The bash patch seems incomplete to me, function parsing is still brittle. e.g.

$ env X='() { (a)=>\' sh -c "echo date"; cat echo

GNU Bash exports shell functions in environment variables which include the function definitions:

$ function foo { echo bar; }
$ export -f foo
$ env | grep -A1 foo
foo=() { echo bar

When a new Bash instance is spawned, it looks for environment variables matching a certain pattern. The contents of those variables are automatically imported as shell functions. As Stéphane Chazelas explains, since this feature was introduced in Bash 1.03, importing of functions was done simply by replacing the = in the corresponding entry in the environment variable array, and interpreting the result as a function definition. Prior to the patch that fixed CVE-2014-6271, the environment variable was interpreted in its entirety, including any commands that follow the actual function body. The patch introduces two special modes to the parse_and_execute() function, SEVAL_FUNCDEF and SEVAL_ONECMD. When the function is called with SEVAL_FUNCDEF, it is supposed to prevent the interpretation of commands other than function definitions. The SEVAL_ONECMD flag is supposed to prevent the function from evaluation more than a single command.

Tavis Ormandy's specially crafted environment variable does something subtly different. It is designed to confuse the parser and corrupt the buffer used to the store the commands to be evaluated. Remnants of the environment variable in the buffer change the interpretation of the subsequent command. This related issue has received the CVE identifier CVE-2014-7169.

The constituents of environment variable definition X='() { (a)=>\' are:

  • () { which is interpreted by the parser as the beginning of a function definition

  • (a)= is intended to confuse the parser and cause it to leave remnants of the environment variable in the buffer

  • >\ is the actual payload that is left in the buffer

The purpose of the payload is to change the interpretation of the command executed in the subshell invoked by sh -c "echo date";. This of course assumes that /bin/sh is a symbolic link to bash. When the command string specified as an operand to -c is placed in the buffer, the contents of the buffer are:

>\[0xA]echo date

The [0xA] is an ASCII newline character, which would normally act as a command separator, but is now escaped by the \ from the payload. As a result, the contents of the buffer are interpreted as

>echo date

Because Bash allows redirection operators to precede commands, this is equivalent to

date > echo 

This simply causes the date command to be executed with its standard output redirected to a file called echo. The remaining cat echo is not part of the exploit, it only demonstrates that now a file called echo containing the output of date exists.

As to why the string (a)= confuses the parser in this case, it would seem to that the it is related to it appearing as a (malformed) nested function definition. The simplified variant of the exploit demonstrates this more clearly:

$ X='() { function a a>\' bash -c echo
$ ls echo
  • 3
    The thing that amazes me about this entire exploit is not the idea that it's an exploit, but the fact that it's been dormant since BASH 1.13 – eyoung100 Sep 26 '14 at 14:43
  • @eyoung100 Not sure what you mean with "the nature of the way Linux was created". echo is "treated as a file"(name) only because of its position in the (bash) command. In echo date date is not treated as a command either. But in >echo date echo is the name of the file where the output of the date command is redirected. – Leiaz Sep 26 '14 at 16:02
  • @Liaz the fact that this works at all is the nature I was getting at. Try to treat a command like echo as a file on Windows and Windows will tell you echo is a command. The nature here is that Linux doesn't care as everything in Linux is a file/filestream etc. See this article – eyoung100 Sep 26 '14 at 16:19
  • 1
    @eyoung100 Thanks for the proofread, although I beg to differ that this has anything to do with that "everything is a file”. For instance, dir>echo is perfectly valid in Windows, the only difference here is that Bash allows redirection operators to precede a command. – Thomas Nyman Sep 26 '14 at 16:39
  • 1
    @eyoung100 Sure, and I agree that the reason for why echo ends up as an outfile is pretty obscure (and the usage here makes it even more confusing, but that was what the question specified). I'm just trying to make the point that I don't think it's really because "the nature of the way Linux was created", but just a peculiarity of how Bash allows redirection operators to be used. Anyway, thanks for your improvements. You pointed out where I wasn't being clear and I've tried to edit the answer to be more precise. – Thomas Nyman Sep 26 '14 at 17:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.