[Toybox] Shell corner cases.
Chet Ramey
chet.ramey at case.edu
Thu May 1 08:29:11 PDT 2025
On 4/30/25 6:23 PM, Rob Landley wrote:
> Somebody forwarded that to me from an exploit how-to site. It's apparently
> a trick used to subvert scripts that call things via absolute path to avoid
> malicious $PATH.
I suppose if you can get a script to source an arbitrary file, you can do
pretty much anything.
> $ x() { echo hello; }; D=x; $D
> hello
OK? Commands are parsed, then executed.
>
>> Since alias expansion happens when the command is
>> read and tokenized,
>
> Yeah, that was the weird part. My code breaks argv[] into separate chunks
> but doesn't try to figure out what they _mean_ until it needs to run them,
> because:
>
> $ alias one='$X'
> $ X='$A'; A=$X one
> bash: $A: command not found
>
> Is still figuring out that it has to move past the prefix assignment to
> expand the alias, so you're saying your "tokenization" recognizes prefix
> assignments...
Alias expansion happens on the first word of a simple command (for our
purposes here). The first word of a simple command that's going to be
eligible for alias expansion is a WORD, not an ASSIGNMENT_WORD.
The parser knows when it's going to read a command, so it knows when to
expect a simple command, and if it reads an assignment statement in that
position, it knows it's an ASSIGNMENT_WORD. Only WORDs in the right
position are eligible for alias expansion -- it's context-dependent.
As POSIX puts it:
"Further distinction on TOKEN is context-dependent. It may be that the same
TOKEN yields WORD, a NAME, an ASSIGNMENT_WORD, or one of the reserved words
below, dependent upon the context."
>
>> the list will be parsed before any of the commands
>> are executed. This is how Bourne-style shells work.
>
> The logic of what counts as a "line" in this context is unclear to me:
Oh, we had a rocking discussion about that topic, and the comments here
aren't half of it.
https://www.austingroupbugs.net/view.php?id=953
>
> $ bash -c $'echo $LINENO;alias a=b\necho $LINENO;a'
> 1
> 2
> bash: line 2: a: command not found
Anywhere the shell executes a string (the command_string argument to
`sh -c', `eval', command substitution bodies), it parses the entire string
as a compound_list and then executes that list.
> Wouldn't trigger (like it does for functions).
>
> Then again busybox ash, mksh, zsh, and even dash are all doing this too, so
> I guess "compatible" beats "sane". Maybe it's so you can do:
>
> alias potato=fruitbat
> source filename
> unalias potato
See above about compound_list parsing.
>
> And, of course:
>
> $ alias one=two
> $ on\e
> bash: one: command not found
When that is tokenized, the backslash is still part of the word, so it
can't match an alias name.
Chet
--
``The lyf so short, the craft so long to lerne.'' - Chaucer
``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRU chet at case.edu http://tiswww.cwru.edu/~chet/
-------------- next part --------------
A non-text attachment was scrubbed...
Name: OpenPGP_signature.asc
Type: application/pgp-signature
Size: 203 bytes
Desc: OpenPGP digital signature
URL: <http://lists.landley.net/pipermail/toybox-landley.net/attachments/20250501/7d733fbd/attachment.sig>
More information about the Toybox
mailing list