Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot
 
PerlMonks  

Re^6: Taint and Shellshock

by tobyink (Canon)
on Sep 28, 2014 at 20:40 UTC ( [id://1102289]=note: print w/replies, xml ) Need Help??


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

kennethk's analysis is entirely correct.

First problem: HOW does the client set "the environmental variable BAD_VAR"

Firstly, one of the key factors in exploiting shellshock is that it's not just a single environment variable that is vulnerable. Any environment variable will do. So it doesn't need to be called "BAD_VAR". It could be called, say, HTTP_BAD_BAR.

Make a request to a CGI script like this:

GET /test.cgi HTTP/1.1 Host: example.com Bad-Var: foo

You'll see that the environment contains a variable called HTTP_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.

No. Forget the script. The script doesn't do anything insecure. Let's imagine a simple script that doesn't even look at environment variables:

#!/usr/bin/perl print "Content-Type: text/plain\n\n"; print "Here's the entire book...\n\n"; system("cat chapter-*.txt");

Yes $ENV{HTTP_BAD_VAR} is tainted, but the script doesn't actually touch that hash value, so no error is raised about it.

The one-argument form of system(), if it contains shell characters (in this case, the asterisk) doesn't spawn the given command directly, but runs it via the system shell (which will usually be bash).

So bash gets spawned. Bash inherits all of %ENV because child processes inherit their parent's environment. Thus bash gets the HTTP_BAD_VAR verbatim from the HTTP request header.

And bash will eval any environment variable that starts with () {.

Replies are listed 'Best First'.
Re^7: Taint and Shellshock
by ww (Archbishop) on Sep 29, 2014 at 02:20 UTC

    Thank you both, tobyink and kennethk, for the explanations. I have definitely learned from your comments.

    UPDATE: Also instructive is an article -- cited in this (Mon, 2014-09-29) morning's Perlweekly -- by David Farrell. In essence, my view is both undermined and supported there:

    As I now understand it, a BAD_ENV can be injected into the params passed to the server's CGI script, and (more-or-less) easily. But getting the malware into the server's environment requires -- at least as I now understand it -- that the server's owner/CGI-writer has failed to use taint to force the server-side code to effectively assess each of the params being provided by the outside user and prevent passage of meta-characters which are (TBO our current knowledge) required to make bash execute the malware writer's payload.

    If I still have this wrong, pray continue my edumuckation....


    ++$anecdote ne $data


      Thank you for sharing that link. The parallel between that article and LanX's suggestion is interesting. From my perspective, the Good Security™ solution is for Perl to balk if any of the %ENV is still tainted prior to shelling out; right now, it only holds for qw|PATH IFS CDPATH ENV BASH_ENV|. It's problematic that a module could expose you in this type of vector. It feels like it breaks the principle of least surprise. Unfortunately, that would break too many scripts and thus would never fly.

      My proposed solution (explicitly setting an exclusive list of expected parameters) would seem to resolve this this issue for my own external calls, but I wanted to get a sense of the relative value of those values I was defaultly relegating to the trash heap. Frankly, I'm still confused at the reluctance to just toss the hash content; of course, that's why I posed the OP.


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

        Much easier to fix the problem one level deeper. Just replace /bin/bash with this Perl script:

        #!/usr/bin/perl -wT use strict; # Clean up environment s/^\(\) {.*// for values %ENV; # Now, exec bash with our name and our arguments exec { $0 } '/bin/bash.original', @ARGV;

        If you're looking at validating all environment variables, you'd need to know which environment variables are supposed to hold what kind of values. And for example LD_PRELOAD or LD_LIBRARY_PATH should be passed through verbatim (because if an attacker already has access to these, you can't even trust yourself).

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others rifling through the Monastery: (3)
As of 2024-04-25 18:50 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found