Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

There is apparently a vulnerability in bash: https://securityblog.redhat.com/2014/09/24/bash-specially-crafted-environment-variables-code-injection-attack/

I am trying to figure out what is happening, but I'm not entirely sure I understand it. How can the echo be executed as it is in single quotes?

$ env x='() { :;}; echo vulnerable' bash -c "echo this is a test"
vulnerable
this is a test
share|improve this question
    
It's not the echo that gets executed. its the function definition of x. If the function defined in x does some sneaky underhanded work, there is no way bash can check the return value if function x were real. Notice the function is empty in the test code. An unchecked return value can lead to script injection. Script injection leads to privilege escalation and privilege escalation leads to root access. The patch disables the creation of x as a function –  eyoung100 9 hours ago
    
Re: there is no way bash can check the return value if function x were real, because the return value was converted into an environment variable. Environment Variables are used to pass arguments to things like services and cron jobs.There is no bounds checking to verify that env x only contains a value. env x could contain a command that a normal user isn't supposed to have access to etc –  eyoung100 8 hours ago
1  
eyoung100, no the echo is getting executed. You can see it's getting executed because the word vulnerable appears in the output. The main problem is that bash is parsing and executing the code after the function definition as well. See the /bin/id part of seclists.org/oss-sec/2014/q3/650 for another example. –  Mikel 3 hours ago

2 Answers 2

bash stores exported function definitions as environment variables. Exported functions look like this:

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

That is, the environment variable foo has the literal contents:

() {  bar
}

When a new instance of bash launches, it looks for these specially crafted environment variables, and interprets them as function definitions. You can even write one yourself, and see that it still works:

$ export bar='() { echo "bar" ; }'
$ bash -c 'bar'
bar

Unfortunately, the parsing of function definitions from strings (the environment variables) can have wider effects than intended. In unpatched versions, it also interprets arbitrary commands that occur after the termination of the function definition. This is due to insufficient constraints in the determination of acceptable function-like strings in the environment.

This is considered insecure because variables are not typically allowed or expected, by themselves, to directly cause the invocation of arbitrary code contained in them. Perhaps your program sets environment variables from untrusted user input. It would be highly unexpected that those environment variables could be manipulated in such a way that the user could run arbitrary commands without your explicit intent to do so using that environment variable for such a reason declared in the code.

share|improve this answer
    
Could this affect any other Bash-like shell then, like Zsh? –  user815423426 6 hours ago
2  
@user815423426 No, zsh doesn't have this feature. Ksh has it but implemented differently, I think functions can only be transmitted in very narrow circumstances, only if the shell forks, not through the environment. –  Gilles 6 hours ago
2  
@user815423426 rc is the other shell that passes functions in the environment, but its with variable with names prefixed with "fn_" and they are only interpreted when invoked. –  Stéphane Chazelas 5 hours ago
    
@StéphaneChazelas - thanks for reporting the bug. –  Deer Hunter 40 mins ago

It is explained in the article you linked ...

you can create environment variables with specially-crafted values before calling the bash shell. These variables can contain code, which gets executed as soon as the shell is invoked.

Which means the bash that is called with -c "echo this is a test" executes the the code in the single quotes when it is invoked.

Bash has functions, though in a somewhat limited implementation, and it is possible to put these bash functions into environment variables. This flaw is triggered when extra code is added to the end of these function definitions (inside the enivronment variable).

Means the code example you posted exploits the fact that the invoked bash does not stop evaluating this string after performing the assignment. A function assignment in this case.

The actually special thing about the code snipped you posted, as I understand it, is that by using putting a function definition before the code we want to execute, some security mechanisms can be circumvented.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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