perl -wTe 'use Scalar::Util qw( tainted ); $x = $ARGV[0]; print "taint +ed!\n" if tainted( $x ); $x = pack "a*", $x; print "No longer tainted +!\n" unless tainted ($x); eval( $x ); ' 'print "hello, world\n";'

The above code creates a file using Perl 5.10, but complains and dies under 5.8.8 as it probably should. I've submitted a perlbug thanking ambrus and tye in the report.

Thanks to ambrus for pointing it out and tye for suggesting Scalar::Util to test the taintedness of a value.

The docs say to use a regular expression (or to make the data the key of a hash) in order to untaint it. There's no mention of pack().

ambrus asked in the CB if that is a bug. I think it probably is.

Replies are listed 'Best First'.
Re: pack() untaints data : bug or undocumented Perl 5.10 feature? (mostly good)
by tye (Sage) on Apr 05, 2008 at 01:07 UTC

    It probably makes sense for most pack formats to untaint. But I agree that it would be better if the "a", "A", and "Z" formats would not untaint. My guess is that it was an intentional features due to the other formats. But making an exception for those few makes perfect sense (or, more accurately, make it so feeding a tainted value as input to an a/A/Z format should cause the output of pack to also be tainted).

    - tye        

Re: pack() untaints data : bug or undocumented Perl 5.10 feature?
by ambrus (Abbot) on Apr 05, 2008 at 12:23 UTC

    Wierdly, it seems that in perl 5.8.8, either of packing and unpacking with "B*" untaints, unpacking with "N*" untaints; but packing with "N*" or packing and unpacking with "C*" or "a*" doesn't untaint a scalar. I've no idea what the correct behaiviour should be.

    Not really related, but note that this command doesn't raise an insecure dependency error:

    perl -wTe '() = unpack $ARGV[0], 1e9;' p
    it segfaults.

    However, the result of such an unpack is tainted, as can be seen from the error from this command.

    perl -wTe '$z = pack "p", "hi\n"; $r = unpack $ARGV[0], $z; eval $r;' +p

    Update: I forgot to say that I found this bug when re-examining Re: What's your favourite method of untainting?.

    Update: see perlbug ticket #52552.

      Perlsec starts of with enthusiastic claims as to it's protections but the text contains many caveats. Winnowing down to the grist, the following data sources are stated to be marked tainted.

      All command line arguments, environment variables, locale information (see perllocale), results of certain system calls ("readdir()", "readlink()", the variable of "shmread()", the messages returned by "msgrcv()", the password, gcos and shell fields returned by the "getpwxxx()" calls), and all file input are marked as "tainted". Italics are mine.
      This would seem to say that all other system calls are not tainted.

      The following statement would seem to confuse some:

      If an expression contains tainted data, any subexpression may be considered tainted, even if the value of the subexpression is not itself affected by the tainted data.
      I could not find where in perldoc the term expression is defined. I found the definition for a statement, but a statement in generally not considered to be an expression. An expression is generally considered to be a sequences of identifiers and operators, although in some languages an expression may include functions. This would seem to leave the exact requirement for pack() or unpack() in an unclear state. I note that it does not say that a statement will, in itself, taint data. This would seem to be reserved for the expressed system calls above.

      In a more specific vien, ambrus writes:

      Not really related, but note that this command doesn't raise an insecure dependency error: perl -wTe '() = unpack $ARGV[0], 1e9;' p

      Not sure what you are thinking here but it should seg-fault, regardless of where the 'p' pattern is received from you are asking to unpack a arbitrary memory offset. I far as I know perl does not ( yet ) promise to protect oneself from out of band memory accesses.

      From perldoc -f unpack:

      The "p" and "P" formats should be used with care. Since Perl has no way of checking whether the value passed to "unpack()" corresponds to a valid memory location, passing a pointer value that's not known to be valid is likely to have disastrous consequences.

      In regards to the use of ARGV as a parameter to unpack, I would think that feeding a argument into unpack without validation could easily lead to bad consequences outside of whether the program is tainted or not, as clearly demonstrated my your example. The taint checks are included as a bookkeeping aid and not to prevent the programmer from hanging himself.


      s//----->\t/;$~="JAPH";s//\r<$~~/;{s|~$~-|-~$~|||s |-$~~|$~~-|||s,<$~~,<~$~,,s,~$~>,$~~>,, $|=1,select$,,$,,$,,1e-1;print;redo}

        Seems to be a storm in a teacup to me too. Given that I can untaint input using

        echo print 'Some piece of nasty code'|perl -Tne"m[(.+)];$_=$1;eval;" Some piece of nasty code

        I don't see any additional risk by allowing my $untainted = unpack 'A*', $tainted;.

        Nor any lesser risk by not allowing it.


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
      I'm not sure of the correct behavior, but the implementation and the docs sure don't agree at the moment. One or the other needs to change.

      If it's the docs that change, a caveat about old code tested under older versions now changing semantics should be present. That's almost never a good thing to see in your docs.

Re: pack() untaints data : bug or undocumented Perl 5.10 feature?
by andk (Novice) on Apr 08, 2008 at 19:30 UTC
    For what it's worth, your well written test program allowed me to determine the code that changed the tainting behaviour: it was patch 24010:

    Change 24010 by rgs@bloom on 2005/03/08 17:53:50

    Subject: Encoding neutral unpack
    From: perl5-porters@ton.iguana.be (Ton Hospel)
    Date: Sun, 6 Mar 2005 18:29:38 +0000 (UTC)
    Message-Id: <d0fi6i$k06$1@post.home.lunix>

    It's quite a large patch: Show patch