This is a personal blog. My other stuff: book | home page | Substack

September 27, 2014

Bash bug: apply Florian's patch now (CVE-2014-6277 and CVE-2014-6278)

OK, rebuild bash and deploy Florian's unofficial patch or its now-upstream version now. If you're a distro maintainer, please consider doing the same.

My previous post has more information about the original vulnerability (CVE-2014-6271). It also explains Tavis' and my original negative sentiment toward the original upstream patch. In short, the revised code did not stop bash from parsing the code seen in potentially attacker-controlled, remotely-originating environmental variables. Instead, the fix simply seeks to harden the parsing to prevent RCE. It relies on two risky assumptions:
  • That spare for this one bug we're fixing now, the process of parsing attacker-controlled functions is guaranteed to have no side effects on the subsequently executed trusted code.

  • That the underlying parser, despite probably not being designed to deal with attacker-supplied inputs, is free from the usual range of C language bugs.
From the very early hours, we have argued on the oss-security mailing list that a more reasonable approach would be to shield the parser from remotely-originating strings. I proposed putting the function export functionality behind a runtime flag or using a separate, prefixed namespace for the exported functions - so that variables such as HTTP_COOKIE do not go through this code path at all. Unfortunately, we made no real progress on that early in the game.

Soon thereafter, people started to bump into additional problems in the parser code. The first assumption behind the patch - the one about the parsing process not having other side effects - was quickly proved wrong by Tavis, who came up with a code construct that would get the parser in an inconsistent state, causing bash to create a bogus file and mangle any subsequent code that /bin/sh is supposed to execute.

This was assigned CVE-2014-7169 and led to a round of high-profile press reports claiming that we're still doomed, and people assigning the new bug CVSS scores all the way up to 11. The reality was a bit more nuanced: the glitch demonstrated by Tavis' code is a bit less concerning, because it does not translate into a universally exploitable RCE - at least not as far as we could figure it out. Some uses of /bin/sh would be at risk, but most would just break in a probably-non-exploitable way. The maintainer followed with another patch that locked down this specific hole.

The second assumption started showing cracks, too. First came a report from Todd Sabin, who identified an static array overflow error when parsing more than ten stacked redirects. The bug, assigned CVE-2014-7186, would cause a crash, but given the nature of the underlying assignment, immediate exploitability seemed fairly unlikely. Another probably non-security off-by-one issue with line counting in loops cropped up shortly thereafter (CVE-2014-7187).

The two latter issues do not have an officially released upstream patch at that point, but they prompted Florian Weimer of Red Hat to develop an unofficial patch that takes a seemingly more durable approach that we argued for earlier on: putting function exports in a separate namespace. Florian's fix effectively isolates the function parsing code from attacker-controlled strings in almost all the important use cases we can currently think of.

(One major outlier would be any solutions that rely on blacklisting environmental variables to run restricted shells or restricted commands as a privileged user - sudo-type stuff - but it's a much smaller attack surface and a a very dubious security boundary to begin with.)

Well... so, to get to the point: I've been fuzzing the underlying function parser on the side - and yesterday, bumped into a new parsing issue (CVE-2014-6277) that is almost certainly remotely exploitable and made easier to leverage due to the fact that bash is seldom compiled with ASLR. I'll share the technical details later on; for now, I sent the info to the maintainer of bash and to several key Linux distros. In general terms, it's an attempt to access uninitialized memory leading to reads from, and then subsequent writes to, a pointer that is fully within attacker's control. Here's a pretty telling crash: bash[3054]: segfault at 41414141 ip 00190d96 ... Soon after posting this entry, I also bumped in the sixth and most severe issue so far, essentially permitting very simple and straightforward remote code execution (CVE-2014-6278) on the systems that are patched against the first bug. It's a "put your commands here" type of a bug similar to the original report. I will post additional details in a couple of days to give people enough time to upgrade.

At this point, I very strongly recommend manually deploying Florian's patch unless your distro is already shipping it. (Florian's patch has been also finally included upstream shortly after I first posted this entry.)

From within the shell itself, the simplest way to check if you already have it installed would be: _x='() { echo vulnerable; }' bash -c '_x 2>/dev/null || echo not vulnerable' If the command shows "vulnerable", you don't have the patch and you are still vulnerable to a (currently non-public) RCE, even if you applied the original one (or the subsequent upstream patch that addressed the issue found by Tavis).

13 comments:

  1. "The patch should apply cleanly to bash 4.2, but requires one minor tweak for 4.3." I'm trying to apply it to 4.3.25(1), what's the "one minor tweak" that you're referring to?

    ReplyDelete
    Replies
    1. One chunk in variables.c will fail because of few extra lines around:

      report_error (_("error importing function definition for `%s'"), name);

      In essence, you should reconcile what ends up in variables.c.rej manually. Most of it should be obvious. The "Restore the original suffix." part from the patch should go right after the first closing curly bracket underneath the existing "error importing function definition" bit.

      Delete
    2. ie.
      else
      {
      if (temp_var = bind_variable (name, string, 0))
      {
      VSETATTR (temp_var, (att_exported | att_imported | att_invisible));
      array_needs_making = 1;
      }
      last_command_exit_value = 1;
      report_error (_("error importing function definition for `%s'"), name);
      }

      /* Restore the original suffix. */
      temp_name[name_length] = FUNCDEF_SUFFIX[0];
      ...right?

      Delete
    3. nvm, http://www.mail-archive.com/arch-commits@archlinux.org/msg189041.html clarified it for me. thanks!

      Delete
  2. These "toughten the feature" patches still feel quite scary.

    Since the feature seem to be so rarely used, how come it isn't off by default already ? Enable it via some ENV var or shopt (bonus point if you can restrict it to specific variable names), and let people who need it take the necessary security steps.

    ReplyDelete
  3. I have a question. When my bash is vulnerable to CVE-2014-6278, How do i check this vulnerablity?? Is the same the result of CVE-2014-6277???

    ReplyDelete
    Replies
    1. There's only one patch, addressing both. The test case provided at the bottom of the blog post tests for the presence of this patch.

      Delete
  4. Not vulnerable to CVE-2014-6271 (original shellshock)
    Not vulnerable to CVE-2014-7169 (taviso bug)
    Not vulnerable to CVE-2014-7186 (redir_stack bug)
    Test for CVE-2014-7187 not reliable without address sanitizer
    /volume1/backups/bash/bashcheck/bashcheck.sh: line 42: 9587 Segmentation fault (core dumped) $bash -c "f(){ x(){ _;};x(){ _;}<<a;}"
    Vulnerable to CVE-2014-6277 (lcamtuf bug #1) [no patch]
    Variable function parser inactive, likely safe from unknown parser bugs

    Same patchset, same test on arm v5/v7:

    Testing /opt/bin/bash ...
    GNU bash, version 4.3.28(1)-release (armv5tel-unknown-linux-gnueabi)

    Not vulnerable to CVE-2014-6271 (original shellshock)
    Not vulnerable to CVE-2014-7169 (taviso bug)
    Not vulnerable to CVE-2014-7186 (redir_stack bug)
    Test for CVE-2014-7187 not reliable without address sanitizer
    /opt/bin/bash: warning: here-document at line 0 delimited by end-of-file (wanted `a')
    Not vulnerable to CVE-2014-6277 (lcamtuf bug #1)
    Variable function parser inactive, likely safe from unknown parser bugs

    ReplyDelete
    Replies
    1. Sigh, this Google thing actually screwed my previous comment: The first part (vulnerable) output is with GNU bash, version 4.3.28(1)-release (powerpc-unknown-linux-gnu)

      Are the tests at https://github.com/hannob/bashcheck/blob/master/bashcheck actually valid?

      Delete
    2. They are probably OK, although I certainly haven't tested on ARM. But for most part, just get Florian's patch and be done with it, there's little value in testing for individual issues.

      Delete
    3. But it's already applied! Better said, the upstream one: http://ftp.gnu.org/gnu/bash/bash-4.3-patches/bash43-027 ; also the today's 028 patch is applied. Why's the thing *still* segfaulting on PowerPC and not ARM or x86/amd64?

      Delete
  5. Thanks for watching our backs and catching the bash s/w defect. Can you post some more tests here to help us evaluate whether our bash is vulnerable?

    ReplyDelete
    Replies
    1. See http://lcamtuf.blogspot.com/2014/10/bash-bug-how-we-finally-cracked.html

      Delete

Note: Only a member of this blog may post a comment.