Unfortunately, there's a lot of gotchas in Bash like this. A lot of them are documented here: <a href="https://mywiki.wooledge.org/BashPitfalls" rel="nofollow">https://mywiki.wooledge.org/BashPitfalls</a>, including the `test -v` case, which is #61. Some more code execution pitfalls are documented here: <a href="https://mywiki.wooledge.org/BashProgramming/05?action=show&redirect=CodeInjection" rel="nofollow">https://mywiki.wooledge.org/BashProgramming/05?action=show&r...</a> including the `-eq` part (under Arithmetic Expansion).<p>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"<p>Note that the `-v` case doesn't really work the way one may infer from reading the OP:<p>> $ key='$(cat /etc/passwd > /tmp/pwned)'<p>> $ [[ -v 'x[$key]' ]]<p>> bash: $(cat /etc/passwd > /tmp/pwned): syntax error: operand expected (error token is "$(cat /etc/passwd > /tmp/pwned)") *<p>> [[ -v "${x[$key]}" ]]<p>> bash: $(cat /etc/passwd > /tmp/pwned): syntax error: operand expected (error token is "$(cat /etc/passwd > /tmp/pwned)")
Yuck, I was always instinctively put off by [[, now I finally have some arguments to justify it.<p>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.
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.
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:<p><pre><code> function guess () { declare -i num="${1}" ; }
</code></pre>
(unless I'm missing something?)
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.
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.
Question: why does the evaluation inside a[] (which does not produce a value) not result in a bad array subscript error in this case?<p>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).
My first insinct would be to remove the bashisms first:<p><a href="https://gist.github.com/alganet/a4198158651f3b2dc43ce658052e2aa0" rel="nofollow">https://gist.github.com/alganet/a4198158651f3b2dc43ce658052e...</a><p>Then, if we run it:<p>"line 3: test: a[$(cat /etc/passwd > /tmp/pwned)] + 42: integer expression expected"