Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Quoting the Shell could mention the use of the environment to eschew shell quoting/escaping issues #202

Closed
ghost opened this issue Aug 18, 2019 · 4 comments
Assignees
Labels
article: update Update an existing article

Comments

@ghost
Copy link

ghost commented Aug 18, 2019

Thanks for writing this article, as a lot of people struggle with shell quoting issues. I think that it might be worthwhile mentioning that, by controlling the environment, it is trivial to side-step shell quoting issues. Here is an example:

#!/usr/bin/env perl

sub test {
	local $ENV{MY_VAR} = 'No "problem here", sir!';
	system 'touch -- "$MY_VAR" && ls -l -- "$MY_VAR"';
}

test();

This will result in something like the following, proving its efficacy.

-rw-r--r-- 1 kerframil kerframil 0 2019-08-18 03:13 No "problem here", sir!

Indeed, this method is highly reliable and is also resilient to shell code injection. The only limitation is that the exported variable should not contain a null byte, otherwise it will result in a truncated expansion. This is an intrinsic limitation of sh, and has to do with C using \0 as a string terminator. Note also that, in Unix-like operating systems, a path may not contain the null byte anyway.

But hang on, you may ask! Why bother, when we can just bypass the shell by conveying an argument vector to a specific executable via the system function in the first place? Well, granted, the example shown is only an academic one. However, this method can - at times - be genuinely useful in practice. Here are some reasons why.

  • Sometimes, a developer may wish to deliberately exploit shell features but without having to jump through hoops making strings safe for injection into the shell code.

  • This technique accomplishes such without having to second-guess what the shell considers to be a meta-character and having to escape/quote accordingly. By delegating (environment) variable expansion directly to the shell, it simply no longer matters. EDIT: It works just as well in zsh, for instance.

  • This technique eliminates the possibility of code injection, unless doing 'interesting' things with eval in the shell.

  • This technique is applicable outside of Perl, and is exceptionally useful for evil languages - such as PHP - that make it comparatively difficult to avoid invoking /bin/sh when creating a sub-process. It can even be leveraged to good effect in applications such as Puppet, for example.

In summary, while I always recommend avoiding the invocation of sh by default, there are some cases where it's difficult to avoid, or even desirable. In that case, this is - in my experience - a little known technique that is worth being mindful of.

@ghost
Copy link
Author

ghost commented Aug 18, 2019

Just to expand upon the point about code injection …

#!/usr/bin/env perl

sub test1 {
	my $var = 'foo $(echo gotcha >&2)';
	system "touch -- \"$var\" && ls -l -- \"$var\"";
}

sub test2 {
	local $ENV{MY_VAR} = 'foo $(echo gotcha >&2)';
	system 'touch -- "$MY_VAR" && ls -l -- "$MY_VAR"';

}

print "test1:\n"; test1();
print "test2:\n"; test2();

Results in …

test1:
gotcha
gotcha
-rw-r--r-- 1 kerin kerin 0 2019-08-18 03:46 foo 
test2:
-rw-r--r-- 1 kerin kerin 0 2019-08-18 03:46 foo $(echo gotcha >&2)

As can be seen, the shell did exactly what it was supposed to in the second case.

@dnmfarrell
Copy link
Contributor

Hey thanks for opening this issue; that is a novel solution! Let me have a think about it.

@dnmfarrell dnmfarrell self-assigned this Sep 11, 2019
@briandfoy
Copy link
Contributor

briandfoy commented Sep 16, 2019

This is a great suggestion. I'll make the addition soon.

@briandfoy briandfoy self-assigned this Sep 16, 2019
@briandfoy briandfoy added the site: enhancement The website could be better or different label Sep 16, 2019
@briandfoy briandfoy added article: update Update an existing article and removed site: enhancement The website could be better or different labels Feb 25, 2021
@briandfoy
Copy link
Contributor

In the end, I simply lifted the now-deleted user's explanation. It will be part of the next update.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
article: update Update an existing article
Projects
None yet
Development

No branches or pull requests

2 participants