Is the behavior behind the Shellshock vulnerability in Bash documented or at all intentional?

前端 未结 4 801
余生分开走
余生分开走 2020-11-30 03:26

A recent vulnerability, CVE-2014-6271, in how Bash interprets environment variables was disclosed. The exploit relies on Bash parsing some environment variable declarations

相关标签:
4条回答
  • 2020-11-30 04:04

    I think it's worth looking at the Bash code itself. The patch gives a bit of insight as to the problem. In particular,

    *** ../bash-4.3-patched/variables.c 2014-05-15 08:26:50.000000000 -0400
    --- variables.c 2014-09-14 14:23:35.000000000 -0400
    ***************
    *** 359,369 ****
          strcpy (temp_string + char_index + 1, string);
    
    !     if (posixly_correct == 0 || legal_identifier (name))
    !       parse_and_execute (temp_string, name, SEVAL_NONINT|SEVAL_NOHIST);
    !
    !     /* Ancient backwards compatibility.  Old versions of bash exported
    !        functions like name()=() {...} */
    !     if (name[char_index - 1] == ')' && name[char_index - 2] == '(')
    !       name[char_index - 2] = '\0';
    
          if (temp_var = find_function (name))
    --- 364,372 ----
          strcpy (temp_string + char_index + 1, string);
    
    !     /* Don't import function names that are invalid identifiers from the
    !        environment, though we still allow them to be defined as shell
    !        variables. */
    !     if (legal_identifier (name))
    !       parse_and_execute (temp_string, name, SEVAL_NONINT|SEVAL_NOHIST|SEVAL_FUNCDEF|SEVAL_ONECMD);
    
          if (temp_var = find_function (name))
    

    When Bash exports a function, it shows up as an environment variable, for example:

    $ foo() { echo 'hello world'; }
    $ export -f foo
    $ cat /proc/self/environ | tr '\0' '\n' | grep -A1 foo
    foo=() {  echo 'hello world'
    }
    

    When a new Bash process finds a function defined this way in its environment, it evalutes the code in the variable using parse_and_execute(). For normal, non-malicious code, executing it simply defines the function in Bash and moves on. However, because it's passed to a generic execution function, Bash will correctly parse and execute additional code defined in that variable after the function definition.

    You can see that in the new code, a flag called SEVAL_ONECMD has been added that tells Bash to only evaluate the first command (that is, the function definition) and SEVAL_FUNCDEF to only allow functio0n definitions.

    0 讨论(0)
  • 2020-11-30 04:14

    In regard to your question about documentation, notice here in the commandline documentation for the env command, that a study of the syntax shows that env is working as documented.

    • There are, optionally, 4 possible options
    • An optional hyphen as a synonym for -i (for backward compatibility I assume)
    • Zero or more NAME=VALUE pairs. These are the variable assignment(s) which could include function definitions.
    • Note that no semicolon (;) is required between or following the assignments.
    • The last argument(s) can be a single command followed by its argument(s). It will run with whatever permissions have been granted to the login being used. Security is controlled by restricting permissions on the login user and setting permissions on user-accessible executables such that users other than the executable's owner can only read and execute the program, not alter it.
    [ spot@LX03:~ ] env --help
    Usage: env [OPTION]... [-] [NAME=VALUE]... [COMMAND [ARG]...]
    Set each NAME to VALUE in the environment and run COMMAND.
    
      -i, --ignore-environment   start with an empty environment
      -u, --unset=NAME           remove variable from the environment
          --help     display this help and exit
          --version  output version information and exit
    
    A mere - implies -i.  If no COMMAND, print the resulting environment.
    
    Report env bugs to bug-coreutils@gnu.org
    GNU coreutils home page: <http://www.gnu.org/software/coreutils/>
    General help using GNU software: <http://www.gnu.org/gethelp/>
    Report env translation bugs to <http://translationproject.org/team/>
    
    0 讨论(0)
  • 2020-11-30 04:15

    This seems like an implementation bug.

    Apparently, the way exported functions work in bash is that they use specially-formatted environment variables. If you export a function:

    f() { ... }
    

    it defines an environment variable like:

    f='() { ... }'
    

    What's probably happening is that when the new shell sees an environment variable whose value begins with (), it prepends the variable name and executes the resulting string. The bug is that this includes executing anything after the function definition as well.

    The fix described is apparently to parse the result to see if it's a valid function definition. If not, it prints the warning about the invalid function definition attempt.

    This article confirms my explanation of the cause of the bug. It also goes into a little more detail about how the fix resolves it: not only do they parse the values more carefully, but variables that are used to pass exported functions follow a special naming convention. This naming convention is different from that used for the environment variables created for CGI scripts, so an HTTP client should never be able to get its foot into this door.

    0 讨论(0)
  • 2020-11-30 04:15

    The following:

    x='() { echo I do nothing; }; echo vulnerable' bash -c 'typeset -f'
    

    prints

    vulnerable
    x () 
    { 
        echo I do nothing
    }
    declare -fx x
    

    seems, than Bash, after having parsed the x=..., discovered it as a function, exported it, saw the declare -fx x and allowed the execution of the command after the declaration.

    echo vulnerable

    x='() { x; }; echo vulnerable' bash -c 'typeset -f'
    

    prints:

    vulnerable
    x () 
    { 
        echo I do nothing
    }
    

    and running the x

    x='() { x; }; echo Vulnerable' bash -c 'x'
    

    prints

    Vulnerable
    Segmentation fault: 11
    

    segfaults - infinite recursive calls

    It doesn't overrides already defined function

    $ x() { echo Something; }
    $ declare -fx x
    $ x='() { x; }; echo Vulnerable' bash -c 'typeset -f'
    

    prints:

    x () 
    { 
        echo Something
    }
    declare -fx x
    

    e.g. the x remains the previously (correctly) defined function.

    For the Bash 4.3.25(1)-release the vulnerability is closed, so

    x='() { echo I do nothing; }; echo Vulnerable' bash -c ':'
    

    prints

    bash: warning: x: ignoring function definition attempt
    bash: error importing function definition for `x'
    

    but - what is strange (at least for me)

    x='() { x; };' bash -c 'typeset -f'
    

    STILL PRINTS

    x () 
    { 
        x
    }
    declare -fx x
    

    and the

    x='() { x; };' bash -c 'x'
    

    segmentation faults too, so it STILL accept the strange function definition...

    0 讨论(0)
提交回复
热议问题