7

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
Thomas Nyman
  • 29,912
  • 10
  • 65
  • 77
wonderingnewbie
  • 213
  • 1
  • 4
  • I took a guess at http://stackoverflow.com/a/26045918/1126841. I'm not sure it's right, so I won't duplicate it here. – chepner Sep 26 '14 at 01:14

1 Answers1

5

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
echo
Stéphane Chazelas
  • 522,931
  • 91
  • 1,010
  • 1,501
Thomas Nyman
  • 29,912
  • 10
  • 65
  • 77
  • 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](http://www.howtogeek.com/117939/htg-explains-what-everything-is-a-file-means-on-linux/) – 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”](https://en.wikipedia.org/wiki/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](https://www.gnu.org/software/bash/manual/html_node/Redirections.html). – Thomas Nyman Sep 26 '14 at 16:39
  • @ThomasNyman Yes, but I don't think, although I may be wrong that Windows allows redirection into a command. I can re-edit that, but what I'm trying to get at is that even tho echo is normally a command that in this instance its now become a file. Consider `echo>echo 'hello world'` the echo output was also piped to a file named echo, where one is a file and one is the command. – eyoung100 Sep 26 '14 at 16:49
  • @eyoung100 _echo_ by itself is simply a word. It's interpretation depends on where it occurs on relation to other tokens. The second `echo` is interpreted as a filename because it an operand to the redirection operator. You could just as well do `X='() { (a)=>\' sh -c "outfile date"`, still leads to the same parser error. – Thomas Nyman Sep 26 '14 at 17:02
  • @eyoung100 _"When `SEVAL_FUNCDEF` is activated, it is supposed to prevent the interpretation of the commands past the functions definitions"_ Reverted this change as well because `SEVAL_FUNCDEV` alone doesn't prevent interpretation past function definitions, it only prevent interpretation of commands that don't belong to _a_ function definition. Only together with `SEVAL_ONCMD` do you get the desired behaviour. – Thomas Nyman Sep 26 '14 at 17:06
  • @ThomasNyman I'm not trying to argue but I can tell you most Windows users who are new to linux who see a command used as an outfile are befuddled at 1st. The fact that you can change the output name is irrelevant, and the editting of your post is up to you. I'm just good at fixing the grammar :) – eyoung100 Sep 26 '14 at 17:06
  • 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
  • NP, that's one of the reasons why you got my upvote :) – eyoung100 Sep 26 '14 at 17:24