1

In someone's reply to one of my posts (which I forgot), I remember

bash -c "somecommand \$1" bash $somevariable

instead of

bash -c "somecommand $somevariable"

I saw this example again in findutils manual

find -exec sh -c 'something "$@"' sh {} \;

instead of

find -exec sh -c "something {}" \;

Do the two examples have the same reason to use the first solution instead of the other solution? If yes, what is it?

Inspired Why does command injection not work in this example? and Is the following the only form of command injection in bash?

Tim
  • 101,790
  • 2
    The answer is explained in the question you linked to in your question (https://unix.stackexchange.com/q/448443/674):

    The reason for this is that the ‘{}’ is expanded to a filename which might contain a semicolon or other characters special to the shell. If for example someone creates the file /tmp/foo; rm -rf $HOME then the two commands above could delete someone’s home directory.

    – Tim Kennedy Jun 07 '18 at 15:26
  • The last find example will usually not work as POSIX only grants that simple {} arguments are expanded at all. – schily Jun 07 '18 at 15:52
  • @schily, depends on what you mean with "usually". GNU find replaces {} anywhere in the strings, and according to documentation, so do the finds on FreeBSD and OpenBSD. So does the one that comes on Macs. I suppose those together are a significant portion of the finds in use. – ilkkachu Jun 07 '18 at 19:10
  • 1
    AIX does not expand it, HP-UX does not, Solaris does not, sfind/libfind does not. Looks like a 4:3 ration against expansion. – schily Jun 07 '18 at 19:22
  • 1
    @schily, AIX, HP-UX and Solaris AFAIK all have the the same AT&T find implementation and account for probably less than 1% of the systems in operation on topic on unix.stackexchange.com. GNU+busybox+freebsd+macOS probably account for more than 90% of the find implementations out there, and all do the expansions. (I'd rather they didn't though as that would get rid of a lot vulnerabilities in poorly written scripts). Or IOW, most people will have never come across an implementation that doesn't do the expansion. – Stéphane Chazelas Jun 08 '18 at 14:59
  • If AIX did have AT&T based sources, it did not confuse uname -v and uname -r. HP-UX is also not really AT&T based. Today one of the most implortant implementations is libfind that is used by many programs in order to implement a find(1) compatible CLI interface inside programs. – schily Jun 08 '18 at 15:12

1 Answers1

1

Yes. Both examples should pass the arguments to bash -c or sh -c as arguments (probably quoted) rather than injecting them into the code as strings.

Injecting code as a string into the in-line shell script would potentially allow the injected string to break out of control structures and execute arbitrary commands, or having the shell execute expansions that should be treated as text.

Example:

bash -c "echo $arg"

with $arg set to the string ; ls -la.

In the find example, this becomes an issue when filenames or pathnames breaks the syntax of the shell script that they are injected into or modifies the control flow, possibly with unwanted consequences.

Additional reference:

Kusalananda
  • 333,661