Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much

Re^6: Taint mode limitations

by Anonymous Monk
on Nov 04, 2012 at 15:21 UTC ( #1002207=note: print w/replies, xml ) Need Help??

in reply to Re^5: Taint mode limitations
in thread Taint mode limitations

So, you wrote a bunch of code without considering security; and now you want to 'fix' Perl; rather than fix your own code.

If I was infallible and always remembered to sanitize user inputs against malicious characters, then I wouldn't need taint mode in the first place would I? So yeah, I do expect taint mode to catch as many of my mistakes as it possibly can. But as it stands, it lets way too many things go by, many of which could easily have been stopped if it had been designed to be less lenient.

Consider the following scenario involving a reasonably qualified programmer (letís call him Alain for the sake of argument ;-)) who makes one honest mistakes and ends up with several security threats, none of which are being caught by taint mode (although they could easily have been caught by a better designed taint mode). It goes like thisÖ

Alain adds a new input to his CGI application, and for some reason, he forgets to sanitize it. Yet Perl doesnít complain because for now, Alain is not using this tainted input to do anything dangerous. You might say that this isnít a big deal because no actual vulnerability has been introduced yet. Still, it would be nice if, upon exit, Perl told Alain that this particular variable became tainted and was never untainted afterwards. This would allow Alain to address the problem right away, before that tainted variable has any chance to cause damage. But nevermind.

Fast forward a few months. Alain has used the original tainted input to derive other variables, which have themselves been used to derive other variables, and so on. So he now has a dozen tainted variables floating around his system. But Perl is not complaining, because none of them is used to do anything dangerous. But thatís about to change. ..

Today, Alain uses one of those tainted variables to compose a HTML string which he prints to his CGI scriptís standard output. As a result, he is now exposing all his users to cross site scripting attacks. Yet, Perl still isnít complaining because it doesnít consider printing a tainted variable to STDOUT as being dangerous.

Now, you might say that this is Alainís fault. He should know that taint mode doesn't protect him against printing tainted variables to STDOUT. So he should never print a string to STDOUT without first checking it for taintedness with the tainted() function. But this seems very error prone. If Alain forgets to do this even once, he will be exposing his users to xss attacks. Wouldnít it be simpler and safer if taint mode did what I am suggesting above, namely, report any tainted variable that never got untainted by the end of the process?

Fast forward another couple of months. The tainted variables have spread even more, and several of them are now being printed to STDOUT, resulting in a growing number of vulnerabilites, and increasing the odds that one of them may be actually exploitable. But Perl still isnít complaining because none of the tainted variable is being used in a system call. So, while Alainís users are exposed to xss attacks, his own server is still unaffected by these tainted variables. But this too is about to change.

Today, Alain takes one of those tainted variables and executes a regexp match with group capture on it, to carry out a task that he never intended as a security sanitization operation. This was bound to happen at some point, given that Alain (like all Perl programmers) is deeply in love with regexps and uses them for all sorts of things (most of which have nothing to do with sanitizing malicious inputs). The net result of this action is that Alain now has a variable which is considered to be untainted, eventhough it was derived from a tainted variable and nothing was ever done to sanitize it against malicious content. Letís call this an ďinadvertently untainted malicious variableĒ. Later on, Alain uses one of the captured group values to compose a shell command that he passes to system() and Bam! His server has now been compromised.

Here too, you might say that this is Alainís fault. He should know that invoking a regexp on a variable can result in inadvertently untainting the malicious captured groups. Before doing any regexp match, he should always check the string for taintedness. So now, we are saying that Alain should be doing this before every print to STDOUT and every regexp with group capture. So, even more opportunities for Alain to slip.

But wait, thatís not all. At some point Alain passes one of tainted variables to a CPAN function which, unbeknownst to him, does a regexp match. Again here, the developers of the CPAN function never meant this match to act as a security sanitization operation. The function uses a captured group to compose the return value, and as a result, the return value of the function is now an inadvertently untainted malicious variable. Alain uses the return value to compose another system() command, resulting in another vulnerability for his server

Maybe that too is Alainís fault. He should know that third party functions can inadvertently untaint malicious variables. So before making any such call, he should always check all arguments for taintedness.

Or maybe Alainís problem is that he doesnít think before invoking a system call. When he is about to issue a system call, he shouldnít trust that tainted mode did its job of identifying tainted variables that were never explicitly sanitized. Instead, he should manually trace back everything that went into composing the system command. HumÖ that sounds pretty hard and error prone, but I guess that's why Alain is paid the bick bucks.

But waitÖ what if Alain passes one of those inadvertently untainted malicious variables to a CPAN function that, unbeknownst to him, uses it to compose a system() command? Is Alain supposed to think about that too and inspect every third party method he invokes to make sure it canít ever result in a system command that includes one of the inputs that he passed to it? Hum... that too sounds incredibly error prone. So, maybe our last two recommendations aren't good and the best thing after all is for Alain to always check argument for taintedness before passing them to a third party function for taintedness.

So, all in all, we are saying that Alain should do this kind of check:

  • before every print to STDOUT
  • before every regexp with group capture
  • before every call to a third party library

Does this sound like Alain is doing all the hard work and taint mode is hardly providing any protection at all? Yes. Is Alain confident that he will always remember to do this before every print, regexp or call to a third party library? No. Could taint do a better job at helping Alain? Yes. In particular, I believe that what I propose on this page would prevent all the problems described above:

That proposal would protect Alain against most (if not all) accidental slips like: adding 5 new inputs and forgetting to explicitly sanitize one of them. But of course, it canít protect Alain against conscious, ďpremeditatedĒ acts of negligence like: labeling a new input with untainted(), just to get rid of Perlís error message, without actually doing anything to sanitize it (or doing a quick, half-ass job of if). As many people have pointed out, nothing can protect Alain against this kind of negligence. If Alain does something that stupid, then THAT is definitely his fault. But everything else should be caught by taint mode (and I canít see a technical reason why it canít be done).

Replies are listed 'Best First'.
Re^7: Taint mode limitations
by BrowserUk (Pope) on Nov 04, 2012 at 15:56 UTC
    But everything else should be caught by taint mode (and I canít see a technical reason why it canít be done).

    I can only ask you to re-read what I wrote in the last section of Re^3: Taint mode limitations.

    I do not disagree that taint mode could have been implemented in a manner that would make it more amenable to being used to catch and fix-up poor code. But it wasn't.

    Alain is now faced with a problem of fixing up his -- self-described -- poor code. Petitioning for a change to the implementation at this point is most unlikely to help him. Even if everyone agreed a change would be beneficial, it would likely be a long time before that made it into a new release.

    And given the existing mechanism is used my millions of pieces of code out there in the real world; and there is no real way to make his explicit de-tainting mechanism co-exist with the current mechanism; the likelyhood of it ever being implemented is very low.

    That leaves Alain one obvious choice.

    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    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.

    RIP Neil Armstrong

      Alain is now faced with a problem of fixing up his -- self-described -- poor code.

      I never said that the code is poor. It just wasn't written with security in mind. But it is very well designed and modular, and it will be almost trivial to add a user input sanitization layer to it (see:

      This layer will protect my app against malicious user input, to the full extent of what is possible given the current limitations of taint mode. But it will still leave many possibilities for error which would be caught if the features I suggest were added to taint mode.

      And given the existing mechanism is used my millions of pieces of code out there in the real world; and there is no real way to make his explicit de-tainting mechanism co-exist with the current mechanism; the likelyhood of it ever being implemented is very low.

      I may be wrong, but I think the taint mode enhancements I propose are completely compatible with the current taint mode. All that is needed is to add an extra option to specify how lenient you want taint mode to be. The default should of course to let it be as lenient as it is now. But those of us who aren't happy with its current leniency could specify a different value for that option.

Re^7: Taint mode limitations
by Anonymous Monk on Nov 04, 2012 at 15:27 UTC
    A poor workman blames his tools
      A poor workman blames his tools

      And a truly good one designs new and better tools that facilitates his life and that of other workmen.

      I think I have proposed a design for such a better tool. Unfortunately, I don't have enough knowlege about perl internals, nor the clout in the Perl community to make it happen.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://1002207]
[stevieb]: shmem thanks for the 'insight' :P
[shmem]: good thing that Sun already took "OpenWindows", otherwise I'd not stop to shudder imagining an "OpenWindows" from MS
[shmem]: more garbage in, more garbage out that would be
[stevieb]: I found that win10 broke a C# library I was using for one project while enhancing tests for a Perl dist, which breaks other Perl dists, and I'm about to throw my hands up on berrybrew. win2k12 broke one thing, win10 breaks something...
[stevieb]: ...unrelated which requires replacing a lot of code and a whole lib. I'm about to go nix only ffs
[shmem]: stevieb: what you're doing sounds afwully complex. Too much for me this evening to provide brighter insight ;-)
[stevieb]: I don't even own a Windows computer. Both my girl and I have a laptop each with Linux. I'm supporting Windows in some of my projects and I can't even guage whether it's worth it or not.
[stevieb]: shmem It's something I desired to have years ago, which is why I took over berrybrew. Cross-platform build/test automation locally, or over the network Test::BrewBuild
[shmem]: sounds good.
[shmem]: but I'm crumbling smaller stones. remember...

How do I use this? | Other CB clients
Other Users?
Others scrutinizing the Monastery: (5)
As of 2017-03-28 22:04 GMT
Find Nodes?
    Voting Booth?
    Should Pluto Get Its Planethood Back?

    Results (342 votes). Check out past polls.