How does the updated Shellshock vulnerability test for CVE-2014-7169 work?

I understand the original test for CVE-2014-6271, which was:

$ env x='() { :;}; echo vulnerable' bash -c "echo this is a test"

But I'm confused by the updated test and corresponding output for CVE-2014-7169:

$ env X='() { (a)=>\' sh -c "echo date"; cat echo
sh: X: line 1: syntax error near unexpected token `='
sh: X: line 1: `'
sh: error importing function definition for `X'
Thu 25 Sep 2014 08:50:18 BST

Could someone briefly explain what is happening here and how it bypasses the patch for CVE-2014-6271?


I've been digging around the webs for a bit since I first posted this question.

According the original discoverer of the bug, bash prior to the CVE-2014-6271 patch imported a function such as:

foo=() {
  code
}

by replacing the equals sign with a space and interpreting it... which meant interpreting beyond the function definition was possible.

The patch for CVE-2014-6271 introduced a special mode of the parse_and_execute() function to limit evaluation to the function definition, and not beyond it.

However, as explained in this thread, the specially crafted environment variable of the CVE-2014-7169 vulnerability test is designed to 1) confuse the parser to death 2) leave scraps in the buffer 3) completely change what the original bash command does when it combines with the scraps already in the buffer.

So to dissect the environment variable:

X='() { (a)=>\'

  • The parser will analyze () { (a)=>\. Note that \ is part of the string; it is not escaping the trailing single quotation.

() {

  • The parser identifies this as a function definition.

(a)=

  • This confuses the parser to death.

>\

  • The parser leaves the final two characters sitting in the buffer.

>\[NEWLINE]

  • At some point before the sh command is run, a newline is placed in the buffer.

>\[NEWLINE]echo date

  • When sh is called (which is probably a symlink to bash in this case), it adds its command arguments, echo date, to the characters already existing in the buffer.

>echo date

  • Since the newline is escaped, bash will parse the buffer as >echo date, which has the same effect as date > echo. A file named echo is created and the stdout of the date command is redirected into it.

; cat echo

  • The second command simply displays the contents of the newly created file.


It doesn't give you a nice clean output, but it does demonstrate the bug.

With no bug, the environment variable X should be ignored, bash should run echo date, and cat should complain that there is no file called echo. Eg consider how dash behaves:

me@myserver$ rm -f echo && env -i  X='() { (a)=>\' dash -c 'echo date'; cat echo
date
cat: echo: No such file or directory

I won't repeat the output you show in your question, and I won't pretend to understand how it works, but bash is running date and putting the output into a file called 'echo'. You can play with alternatives to date to convince yourself that this is usable and dangerous.