|
>Simple trick behind this technique is that when using shell wildcards, especially asterisk (...), Unix shell will interpret files beginning with hyphen (-) character as command line arguments to executed command/program. To be clear, the shell isn't really 'interpreting' anything here — it knows absolutely nothing about the argument conventions of whatever program you're running[0]. All it's doing is passing a list of arguments to an executable; how the executable deals with that is up to it. And this isn't only a shell problem — it's an issue when you pass arbitrary arguments to ANY external utility in ANY language. For example, maybe you have some kind of tool that calls grep: # Perl
exec '/usr/bin/grep', '-R', $input, 'mydir';
# PHP (with Symfony Process)
(new Process(['/usr/bin/grep', '-R', $input, 'mydir']))->run();
# Python
subprocess.run(['/usr/bin/grep', '-R', input, 'mydir'])
# C
execv("/usr/bin/grep", (char *[]) {"grep", "-R", input, "mydir", NULL});
All of these are safe in the sense that there's no risk of shell command injection (in fact, only the PHP one even calls the shell), but NONE of them are safe against this problem, where the input value might begin with a hyphen. In this grep scenario it's probably not a security issue, but it can produce confusing results for the user if nothing else.As others mentioned, you must ALWAYS use '--' to mark the end of option processing when you do something like this. [0] Technically the shell knows about the conventions of its built-ins, but even those mostly handle arguments in a similar fashion to external utilities, where an arbitrary argv is fed to a function and then parsed using some getopts-like method. |
I tried to think of an example where it could create a problem and the best I could do so far is injecting -f /sensitive-file/that-the-user/otherwise-cannot-read, supposing that mydir contains instances of the sensitive things, or that the contents of mydir are under the user's control.
So for example, suppose that the user has SFTP access to upload stuff to mydir, and suppose that there's a file /etc/spynames containing a list of spies (but it's mode 660 so the user normally can't read it). Maybe the grep command gets run with user-provided input and with the same group as /etc/spynames, and so then the user could SFTP upload a file containing suspected spies, and then inject causing the execution of
/usr/bin/grep -R -f /etc/spynames mydir
The output will be lines that are also present in /etc/spynames.
Edit: apparently -f/etc/spynames will be parsed as -f /etc/spynames, and so it isn't even necessary to be able to inject a space. I bet some form of this attack works on hundreds of deployed Internet services.