Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?
 
PerlMonks  

Does fatalsToBrowser give too much information to a cracker?

by rinceWind (Monsignor)
on Apr 10, 2002 at 10:34 UTC ( [id://157989]=perlquestion: print w/replies, xml ) Need Help??

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

When I posted this node, it provoked a response that fatalsToBrowser should be commented out of production code.

This was posted to the back end of a thread resolving a novice question, but I feel the subject deserves a more general airing, and warrants feedback from more monks.

Is use CGI::Carp qw(fatalsToBrowser) good practice? I have always been advocating this as a good wheel that doesn't need re-inventing.

If the answer to this question is no, is there a standard dienice routine, or should you roll your own?

Replies are listed 'Best First'.
Re: Does fatalsToBrowser give too much information to a cracker?
by George_Sherston (Vicar) on Apr 10, 2002 at 10:59 UTC
    I think it's great, but in development. In fact it's so great that I edited my copy of CGI::Carp to send warnings to the browser too, instead of putting them in comments. But I always delete it when the script goes live. If the script breaks down when somebody else is using it then what I want is an errordocument redirect at the web server level to send them to a comments form to let me know what happened. I can then look at the error log to get the info I need to fix it. But the error messages are of no interest to anyone except (a) me or (b) someone I don't want to see them.

    § George Sherston
Re: Does fatalsToBrowser give too much information to a cracker?
by Dog and Pony (Priest) on Apr 10, 2002 at 11:09 UTC
    If your message is informational enough to aid you when debugging, it is probably informational enough to aid a cracker. Of course, that would depend on what, exactly, you are emitting, but for fatalsToBrowser to do any good, error messages should, like normal error messages, contain as much information as possible related to the problem, yes? This could very well include complete SQL statements, "secret" parameter names, file paths, and lots of other potentially harmful things. Also, even if you craft your messages in a protected way, what is to say that something unforseen won't go fatal on you and display something critical?

    All that aside, I don't want any visitors to any site of mine to get any debugging information on their screens at all, except possibly something like the really excellent method this site uses, with an error ID that I assume maps to a log entry, so the user can describe what he/she was doing and the programmer can compare that with the resulting error logs.

    If the error messages should go anywhere in production code, I feel it should be to error logs on disk or in DB, or by mail to the administrator, or a healthy combination. Not to the user - the user should get a friendly "Sorry" screen, with instructions to try again, and a way to notify the webmaster. No matter what I can or who I am, if I have nothing to do with the site's administration, stack traces and debugging information is just plain ugly, and as a visitor I probably want the friendly screen even if I could understand it. Probably. :)


    You have moved into a dark place.
    It is pitch black. You are likely to be eaten by a grue.

      This could very well include complete SQL statements, "secret" parameter names, file paths, and lots of other potentially harmful things.

      Could you explain to me how SQL statements can help a cracker if your program is well written? After all, you do use quote methods or placeholders, and you check data before using it -- or don't you?

      The same goes for file paths. I see no problem in telling that my home page is located at /vhost/juerd/juerd.nl/index.plp. Does knowing the path enable you to use files that can't be read by my apache daemon? If my code was written badly, you could guess the number of times you need "../" to get to the root directory, but my code doesn't use paths without checking (or even parsing) them first, so that information is completely useless.

      Secret parameter names in your code are often a sign of bad programming too. Do you put your SQL passwords in your code, or somewhere safe, with nice 403 error messages if anyone tries to get it through http?

      To avoid being cracked, it's better to conceal version numbers than source code. After all, Apache's entire source code is open, MySQL's source is completely disclosed, and so is Perl's. Why hide parts of your own source if those parts can help debug?

      Not to the user - the user should get a friendly "Sorry" screen, with instructions to try again

      Yes, the user should get a "try again" and a "sorry". But some users, like me, hate to not know what's going on. If I'm going to report a bug, I'm going to report it in great detail. If there's no information, I never report it - I assume some automatic e-mail is being sent, because if the author wanted me to report the bug and does not send error e-mails automatically, he'd have included the information he needs to fix it.

      I don't like using Microsoft Windows. Why? Because since the very first General Protection Fault I ever saw, to the recent blue screens and Fatal Exceptions, I have absolutely no idea about what goes wrong when something goes wrong.

      Not all users are Teletubbies saying "uh oh" and "again" when something goes wrong. There should be a friendly message for those who are, but there should be detailed information for those who like to know more.

      This site uses error IDs, which apparently are mapped to some place in a log. I have seen quite a few after the server move, and it was annoying. The only thing I could do was paste the message, while I would have liked to be able to suggest a fix, or at least have a clue about what error I had triggered.

      When I get an e-mail message with a bug report from one of the sites I maintain, and the user was smart enough to supply all information, I can often fix it within a few minutes. If I get an error-ID (I tried several methods of reporting bugs), I have no idea if the bug is going to be huge or tiny, and I'm not motivated at all to fix it.

      U28geW91IGNhbiBhbGwgcm90MTMgY
      W5kIHBhY2soKS4gQnV0IGRvIHlvdS
      ByZWNvZ25pc2UgQmFzZTY0IHdoZW4
      geW91IHNlZSBpdD8gIC0tIEp1ZXJk
      

        Could you explain to me how SQL statements can help a cracker if your program is well written? After all, you do use quote methods or placeholders, and you check data before using it -- or don't you?

        I do. But I don't assume that my checking, my quoting and my security is perfect, no matter how "good" I think I am. I can always have missed something, or if we are several on the project, someone else might have. Or maybe some unknown bug in perl or apache suddenly decides to let data through in some way when this cracker exploits something I didn't know about.

        I'm pretty sure that all those exploits that has happened, like buffer overflows and other stuff in open source and closed source projects was not due to someone just saying "Ah darn it. We just skip checking this part here, let's go grab a beer instead." - I am pretty sure it was a mistake (for the most parts at least) and the guys doing it thought they quoted and checked all the data. Turns out they were wrong. (It is a strange comparison perhaps, but you used it first :) ).

        Maybe you feel confident enough to know you have checked everything possible. I don't. And even if I did, someone else might muck my safe stuff up.

        Secret parameter names in your code are often a sign of bad programming too.

        Haven't done that yet. But I've heard about displaytype=hack.

        Do you put your SQL passwords in your code, or somewhere safe, with nice 403 error messages if anyone tries to get it through http?

        Usually in a module somewhere inaccessible. At least via HTTP. :)

        After all, Apache's entire source code is open, MySQL's source is completely disclosed, and so is Perl's. Why hide parts of your own source if those parts can help debug?

        No reason at all, if all the users are "white hats". All the reason in the world if just one of them wears the black, because my code has not been reviewed, refined and bug tested by thousands of volunteers, of which many are also excellent programmers. It has been tested possibly only by me, of which none is an excellent programmer. :) And that code you mention has also been known to break at times. What makes it good to use is rather the speed with which things are discovered and fixed, not the out-of-the-box safety... although that is pretty darn impressive too.

        Not all users are Teletubbies saying "uh oh" and "again" when something goes wrong. There should be a friendly message for those who are, but there should be detailed information for those who like to know more.

        That is totally ok by me. If you want to, you can provide the user with whatever you think is friendly - of course. :) And I agree it isn't all that bad an idea. But. I'd still probably craft something directed to "the knowledgable user", I'd still not dump whatever to someone I don't know what his/her intentions are.

        I have no idea if the bug is going to be huge or tiny, and I'm not motivated at all to fix it.

        We are all different, thank heavens. If I'd give you one piece of advice on how to run your sites, it would be "do what works for you". Of course. :)


        You have moved into a dark place.
        It is pitch black. You are likely to be eaten by a grue.
      the user should get a friendly "Sorry" screen, with instructions to try again, and a way to notify the webmaster

      I think it depends on the application. If you are offering a free service, you can probably get away with this. If you are offering a service where you have customers that are paying for the usage of your page, you'll need to have more than just this.

      Otherwise, you'll end up with a support department always trying to figgure out what to tell a customer whenever they write in and ask what went wrong.

      In my experience, the best system is short descriptive error messages. These give clueful users enough info that they don't need to request support. It also gives your support department enough info to go on that they don't have to spend so much time helping the less-cluefull users (or bugging the programmers).

      Your results may vary.

Re: Does fatalsToBrowser give too much information to a cracker?
by Ryszard (Priest) on Apr 10, 2002 at 11:25 UTC
    IMO any un-necessary information is too much information.

    For logging in type applications, I dont even relay explicitly which out of username or password is incorrect. just tell the user to enter it again.

    If you have a production application that may fail, I personally dont see any good in reporting the error to a user, and have the user feeback the error...

    I think better style may be to write a die handler, issue a generic page, log the error, and send an alert via pager/email/whatever suits.

    Even tho the user may be faced with a nondescript page, which may be frustrating, they wont be faced with an "interpreter" level error message (less professional). Lesser of two evils...

    I generally program by the philoposphy, hide all errors, and report back generic stuff only. No version numbers, no OS / external app error messages, nothing. the user is there to use the application, not understand the engine.

    Draconian, yes.

Re: Does fatalsToBrowser give too much information to a cracker?
by strat (Canon) on Apr 10, 2002 at 11:11 UTC
    I agree with George; warnings and errors are nothing for normal user, and may sometimes even become dangerous
    (e.g. open (FILE, $file) or die "can't read password from $file: $!"; or the like. Because with some providers, you have to keep "sensible" data in directories that might eventually be accessed by web ).

    Another reason why I always remove -w (use warnings) in production systems, as well as qw(fatalsToBrowser) and try to do some defensive programming, to try to catch all errors that might happen is that I don't want to confront users with errormessages they won't understand or won't be able to do anything against.

    In cgi-scripts, I only use die for really serious errors; more often, I write an own error-outputting-routine that cares about returning a complete html-page.

    Best regards,
    perl -le "s==*F=e=>y~\*martinF~stronat~=>s~[^\w]~~g=>chop,print"

      Another reason why I always remove -w (use warnings) in production systems ... is that I don't want to confront users with errormessages they won't understand or won't be able to do anything against.

      How does removing -w aid that? Warnings (even with fatalsToBrowser, since warnings by their very nature aren't fatal) only appear in the server error log, which isn't going to be seen by users.

      In deployed code there shouldn't be any warnings generated, but should something of a dubious nature occur surely it's better for the warnings to be available in the log than not at all?

        Actually, warnings produced by -w can often be viewed in the raw data returned by the HTTP server. It won't display in the browser, but is visible with GET (or is it HEAD?) or with a util such as curl or Sam Spade. These errors can reveal paths and filenames, which may or may not be a problem. I tend to use a BEGIN{} block to skip stupid errors ("$xxx used only once...") and/or carpout() to redirect the errors to a file.
Re: Does fatalsToBrowser give too much information to a cracker?
by tachyon (Chancellor) on Apr 10, 2002 at 12:56 UTC

    Contemplate this code:

    use CGI::Carp qw( fatalsToBrowser ); .... $file = $q->param('file'); .... open FILE, $file;

    Now contemplate this snippet. If you don't immediately see what it does install it in your cgi-bin (then send me the url :-)

    #!/usr/bin/perl -w use strict; $|++; use CGI qw( :standard ); use CGI::Carp qw( fatalsToBrowser ); my $command = param('command'); print header, start_form({ -method=>'get' }), textfield({-size=>75,-name=>'command'}), submit('Run'), end_form; if ($command) { open( CMD, "$command 2>&1|" ) or die "$!: running command: '$command +'"; print "<pre>\n"; print escapeHTML($_) while (<CMD>); print "</pre>\n", end_html; close CMD; }

    cheers

    tachyon

    s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

      -T was made for people who make those mistakes.

      Of course, with badly written programs you want to conceal everything, or as least as much as possible. You might even want to change some texts and some layout so people can't look up the source in Matt's archive.

      $file = $q->param('file'); die "horribly" if $file !~ /^[a-z]+\z/; open FILE, $file;
      Or, untainting:
      $file = $q->param('file'); ($file) = $file =~ /^([a-z]+)\z/; open FILE, $file;

      U28geW91IGNhbiBhbGwgcm90MTMgY
      W5kIHBhY2soKS4gQnV0IGRvIHlvdS
      ByZWNvZ25pc2UgQmFzZTY0IHdoZW4
      geW91IHNlZSBpdD8gIC0tIEp1ZXJk
      

        my $sth = $dbh->prepare("SELECT * FROM customers WHERE name = '$name'" +); $sth->execute(); # so what happens if: $name = "O'Deary"; SELECT * FROM customers WHERE name = 'O'Deary' # or even $name = "Just another' or name = name or name = 'Perl hacker," SELECT * FROM customers WHERE name = 'Just another' or name = name or +name = 'Perl hacker,"

        Sure so you should use ? place holders. With fatalsToBrowser active a *creative* user will probably get an informative error after submitting the first name. Then such a user might get the entire customer database. Thanks for coming....

        Security is all about hurdles, depth and vigilence. You need to accept that nothing can ever be 100% secure. You attempt to make it more trouble than it is worth to breach your security. Just as you would be unwise to publish the wiring diagram for your alarm system so to you are unwise to (widely) advertise your source code. Of course code reviews like those offered by merlyn are a good idea (if you trust him ;-)

        cheers

        tachyon

        s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

Re: Does fatalsToBrowser give too much information to a cracker?
by cyberconte (Scribe) on Apr 10, 2002 at 12:11 UTC
    Thats kind of a double-edged sword.

    To start, its perfect for development, espeically while you're the only person accessing the page. Its an invaluble tool to use for debugging, instead of going back and forth from logs to browser to code.

    However deployment is another issue. How sure are you of your code? I run an open source samba search engine (Phynd) and leave fatalsToBrowser on. Why? One, it helps in bug reporting. If a user gets an error, they can explain it in more detail, expeically with the error they got - it cuts down on a lot of the tailchasing. Second, theres nothing really sensitive that could be displayed. Variable names and search queries, yes, but since one can download the source, how would that hurt? I'm not dealing with passwords or anything sensitive either.

    If you *are* dealing with sensitive information or are using building a closed source solution, then fatalsToBrowser may not be the best alternative.
Re: Does fatalsToBrowser give too much information to a cracker?
by davorg (Chancellor) on Apr 10, 2002 at 15:10 UTC

    You could easily be giving the crackers information that is very useful to them. Like, for example "hey look this CGI program is implemented in Perl". Even that seemly innocuous piece of information tells them useful things that they shouldn't know. They know that Perl is installed on your web server. Depending on the error they see, they may have clue as to the version. Some (old) versions of Perl have CERT security advisories against them. You don't want crackers knowing that you're running these versions.

    Always remove fatalsToBrowser from production code, but leave in use CGI::Carp as it will give you well-formatted and timestamped messages in the error log.

    If the answer to this question is no, is there a standard dienice routine, or should you roll your own?

    I'm far from convinced of the need for a dienice as you see described in many beginners CGI books. In many cases the default web server "500 error" page works just as well and you've got all the details in the error log.

    --
    <http://www.dave.org.uk>

    "The first rule of Perl club is you do not talk about Perl club."
    -- Chip Salzenberg

Re: Does fatalsToBrowser give too much information to a cracker?
by Juerd (Abbot) on Apr 10, 2002 at 11:53 UTC

    Whenever you have something that can output, think not about if it's good or bad THAT it outputs, but think about WHAT it can output, and how that might help a cracker.

    Apache sends its version number on every request, by default. This allows crackers to use an exploit without any further computer knowlegde.

    I'm convinced my source is safe. UPDATE - You may stop commenting on this now. Of course no code is flawless. I just think a cracker gains nothing by knowing pieces of my code, and thus think it's safe to report errors to the user. If it weren't about commercial stuff and copyright, I'd give it to you, saying how proud I am that the source code is completely useless to you. Not because of its bad style (or in the case of juerd.nl, maybe so), but because I'm sure you can't abuse the paths or SQL statements.

    When programming for the web, Perl isn't the only method of keeping information safe. *NIX file permissions are way more important, and Apache's methods of disallowing people to view contents, and database servers' techniques for not allowing remote connections are.

    Yes, when you're a beginner, better hide your source and debugging information until you're convinced it's safe.

    U28geW91IGNhbiBhbGwgcm90MTMgY
    W5kIHBhY2soKS4gQnV0IGRvIHlvdS
    ByZWNvZ25pc2UgQmFzZTY0IHdoZW4
    geW91IHNlZSBpdD8gIC0tIEp1ZXJk
    

      "I'm convinced my source is safe."

      Maybe it makes me a beginner, but I'm not yet convinced my code is safe. Just as well as I'm not convinced my code is free from bugs.

      I keep on looking for bugs and security holes in my code, and in my software design, even after it's been put in production. And yes, sometimes I do find things that require an urgent correction.

      If that makes me a beginner, so be it.


      Everything went worng, just as foreseen.

      "I'm convinced my source is safe."

      Then you really don't even need an exception handler, do you? *Smiles*

      The fact that an exception handler is triggered indicates that the software was caused to behave in a way which is not within normal bounds. While I can appreciate your point of view as someone who would like to help me fix the problem, there are just as many (or even more) people who would like to see how they can abuse this new found "feature" to comprimise my system. What you call debugging detail, the others half calls a roadmap.

      I bet the developers of the first TCP/IP stacks (with predictable sequence numbers) thought their source was safe... until Kevin Mitnick abused it. I bet the developers of ICMP error messaging never thought it would be used to recon systems. I have to assume that the person on the other side of my system is smarter than me, more clever than me, and would like to comprimise my security.

      Update for Juerd

      "And exactly how did he abuse TCP/IP?"

      The Mitnick attack was based on predicting sequence numbers... this is why most current TCP/IP stacks use non-predictable sequences.

        Then you really don't even need an exception handler, do you? *Smiles*

        Well, I do. Errors are often caused by external problems, like exceeded disk quotas, connection errors etc. Or null bytes inserted in my source with terrible harddisk crashes.

        until Kevin Mitnick abused it.

        And exactly how did he abuse TCP/IP? The same way criminals abuse roads to get away? Or are you one of the many people who just blame this Mitnick guy for everything that is a crack?

        I bet the developers of ICMP error messaging never thought it would be used to recon systems.

        It's not the protocol that lets people abuse, it's the implementation. That's because it's very simple to make mistakes in lower level languages (hence Perl's huge number of bugs :)

        I have to assume that the person on the other side of my system is smarter than me, more clever than me, and would like to comprimise my security.

        Even if he is and would, how could error messages help crack a well written Perl program?

        U28geW91IGNhbiBhbGwgcm90MTMgY
        W5kIHBhY2soKS4gQnV0IGRvIHlvdS
        ByZWNvZ25pc2UgQmFzZTY0IHdoZW4
        geW91IHNlZSBpdD8gIC0tIEp1ZXJk
        

      I'm convinced my source is safe.

      Well that must make you the only programmer in the world who has thought of every angle. Even with open source code with many years of use and review vulnerabilities still crop up.

      There are many cliches but perhaps "Pride cometh before the fall" is the most appropriate.

      cheers

      tachyon

      s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

      Like the old saying: "Pride precedes a fall". I'd rather prepare for a big push from an unexpected direction. You know it will come.
Re: Does fatalsToBrowser give too much information to a cracker?
by Seumas (Curate) on Apr 10, 2002 at 19:57 UTC

    I prefer not to use fatalsToBrowser in production because I don't want to expose paths, file names or specific errors to users. I sometimes use it in development, but find that tailing my server logs in another window is just as easy.

    In my current project, I use cluck() to send a stack trace and error to my server logs when something goes wrong and just print out a generic error to my users. For my purposes, I don't need them to know what the specific problem is (it probably won't help them to know if it's a database error as opposed to a code error, for example).

    Here's a crude example of what I currently use. I'm sure there are a number of far better solutions, but this seems to work for me right now (and I'm still developing my debugging/error-reporting/error-handling skills):

    sub ErrorHandler { if ($DBI::errstr) { cluck("The following database error occurred:\n $DBI::errstr") +; print "Error message to display to your users."; } else { cluck "An error has occurred"; print "Error message to display to your users."; } }
Re: Does fatalsToBrowser give too much information to a cracker?
by ajt (Prior) on Apr 11, 2002 at 09:13 UTC
    I think that you are correct that fatalsToBrowser is unwise in production code. If it gives you enough information to be helpful during development, then I'm sure it gives enough to help a cracker.

    There are two kinds of errors though, application errors, and user errors.

    • With Application errors, I think the standard 500 error message is all that the user needs to see, though you can spruse the 500 message error page up if you want - though an email or debug dump to the server log is still wise.
    • User error, and here you need to tell the user something so that they can fix their input, without giving a cracker any additional information. I think that when possible this is best caught in the browser with JavaScript and good interface design, before the CGI process starts.

    While security through obscurity isn't a viable approach on it's own, there is no point in giving crackers a free ride.

    I'm currently working on Perlfect Search which does use fatalsToBrowser, and I'm in the process removing it and making it run under strict.....

    My humble 2 credits.

Re: Does fatalsToBrowser give too much information to a cracker?
by DaWolf (Curate) on Apr 10, 2002 at 19:26 UTC
    I always prefer to do my own error handling sub routines. I think you should only use fatalsToBrowser in the development stage.

    After this you should disable it and put people testing the system so you know if there is any situation that wasn't covered by your error subs.

    Remember that you should cover even errors that wasn't generated by human action like database connection errors and stuff.

    BTW, there's no such thing as the perfectly safe system. Think systems as houses: a thief can break in any house, but if you lock your doors and windows or allow only identified people to get in, your "safety level" is increased.

    Just my thoughts on this : )

    Er Galvão Abbott
    a.k.a. Lobo, DaWolf
    Webdeveloper
Re: Does fatalsToBrowser give too much information to a cracker?
by BUU (Prior) on Apr 10, 2002 at 16:05 UTC
    In terms of aesthetics .. the 500 error page is just ugly. However, for the most part it doesnt give you any more or less information then most 'dienice' pages, as they usually just say 'there has been a problem'. However, a dienice routine does confirm that the error is on their side, not your browser. (Yes im aware cgi=serverside, however browsers can do funny things.)
      However, a dienice routine does confirm that the error is on their side, not your browser.

      That is quite true. However, there is no need to give any more information than that the problem was indeed server-side, how to contact the administrator, what information to provide when contacting the admin, and what to do instead (such as try again later). I usually find that when I get the time and date of when an error occurred, I can find out what went wrong by looking at the error-log. Of course, often enough the user will be pissed off, to various degrees, but against that, hardly any dienice-routine helps ... (:

      --cs

      There are nights when the wolves are silent and only the moon howls. - George Carlin

      A reply falls below the community's threshold of quality. You may see it by logging in.
      In terms of aesthetics .. the 500 error page is just ugly.

      Well, yeah. But what's stopping you from defining your own? Most web servers allow you to control exactly what the error pages look like.

      --
      <http://www.dave.org.uk>

      "The first rule of Perl club is you do not talk about Perl club."
      -- Chip Salzenberg

A reply falls below the community's threshold of quality. You may see it by logging in.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others sharing their wisdom with the Monastery: (4)
As of 2024-04-19 19:00 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found