Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

Re: magic-diamond <> behavior -- WHAT?!

by JavaFan (Canon)
on Oct 29, 2008 at 23:19 UTC ( [id://720361]=note: print w/replies, xml ) Need Help??


in reply to magic-diamond <> behavior -- WHAT?!

Shouldn't this be fixed with 3-argument open?
Fixed implies broken. This feature is there by design, and predates perl5. I find it useful.
I really like the magic-diamond for quick one-liners, but this just sounds all the security/robustness alarm bells.
One-liners are one-liners. They are there for convenience. Writing secure and/or robust programs means you're going to put in more effort than a one-liner.

One of perl mottos is to make "easy things easy, and hard things possible". Magic open is a form of easy. Writing secure and robust programs is a hard thing. For that, you taint your command line arguments, and use 3-arg open. Note that a simple -T flag prevents your example from doing any harm:

$ perl -TwE '$ENV{PATH} = "/bin"; while (<>) {say}' '/bin/rm * |' Insecure dependency in piped open while running with -T switch at -e l +ine 1. $
Replacing magic open with 3-arg open means easy things are not so easy any more.

Replies are listed 'Best First'.
Re^2: magic-diamond <> behavior -- WHAT?!
by repellent (Priest) on Oct 30, 2008 at 00:17 UTC
    Allowing arbitrary execution of shell commands is a cardinal sin in security. Not only that, the magic-diamond does it implicitly. This goes beyond the realm of making "easy things easy, and hard things possible". This is a security-hole, IMHO.

    Sure, the current magic makes it great for some useful (albeit uncommon) operation that you would induce by naming your ARGVs (most likely, filenames) in a certain special way. But consider the more common usage of the diamond: to write filters.

    For example, would you ever expect the following to execute shell commands? Currently, it can.
      # strip "#"-till-EOL perl -pe 's/#.*$//' *

    I certainly don't. I see this as a read-only operation that prints to STDOUT, and I'd like to be able to assume so.

    Does this mean I have to put in effort now to ensure * does not contain any magic, just because I'd like to do the common unmagical operation of reading the files? "Magic open" is too dangerous "a form of easy".

    Let's lessen that impact -- the security and robustness benefits will exceed the gains of the obscure magic. Just my opinion.

    P/S - Doesn't it seem ridiculous to have ARGV::readonly instead of the inverse-situation of having (the fictional) ARGV::magical?
      Allowing arbitrary execution of shell commands is a cardinal sin in security. Not only that, the magic-diamond does it implicitly. This goes beyond the realm of making "easy things easy, and hard things possible". This is a security-hole, IMHO.
      It's no more a security hole than "system" is. Or a kitchen knife a murder weapon. Magic open was there before the fast majority of the current Perl programmers even knew there was such a thing as Perl, and it has been documented that way.
      For example, would you ever expect the following to execute shell commands? Currently, it can.
      # strip "#"-till-EOL perl -pe 's/#.*$//' *
      I certainly don't. I see this as a read-only operation that prints to STDOUT, and I'd like to be able to assume so.
      Too bad. It isn't going to change. But with the addition of a single keystroke, that filter won't execute arbitrary shell commands. And IMO, it's always a good idea to enable tainting if you're running in an environment you cannot trust (but then, if you cannot trust the environment, is such a broad shell expansion a good idea in the first place?)
      Let's lessen that impact -- the security and robustness benefits will exceed the gains of the obscure magic. Just my opinion.
      Noted. But in my opinion, fundamentally changing the behaviour of a feature that predates the existence of perl5 doesn't justify the gain - specially not if the gain can be gotten by running with tainting on. Which even predates 3-arg open.
      Doesn't it seem ridiculous to have ARGV::readonly instead of the inverse-situation of having (the fictional) ARGV::magical?
      Not to me.
          It's no more a security hole than "system" is. Or a kitchen knife a murder weapon. Magic open was there before the fast majority of the current Perl programmers even knew there was such a thing as Perl, and it has been documented that way.

        I disagree. system is an explicit call. By analogy, if I were to system(), I would pick up the kitchen knife and know better. With the magic-diamond <>, the knife may magically backstab me without me even realizing what happened ;-) I know now, but how about the uninformed?

        I can respect legacy since magic open existed a long time ago. But sometimes legacy needs to change for the sake of security considerations.

          But with the addition of a single keystroke, that filter won't execute arbitrary shell commands.

        Awww man.. now I've got to taint my simple filters? How is this making it easy and safe for common & simple read-only filter operations, like the one in my previous post?

          And IMO, it's always a good idea to enable tainting if you're running in an environment you cannot trust (but then, if you cannot trust the environment, is such a broad shell expansion a good idea in the first place?)

        At $WORK, I can trust that my environment is not hostile. But I don't trust that my environment is error-free. So, you can say it's sort of a semi-trust :-) The last thing I need to worry about is how filenames will affect my Perl filters.
        A reply falls below the community's threshold of quality. You may see it by logging in.
Re^2: magic-diamond <> behavior -- WHAT?!
by wol (Hermit) on Oct 30, 2008 at 14:53 UTC
    One of perl mottos is to make "easy things easy, and hard things possible".
    I think this motto needs to be tempered with a bit of "make dangerous things hard", or at least "make dangerous things look dangerous".
    Writing secure and robust programs is a hard thing.
    All the more reason to make it a bit easier!

    How about a new use directive:

    use insecure_features_no_one_really_needs;

    --
    .sig : File not found.

Re^2: magic-diamond <> behavior -- WHAT?!
by zwon (Abbot) on Oct 27, 2009 at 21:21 UTC
    Fixed implies broken. This feature is there by design, and predates perl5. I find it useful.

    After quick look I've found that pod2html, pl2pm, and prove are vulnerable. And it's hard to assume that their authors didn't know about this "feature". I'm pretty sure that if I spend more time investigating /usr/bin I'll find more. Some of these scripts are run by root, and he may don't even know that they written in Perl, I don't think he checking that there are no files with | or < in their names. So I have only touch the file with the right name in the right place. That's what I call "things are broken".

    Isn't it easier to fix scripts that rely on magic open after they stop working, then to fix scripts that work perfectly, except that they could ruin your system.

      Wait. You want to protect against a root who runs some-program-he-doesn't-really-know * in a directory with world write access, without looking at the content of the directory?
      Isn't it easier to fix scripts that rely on magic open after they stop working, then to fix scripts that work perfectly, except that they could ruin your system.
      I'd say the person with root access is a way bigger problem to your system than magical open.

        What do you mean by "really know"? Do you saying that before running some program I should review the sources? Are you really always do that? And root access is not a requirement to fall into that trap, ordinary users, who don't even know what Perl is, also can run these scripts.

      You must have an old perl/pod2html :)

      ack "\<ARGV\>" C:\perl\5.10.1\bin\*bat

      ack "\<\>\s*\)" C:\perl\5.10.1\bin\*bat

      C:\perl\5.10.1\bin\brace-compress.bat:59: while ( <> ) { C:\perl\5.10.1\bin\c2ph.bat:488:STAB: while (<>) { C:\perl\5.10.1\bin\dbilogstrip.bat:53:while (<>) { C:\perl\5.10.1\bin\perlbug.bat:994: my $result = scalar(<>); C:\perl\5.10.1\bin\perlthanks.bat:994: my $result = scalar(<>); C:\perl\5.10.1\bin\pl2pm.bat:56:while (<>) { C:\perl\5.10.1\bin\podgrep.bat:51:while (<>) { C:\perl\5.10.1\bin\podtoc.bat:21:while (<>) { C:\perl\5.10.1\bin\ppm.bat:99: last unless defined ($_ = <> ); C:\perl\5.10.1\bin\pstruct.bat:488:STAB: while (<>) { C:\perl\5.10.1\bin\scandeps.bat:45:while (<>) { C:\perl\5.10.1\bin\SOAPsh.bat:29:while (defined($_ = shift || <>)) { C:\perl\5.10.1\bin\splain.bat:451: while (defined (my $error = <>)) + { C:\perl\5.10.1\bin\XMLRPCsh.bat:28:while (defined($_ = shift || <>)) {
        Your 'ack' is wrong on two accounts. First of all, pod2html doesn't do anything more than using a module, and calling a single sub in that. The work is done in ..../lib/5.10.1/Pod/Html.pm.

        But even then, searching for <ARGV> or <>won't reveal much. But this is relevant:

        local(@ARGV) = @_; ... local *POD; unless (@ARGV && $ARGV[0]) { $Podfile = "-" unless $Podfile; # stdin open(POD, "<$Podfile") || die "$0: cannot open $Podfile file for input: $!\n" +; } else { $Podfile = $ARGV[0]; # XXX: might be more filenames *POD = *ARGV; } ... my @poddata = <POD>;

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://720361]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others taking refuge in the Monastery: (3)
As of 2024-04-25 09:39 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found