[EMAIL PROTECTED] wrote:
>>>I, being too lazy to look up a perl function, would use 
>>
>>hostname command in
>>
>>>backticks like so:
>>>
>>>$HostID = `hostname`;
>>>
>>
>>Right which is why the above is "too lazy". Anyone reading this please
>>don't settle for the above, it is error prone, insecure, and
>>insufficient. There is no error checking, there at least needs to be a
>>full path, and it is potentially slower.
> 
> 
> After the initial shock of having 1 simple assignment statement ripped to
> shreds, I thought about it for a minute and it downed on me that I'm not
> buying into your accusations. I would like you to please explain them. If
> these are indeed realistic problems then everyone should know why. And
> please don't use examples like, "it is insecure because someone could swap
> out the hostname binary with something potentially damaging" because that
> would require root access and for that matter a bang statement to the perl
> binary would suffer from the same security flaws.
>  

Very well.....

1. Insecure: when using a shell command from a script you are at the
mercy of the environment of the invoking user. If you do not have
complete control of the environment you are at risk. This was the oldest
trick in the book when I was in college, create a script called 'su',
place it in a 'bin' directory in your user account, place '~/bin' at the
front of the PATH environment variable. Then go to the sysadmins and say
you had screwed up your account in some manner that would require them
to become root. So logged in under your user they ran 'su' which was
naturally setup to emulate the look of the real 'su' command. After
about 10 seconds you now have root's password. Of course most people
aren't this susceptible anymore, and most are using 'sudo' which has
protections in place, but the point remains. Unless you use a full path
to a script you have no idea of what malicious intent has been placed in
the path to cause you problems. And even if you do use a full path there
is nothing to say that the command you are calling hasn't been replaced.
Not to mention any code receiving input from an external source should
have taint checking on.  (Despite your claim to the contrary this is
still a real enough threat.)

2. Error Prone: your command is insufficent because you do not check
whether or not the command was even runnable. Backticks provides a
return result in $? that will tell you whether or not you were able to
fork, and whether or not the command existed, you had the proper
permissions, etc. Without checking all of this each time you call out to
a system command you are not providing sufficient error checking. On top
of that you were not checking the exit value of the command so you don't
know if it ran successfully or not, you only know whether you got any
output. You don't know if it dumped core, or what signal caused it to
stop in the case that it failed. You also didn't include the STDERR
capturing idiom in the command so you don't know if there was error
output or warnings generated.

3. Portability: the command issued may have different switches, may not
exist, or may be for a completely different purpose depending on what
platform you are running. 'hostname' is actually the perfect example,
because to my knowledge it doesn't even exist on Windows systems. Many
commands have very different settings and interfaces across the many
unix systems, and depending on the available /bin/sh (assuming it is the
default system shell, which isn't necessarily true either) there may be
different quoting patterns needed, or the shell may not support long
option processing. Granted a lot of code is intended to run on a single
platform, but unless that was specifically provided in the spec by the
poster you don't know, so can't assume. Some systems may not even
provide a proper fork clone, more on that below.

4. Speed/Forking: because backticks causes a fork, you are using system
resources in a way you wouldn't necessarily need to if you were able to
use a built-in function. When Perl forks, it forks an exact copy of the
running process and then transitions to the new command (at least on
*nix systems) which may cause use of memory resources, file descriptors
(which include open sockets to databases or possible remote locations),
and other system level attributes that you wouldn't otherwise need. And
the memory footprint of the running process includes all loaded modules
so could be quite large. When running a forked system command, the perl
interpreter has to fork, then exec the shell, the shell then has to
parse the command line (which unless you have seen the parsing map you
wouldn't believe how long this takes), then it has to fork and exec
again into the running process, that process may then have to do its own
option parsing, etc. which all could have been avoided by using the
internal method. So it is almost always slower to call a system command
when an internal method is available. Finally each call to
system/backticks is independent, meaning that depending on the command
being run and the optimizations of the alternatives there is no
potential to use caching, session management, etc. to improve
efficiency. Although system/backticks are written correctly in Perl 5,
if you are using your own fork/exec model and don't include sufficient
'wait' code then your system may also become swamped by zombies,
eventually causing a locked system, assuming you don't hit the memory
limit first.

I leave it to you whether I have backed up my position, but shelling out
should *always* be an absolute last resort, which at times does happen,
but when it does it should be executed with care and diligence. And if a
module exists that can provide an alternative it should definitely be
used, if for no other reason than maybe it will have to shell out too,
but in that case the module author has more likely thought of the above
things and done his best to avoid the issue. Sys::Hostname is the
perfect example, it will eventually shell out too if all the preferred
methods fail, but it does the proper amount of error checking, taint
checking, etc. Check out the source if you want to see what I mean by
sufficient handling.

http://search.cpan.org/src/NWCLARK/perl-5.8.7/ext/Sys/Hostname/Hostname.pm

And those are just my reasons, the gurus may have more/better ones...
> 
>>>Not sure if that will catch a newline character so I would 
>>
>>also follow it
>>
>>>with this:
>>>
>>>$HostID =~ s/\n//;
>>
>>Right, in which case we can at least suggest 'chomp',
> 
> 
> Matter of preference really. I like using regex.
>

Well again if your preference is error proneness and slower by all
means, I can't prevent you from doing it. But you haven't considered
what the new line character may be for the given system, whether or not
the given shell/program provides one. And firing up the regex engine
will always be slower than using a simple chomp, especially since you
are making the assumption that there is only one new line (fairly safe
granted with 'hostname') and haven't even provided the courtesy of
anchoring it to the end of the string to at least get that efficiency
improvement.

It is still just sloppiness, and beginners don't need to be picking up
bad habits.

http://danconia.org

[snip]

-- 
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
<http://learn.perl.org/> <http://learn.perl.org/first-response>


Reply via email to