from Hacker News

TIL: Some surprising code execution sources in bash

by nathan_phoenix on 11/22/24, 10:43 AM with 46 comments

  • by mmsc on 11/22/24, 4:30 PM

    Unfortunately, there's a lot of gotchas in Bash like this. A lot of them are documented here: https://mywiki.wooledge.org/BashPitfalls, including the `test -v` case, which is #61. Some more code execution pitfalls are documented here: https://mywiki.wooledge.org/BashProgramming/05?action=show&r... including the `-eq` part (under Arithmetic Expansion).

    Basically, the -v case was by design, so for `-v 'hash[$key]'`, "$key is expanded before the array subscript evaluation, and then the whole array plus expanded index is evaluated in a second pass". "Newer versions of bash (5.0 and higher) have a assoc_expand_once option which will suppress the multiple evaluations"

    Note that the `-v` case doesn't really work the way one may infer from reading the OP:

    > $ key='$(cat /etc/passwd > /tmp/pwned)'

    > $ [[ -v 'x[$key]' ]]

    > bash: $(cat /etc/passwd > /tmp/pwned): syntax error: operand expected (error token is "$(cat /etc/passwd > /tmp/pwned)") *

    > [[ -v "${x[$key]}" ]]

    > bash: $(cat /etc/passwd > /tmp/pwned): syntax error: operand expected (error token is "$(cat /etc/passwd > /tmp/pwned)")

  • by PhilipRoman on 11/22/24, 3:23 PM

    Yuck, I was always instinctively put off by [[, now I finally have some arguments to justify it.

    IMO safe shell scripting is kind of dead. I can do it if I really have to, but too many external programs have tricky "convenience" features like interpreting flags after positional parameters, etc.

  • by voidfunc on 11/22/24, 4:24 PM

    So many footguns in bash. When do we finally get serious about ditching this language as an industry in the same way we are about memory safety?
  • by spiffytech on 11/22/24, 4:12 PM

    What's the fix for those code samples?

    Shellcheck currently gives Sample 1 a pass. I hope this is something it can be modified to catch.

  • by webstrand on 11/22/24, 3:40 PM

    I... don't understand. I thought the whole reason for using [[ and breaking posix compatibility was to prevent just this kind of vulnerability. Why would bash do this.
  • by tpoacher on 11/22/24, 4:38 PM

    From what I understand, based on the premise that this results from switching into 'arithmetic' mode, you don't even need test. The following will also work with the proposed attack:

      function guess () { declare -i num="${1}" ; }
    
    (unless I'm missing something?)
  • by zettabomb on 11/22/24, 3:51 PM

    Honestly I just don't write shell scripts anymore, bash or otherwise. By the time any system I use is up, Python is available. I don't know if I've found a true need for shell in anything application level. I'll even fire up a Python shell for something simple like mass renaming files, simply because the string manipulation is so much easier.
  • by IYasha on 11/24/24, 8:00 AM

    I have a related question: is integer/"((math))" logic really safer (in bash) than "[normal]"? I usually try hard to use declare -i iMyVar; as many applicable variables as possible. But evaluation of strings is still usually a hellhole... I mean hole hell.
  • by tpoacher on 11/22/24, 4:45 PM

    Question: why does the evaluation inside a[] (which does not produce a value) not result in a bad array subscript error in this case?

    if you try to evaluate this kind of things as an arithmetic expression directly, it will fail with an error of a bad subscript (mind you, the attack will still work though).

  • by alganet on 11/22/24, 3:17 PM

    My first insinct would be to remove the bashisms first:

    https://gist.github.com/alganet/a4198158651f3b2dc43ce658052e...

    Then, if we run it:

    "line 3: test: a[$(cat /etc/passwd > /tmp/pwned)] + 42: integer expression expected"