Re: Trojan Horse? (taint mode)
by blakem (Monsignor) on Nov 25, 2001 at 15:37 UTC
|
Here is the relevant portion of the text from page 13: (I believe this is fair use)
Trojan horses
While we are talking about obfuscation, it is worth talking about a very insidious way of including executable code within strings. Normally, when Perl sees a string such as "$a", it does variable interpolation. But you now know that "a" can be replaced by a block as long as it returns a reference to a scalar, so something like this is perfectly acceptable, even within a string:
print "${foo()}";
Replace foo() by system ('/bin/rm *') and you have an unpleasant Trojan Horse.
print "${system('/bin/rm *')}"
Perl treats it like any other function and trusts system to return a reference to a scalar. The parameters given to system do their damage before Perl has a chance to figure out that system doesn't return a scalar reference.
Moral of the story: Be very careful of strings that you get from untrusted sources. Use the taint-mode option (invoke Perl as perl -T) or the Safe module that comes with the Perl distribution. Please see the Perl documentation for taing checking, and see the index for som pointers to the Safe module.
At the very best this is correct but unclear... at the worst it is just plain wrong. The above implies (but doesn't exactly state) that this would wreak havoc on your machine:
$a = q|{system('/bin/rm -rf *')}|;
print "$a";
but, as has been stated above, the output of this snippet is simply the value of $a.... no external commands are executed.
Unless I'm overlooking something, this looks like an Errata to me.
-Blake
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
I think its very clear... I decided to try it as the author stated above. I used echo because well - I like my system the way it is. And its a good thing I did too because the command executed. This is what I have:
#!/usr/bin/perl
$a ="${system(\"echo 'hello from system'\")}\n";
print "$a";
And this is the output:
hello from system
stupid.pl
I think this is what the author is talking about. Now when I use the q or qq it responds as you said so I guess that perl treats qq differently than an actual double quote. Something I didn't know. Interestingly enough it prints the name of the script out as well when this command executes... not sure why. | [reply] [Watch: Dir/Any] [d/l] [select] |
|
I see no difference in the behavior of the following two lines:
$a = qq|${system("echo 'hello from system'")}\n|;
$a = "${system(\"echo 'hello from system'\")}\n";
They both execute the 'echo' command which sends a message to your terminal and returns 0. My perl (5.00503 and 5.6.1 on unix) then complains that 0 is not a scalar ref and dies. Apparently your perl is casting the return value of 0 into a scalar ref to 0, and $a is assigned the value of $0, which happens to be the name of the script.
The book seems to imply that this behavior emulates what would happen if $a had come from user input. Fortunately that is not the case. If $a had come from STDIN, none of the above caveats would apply. Try it:
#!/usr/bin/perl -wT
use strict;
my $a = <STDIN>;
chomp($a);
print "$a";
</code>
-Blake
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
Re: Trojan Horse? (taint mode)
by dws (Chancellor) on Nov 25, 2001 at 10:53 UTC
|
I'm under the impression that tainted data is mainly a concern if you're going to eval it, or pass it to system or backticks, are there any really sneaky situations that I'm missing?
open(IN, $file);
can really spoil your day if $file contains
"| rm -f *"
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
The author warns that a string like "$a" does variable interpolation. No surprise there. Then he say's "But you now know that "a" can be replaced ba a block as long as it returns a reference to a scalar..." and so we should be worried about someone filling a variable with {system('/bin/rm -rf /*')} and maybe doing 'bad things' to us.
In my humble opinion, by his statement, "a" can be replaced, the original author may be discussing literally replacing the letter 'a' in the expression, "$a", with an actual (curly brace-delimited) block of code; in other words, changing the expression (quotes and all), "$a" to the different other expression, "${system('/bin/rm -rf /*')}", not necessarily assigning such a string as "{system('/bin/rm -rf /*')}", to the variable, $a and interpolating that.
I by no means intend, by posting this reply, to minimize the importance of the interpolation discussions. Nor is it my purpose to cast a pall on any of the extemely pertinant, valid points made in any of those threads.
However, the questions being discussed do not seem to me to be addressing the behavior described (as I read it) by the original author (not that it was especially well written). Perhaps all is right with the world and interpolation is, in fact, predictable.
dmm
You can give a man a fish and feed him for a day ...
Or, you can teach him to fish and feed him for a lifetime
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
| [reply] [Watch: Dir/Any] [d/l] |
Re: Trojan Horse? (taint mode)
by jarich (Curate) on Nov 25, 2001 at 13:06 UTC
|
Perl interpolates variables in double quoted strings safely.
Everything in the variable is considered to be a literal.
So
my $a = q#${system('rm -rf /')}#;
print "The command in \$a is $a\n";
will print out:
The command in $a is ${system('rm -rf /')}
and not even attempt to remove my files. Likewise this
my $b = "The command in \$a is $a\n";
sets $b to the string we printed out. Printing $b does
exactly the same as the above. The only way this
is going to come and cause us grief is if we eval $a - as
you've suggested.
Perhaps the author is mistaken or you've misunderstood the
reference, can you post the paragraph or two? I've checked
the book errata and it's not mentioned anywhere there, but it's
a pretty big mistake if you haven't misunderstood it.
Even authors make mistakes. :) | [reply] [Watch: Dir/Any] [d/l] [select] |
|
| [reply] [Watch: Dir/Any] |
Re: Trojan Horse? (taint mode)
by chromatic (Archbishop) on Nov 25, 2001 at 23:15 UTC
|
chomp(my $input = <STDIN>);
print "$input\n";
Feed this one the shell command above (a nice variable dereferencing scheme) and it'll print out literally.
Unless you're doing hazardous things with string eval, you're probably safe. | [reply] [Watch: Dir/Any] [d/l] [select] |
Re: Trojan Horse? (taint mode)
by IraTarball (Monk) on Nov 25, 2001 at 20:27 UTC
|
Thank you gents. I thought this was an especially unclear passage, as blakem pointed out. It might be correct if the author means print "${system('rm -rf')}"; is bad but that would be your own dumb fault wouldn't it? And what would that have to do with taint?
Well, any way, thanks for your clarity and wisdom.
Ira,
"So... What do all these little arrows mean?"
~unknown | [reply] [Watch: Dir/Any] [d/l] |
Re: Trojan Horse? (taint mode)
by BrentDax (Hermit) on Nov 26, 2001 at 11:46 UTC
|
There are some pretty dangerous possibilities:
$a=" (?{system('rm -rf *')})";
$b=~/foo($a)bar/;
That will ruin your whole day.
=cut
--Brent Dax
There is no sig. | [reply] [Watch: Dir/Any] [d/l] |
|
For this to ruin your day, you would have to explicitly permit the execution of code within interpolated variables with use re 'eval'; So, like the example in the book, it looks scary on the surface, but isn't that bad in practice.
-Blake
| [reply] [Watch: Dir/Any] [d/l] |
|
| [reply] [Watch: Dir/Any] [d/l] |
Re: Trojan Horse? (taint mode)
by mattr (Curate) on Nov 26, 2001 at 12:56 UTC
|
I can't figure out why you would ever want to execute/eval
untainted CGI input as-is. And I don't know if I'd trust Perl's
CGI tainting to keep my evals safe from those curly brackets.. paranoia is
good there.
As far as standard input, you are worried about a user
maliciously erasing all their own files? Or are you allowing
users to run suid? Context?
update 2002.1.26 sorry I missed your/blakem's quotation. | [reply] [Watch: Dir/Any] |
|
The context is general knowledge. This all started when I read the passage I tersely quoted and blakem included in full. It's not to solve a specific implementation problem, but rather to ensure understanding so that I can avoid specific implementation problems.
I can't figure out why you would ever want to execute/eval untainted CGI input as-is
Yeah, that does sound dangerous. That's why the quoted material caught my attention. It seemes to imply that code could be evaluated without my express permission but instead simply because I put it in double quotes. That kinda freaked me out.
Thanks,
Ira,
"So... What do all these little arrows mean?"
~unknown
| [reply] [Watch: Dir/Any] |