in reply to Re: Taint and Shellshock
in thread Taint and Shellshock

Taint has wide usage, but it only limits passing certain environmental variables through. If the CGI request sets BAD_VAR = rm -rf /, Perl will happily pass that through to your executable without untainting because it doesn't expect your child process will use it (in my understanding).


#11929 First ask yourself `How would I do this without a computer?' Then have the computer do it the same way.

Replies are listed 'Best First'.
Re^3: Taint and Shellshock
by ww (Archbishop) on Sep 27, 2014 at 19:22 UTC

    Perhaps I don't understand the parent node as it was intended, but if I do correctly grok it, I think it's misleading, at best.

    Oversimplifying a bit, when the -T CLI option is on, anything that comes from outside the script is "tainted."

    Untainting data (be it ENV, $vars or anything else) can be fairly easy... but often is anything but 'easy' or simple. Consider, for example, data received as input from a form on a website.

    However, take a simple case, where login_data (an ID and yeah, this is old) was supposed to be five digits -- no more, no less, and nothing that's not an (arabic) digit. Since the user entry is tainted, the cgi in use untaints the login_data (to the site owner's satisfaction) by checking that the id received consists of exactly five digits:

    unless ( $value =~ /^\d{5}$/ ) # UNTAINT { out_badlog(); warn ("bad after UNTAINT\n"); exit; }

    Ascertaining that the five digits comprise a valid ID is a different topic and is performed in another part of the script.

    So, moving on to this from perlsec:

    "SECURITY MECHANISMS AND CONCERNS
    Taint mode
    Perl automatically enables a set of special security checks, called *taint mode*, when it detects its program running with differing real and effective user or group IDs. The setuid bit in Unix permissions is mode 04000, the setgid bit mode 02000; either or both may be set. You can also enable taint mode explicitly by using the -T command line flag. This flag is *strongly* suggested for server programs and any program run on behalf of someone else, such as a CGI script.
    "

    perlsec offers much more of relevance to the immediately previous comment from kennethk.

    There's more in perlfaq7.pod about determining "if a variable (emphasis supplied) is tainted" ...after which pf7 offers these gems:

    " You can use the tainted() function of the Scalar::Util module, ....See also 'Laundering and Detecting Tainted Data' in perlsec."

    Frankly, I (for just one, I hope) was unaware (because of far too cursory reading of its docs) that S:C offered capabilities there. I hope this belated epiphany is useful to others.

    Updated: Para 1 added and paras 2,3 and 4 edited for clarity


    ++$anecdote ne $data


      I think you misapprehended my point (or I misapprehend yours). Suppose the client request to a Perl script sets the environmental variable BAD_VAR. In Perl, $ENV{BAD_VAR} is tainted. Suppose your CGI script is
      #!/usr/bin/perl -wT print "Content-type: text/plain\n\n"; local $ENV{PATH} = '/usr/local/bin'; print `my_prog 12345`;
      From my understanding, Perl will not raise any issue in the scenario where my_prog accesses BAD_VAR, and hence %ENV can be used to bypass taint. Is this not correct?

      #11929 First ask yourself `How would I do this without a computer?' Then have the computer do it the same way.

        First problem: HOW does the client set "the environmental variable BAD_VAR" (and assuming the worst, let's use your earlier suggestion that BAD_VAR be set to rm rm -rf /) and where does the script you've shown us access BAD_VAR?

        Somehow, that value has to get passed in to the script... not just to the params packaged up by CGI, but from the params to the script. Taint won't allow that except to allow the 'bad' params to be passed to a part of the script that purports to scrub the input; the untaint function. Of course, if the scrubbing is done badly, that's a failure on the programmer's part; not Perl's and not taint's.

        Second (or, more of the same): if the script allows rm -rf / to pass an untaint function, the script's author hasn't done an adequate job. The script should have been designed to ensure that outside data conforms to a (reasonably) testable format... and should (with taint's help) block execution, eval or anything else dangerous, if the data doesn't conform.


        ++$anecdote ne $data