Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling
 
PerlMonks  

Format string vulnerability

by Mr_Person (Hermit)
on Dec 01, 2005 at 01:36 UTC ( [id://513169]=perlquestion: print w/replies, xml ) Need Help??

Mr_Person has asked for the wisdom of the Perl Monks concerning the following question:

I just read about the new vulnerability in Webmin and after taking a look at the module involved, I was surprised at how easy it would be to make this mistake. The problem is that Webmin passes user input to the Sys::Syslog module without escaping it. The issue with this is that the Syslog module uses printf to format its output and someone can easily put something like %n in the string which will cause the script to abort because of a write error.

Knowing this now, I'll be sure to look over all my scripts that use Sys::Syslog and will be sure to pay careful attention in the future to modules that say anything about using printf. However, I was wondering if there was any general rule that I am missing here. It just seems to easy to unknowingly pass something to a module that you don't know uses printf. Is there any way taint mode can check for this? Thanks!

Replies are listed 'Best First'.
Re: Format string vulnerability
by graff (Chancellor) on Dec 01, 2005 at 03:14 UTC
    I personally would not consider this case to be a "sign of a deeper/more pervasive problem" -- definitely not something I'd lose sleep over. Having looked at the faulty (s)printf usage in webmin/miniserv.pl code, I'd expect that most people don't use (s)printf that way.

    The whole point of (s)printf is to parameterize the format string, using "%..." placeholders in much the same way that we use "?" placeholders in the sql statements that we execute via DBI. It's kind of surprising (indeed, I am shocked -- shocked!) to see code where scalar variables holding "printable" values are being used directly within the format string, instead of being passed as parameters that will fill the "%..." placeholders that should have been in the format string in the first place.

    Looking at the patches for fixing the hole, doing it right is a simple enough habit to get into, and people who read and understand the man page for sprintf generally start out with the correct habits from the start.

    (Having said that, however, I can confess that I have caught myself a few times, putting scalar variables into the quoted format string that I pass to sprintf, just because I didn't need a specific column width or leading zeros or fixed decimal point, etc. And of course, if people start getting into "in-line creation" of the format string, by concatenating pieces together, I can imagine that they might lose sight of where placeholders should go, instead of variables -- it's a matter of getting to be a bit too clever at times.)

    If you want to be really careful, grep for /s?printf/ in the suspect source code, and look for scalar variables inside double quotes adjacent to those calls. It shouldn't be too hard to cook up a simple perl script to look for potentially offending patterns in perl code -- good enough to catch most cases.

    (Yes, yes, yes, it's true that only perl can parse perl source code -- but if a regex and Text::Balanced can spot even one suspect sprintf call in a perl file, you at least know to pay closer attention to that file, and maybe anything by that author.)

    updated to fix a grammar mistake; also, checked the perlsec man page, and can report that (s)printf is not mentioned there. Taint mode does not trap tainted data being included as part of the format string passed to (s)printf -- i.e. the following does not die with a taint error, and it does generate a 50K string of spaces:

    perl -T -e '$arg = shift; printf "you said $arg\n"' %50000s
      Taint mode does not trap tainted data being included as part of the format string passed to (s)printf -- i.e. the following does not die with a taint error
      And it shouldn't. Tainting prevents you from using tainted data to (potentially) modify the environment. You can't open a file for writing if the filename is tainted. But you can print tainted data. Or open a file whose name is tainted. Tainting will not prevent your program from consuming huge quantities of memory or CPU time - or from printing out very long strings.
      Perl --((8:>*
Re: Format string vulnerability
by petdance (Parson) on Dec 01, 2005 at 16:50 UTC
    There are two issues here. The first is that Webmin shouldn't be using untrusted strings from the outside world. This is asking them to get DOSed. Something like
    $untrusted_format = "%10000000d"; sprintf( $untrusted_format, 1 );
    is going to generate a one million character string.

    The other problem is that there is indeed an integer overflow in sprintf that is explained in http://www.dyadsecurity.com/adv/perl.adv. Add this with Webmin's bad use of format strings, and we've got a case where a box could get 0wned.

    We're working on it in p5p, and will be announcing fixes soon.

    xoxo,
    Andy

Re: Format string vulnerability
by inman (Curate) on Dec 01, 2005 at 09:31 UTC
    This was incorrectly reported at Computerweekly.com as Perl open to format string security hole. Perl as a language isn't to blame. A module written in perl that is used by a third party application is to blame.

      This is not entirely correct, it's a perl bug that can be exploited if a script uses format strings insecurely (as the webmin module in question does). See demerphq's post on the subject.


      Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it. -- Brian W. Kernighan
        dont worry guys php is next ;]
      I think that putting the blame on webmin, without carefully looking at perl itself is even more damaging to perl that the article in computerweekly. Luckely, perlmonks isn't read by the non-perl-insiders at large, and luckely, p5p was smart enough to do some introspection and not send out a rebuttal.

      The security issues are there in Perl, and they are now being addressed. And while webmin isn't free of blame, the issues in Perl make the difference between a denial of service attack (due to the bug in webmin) and comprimising the machine (due to the combined effects of the flaws in webmin and perl).

      Perl --((8:>*

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://513169]
Approved by GrandFather
Front-paged by Aristotle
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others avoiding work at the Monastery: (8)
As of 2024-04-18 14:27 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found