The HTTP 500 SolutionMy online backup service offers bug bounties for mistakes in the client software; while I explicitly exclude bugs in the Tarsnap website (with the exception of cosmetic errors) in an attempt to discourage people who blindly run vulnerability scanners against websites, I still get a lot of bogus "bug reports". One of the more common reports is "I managed to trigger an HTTP 500 Internal Server Error" response; what people don't realize is that this is in fact entirely deliberate, as part of what I call the "HTTP 500 Solution".
There are several ways to trigger such responses from my CGI scripts. For example, sending an application/x-www-form-urlencoded input which is syntactically invalid; sending a form or query string which has invalid percent-encoding; or sending a form or query string which encodes for a NUL byte in a name or value. All of these have one thing in common: They should never happen. Upon encountering such an invalid request, my CGI scripts respond very simply: They immediately exit — at which time Apache, having not seen any valid HTTP response from them, sends back a canned "Internal Error" response.
The crux of the matter is this: A CGI script offers a contract. Give it some appropriate input, and it will give you some output. But if you don't give it appropriate input, it doesn't owe you anything. Not a redirect to some other page on the website; not a helpful message to tell you precisely how your input was invalid; and certainly not an attempt to "fix" your input by stripping out the invalid parts. If you don't want to play by the rules, it's perfectly entitled to take its ball and go home.
More importantly, attempting to respond to invalid inputs is dangerous, for two reasons. First, in such a scenario we've already identified that someone is trying to be evil; it's entirely possible that there is more evil going on than we detected. And second, error-handling paths never receive as much testing, because they are not frequently encountered "in the field"; no matter how comprehensive your testing is (and most isn't, since there's almost always a bias towards testing things which should suceed rather than testing things which should fail) it will never cover as many combinations of strange inputs and obscure environments as your code is likely to encounter in production. Poorly tested code has more bugs per line; and when you're faced with the likelihood of a large number of bugs per line of code — whether it's due to poor testing, poor developers, or merely because the code is difficult for reviewers to understand — it's important to minimize the amount of bug-prone code. The shortest possible error-handling path is "exit(1);".
Postel's law states that one should be conservative in what one does, but liberal in what one accepts from others; this is great advice for life, but terrible advice for writing software. When it comes to software security, it's better to be conservative in what one does and paranoid in what one accepts from others — and prone to freeze when surprised.
blog comments powered by Disqus