This has less to do with wildcards and more with passing arbitrary filenames to commands without making sure they are not interpreted as options. That these filenames come from the expansion of * is irrelevant - they could just as well be read from a file. This "vulnerability" doesn't even need to involve a shell at all - any exec*() with the same arguments will have the same result.
Most commands provide a "--" flag to indicate that all further arguments are not to be interpreted as anything other than filenames/whatever non-option arguments the command consumes.
GNU chmod/chown include this. I don't remember if stock tools on SunOS did, but I'd often use GNU coreutils compiled for Sun as they had more features.
> This has less to do with wildcards and more with passing arbitrary filenames
I think the issue being pointed out was that wildcards are expanded to filenames before parsing of arguments, which of course means you may not know what all filenames you're passing.
While this is something we all know, it can certainly slip through the cracks when you decide you just want to delete everything in the folder.
> This "vulnerability" ...
I don't know that it's a vulnerability proper so much as a warning to think before hitting enter.
Kinda true, but in a typical shell script (or even any other kind of program) there aren't many user controlled variables that would typically be incorporated directly into a command invocation. Pathname expansions are the most common and likely vector because it's common to both introspect directory trees and then pass those file paths as arguments to other utilities.
That's why I always put a line like
set -f # disable pathname expansion
at the top of my shell scripts, in addition to several other settings (e.g. -e, -u, and -C). Because file globbing is a common operation in shell scripts I invariably have to re-enable it locally (e.g. set +f; set -- *; set -f; for F; do ...; done) somewhere. That extra work reinforces that pathnames are tainted, making it easier to remember to use the "--" option argument terminator where ever else I pass file names--particularly names not statically defined in the script--whether they come from globbing or some other route.
As an aside, I really dislike GNU-style argument vector permuting, where getopt/getopt_long rearranges "cmd foo bar -x" to be "cmd -x foo bar". On BSD doing something like 'ls /tmp "$X"', where X is user controlled, is relatively safe because "/tmp" terminates option parsing. Not so with GNU getopt. I get the convenience of permuting the vector, but I just don't think it's worth the cost in terms of security (it's a dangerously nuanced semantic) or in terms of the size of the GNU getopt/getopt_long implementation (it could be many times simpler and shorter, not to mention requiring only a constant amount of work and memory, but-for the permuting).
This is really a vulnerability that applies in any case where you pass user supplied arguments to a command line program. Suppose you have a bunch of files on a server and you allow the user to send a list of files that they want to download as tar. You're careful to avoid directory traversal attacks so you reject filenames that contain slashes. Then, you do:
exec(["tar", "cz", ...user_wanted_files])
The user sends you a GET /api/storage/download_tar?files=--checkpoint%3D1&files=--checkpoint-action%3Dexec%3Dsh+shell.sh which causes you to execute the contents of shell.sh. No shell, no glob necessary.
Windows in this regard does it right. It provides standard calls for expanding globs, but the glob handling is handled purely in the application logic, not in the shell itself.
There are some advantages to doing this in the shell, but really they are dwarfed by the problems that are caused by users not being very careful about quoting and "--" arguments.
There's no problem for folks who know the "secret." But what is the utility?
None, IMHO. I've never named a file starting with a dash in my career or as a child, except as an experiment to see if it could be done. Files promptly deleted afterward.
20 comments
[ 2.9 ms ] story [ 54.9 ms ] threadMost commands provide a "--" flag to indicate that all further arguments are not to be interpreted as anything other than filenames/whatever non-option arguments the command consumes.
I think the issue being pointed out was that wildcards are expanded to filenames before parsing of arguments, which of course means you may not know what all filenames you're passing.
While this is something we all know, it can certainly slip through the cracks when you decide you just want to delete everything in the folder.
> This "vulnerability" ...
I don't know that it's a vulnerability proper so much as a warning to think before hitting enter.
That's why I always put a line like
at the top of my shell scripts, in addition to several other settings (e.g. -e, -u, and -C). Because file globbing is a common operation in shell scripts I invariably have to re-enable it locally (e.g. set +f; set -- *; set -f; for F; do ...; done) somewhere. That extra work reinforces that pathnames are tainted, making it easier to remember to use the "--" option argument terminator where ever else I pass file names--particularly names not statically defined in the script--whether they come from globbing or some other route.As an aside, I really dislike GNU-style argument vector permuting, where getopt/getopt_long rearranges "cmd foo bar -x" to be "cmd -x foo bar". On BSD doing something like 'ls /tmp "$X"', where X is user controlled, is relatively safe because "/tmp" terminates option parsing. Not so with GNU getopt. I get the convenience of permuting the vector, but I just don't think it's worth the cost in terms of security (it's a dangerously nuanced semantic) or in terms of the size of the GNU getopt/getopt_long implementation (it could be many times simpler and shorter, not to mention requiring only a constant amount of work and memory, but-for the permuting).
Wildcard expansions are done by shells, so no, exec() wouldn't trigger this "vulnerability".
Unless you're talking about a specific language's exec() that either does its own wildcard expansion, or actually runs its arguments in a shell.
To do it correctly, you would have to do:
Or add ./ to the start of each filename.https://offensi.com/2020/08/18/how-to-contact-google-sre-dro...
>An attempt to modify the database name in the API call from ‘mysql’ into ‘--help’ results into something that surprised us...
There are some advantages to doing this in the shell, but really they are dwarfed by the problems that are caused by users not being very careful about quoting and "--" arguments.
None, IMHO. I've never named a file starting with a dash in my career or as a child, except as an experiment to see if it could be done. Files promptly deleted afterward.