Security Pitfalls for Inexperienced Web Designers

by Savage Monkey

I am a college student and I often have the opportunity to use and assist with websites developed by other students.

Doing so has given me an appreciation for common security holes introduced by inexperienced web designers.  Here I will provide a few examples of what not to do, or, from the sysadmin's point of view, what to make sure your users don't do.

First of all, validate all input, including GET/POST data you think only your own pages will produce, cookies produced by your own site, and, of course, user form data.  Pay particular attention to anything where a parameter specifies a file to fetch or a command to run.

One site I saw recently allowed users to specify, in a text field, arguments to fortune.  The CGI script would then run something like fortune $user args without any checks, allowing the user to pass a parameter like ; rm -rf or literally anything else he wanted.

If you really must put user data in backticks, consider giving the user a set of options to choose from.

For instance, allow the user to check if he wants an offensive fortune, rather than letting him type any parameter he can think of.

Similar problems can occur when parameters specify files to fetch, especially with functions like file() and readfile() in PHP, which will work on virtually any resource, including local files and URLs.

Many sites load different pages using something like: http://www.example.com/index.php?page2fetch=sales.html

Lazy webmasters will neglect to verify that sales.html is indeed a part of the website, letting a malicious user specify page2fetch=/etc/passwd, for instance, to examine an arbitrary local file, or page2fetch=http://www.google.com, e.g., to use your site as a proxy.

Some webmasters think they can solve this problem by appending a particular extension (html, say) to the page2fetch parameter.  They're generally wrong.  Enemies can circumvent this by appending a null character to the end of the parameter, tricking the system into ignoring the appended extension, and if this fails to work, they can still access unintended resources ending in the given extension.

The only safe way to use this technique is to give index.php a whitelist of acceptable pages to fetch, and serving an error page if page2fetch is not on this list.

Use a similar method for other input as well.

If your site requires someone to register with an email address ending in 2600.com, you may realize (as many webmasters fail to) that a malicious user could register with something like:

joeschmo@gmail.com,nobody@2600.com

Which, with poor authentication, would cause the registration info to be emailed both to:

joeschmo@gmail.com and nobody@2600.com

Or with something like: <joeschmo@gmail.com>nobody@2600.com - where the email would be sent to joeschmo, with nobody@2600.com treated by the email system as a comment.

Are there other tricks someone could use?

Don't spend time sifting through the email RFCs trying to figure it out.  Err on the side of caution, and make sure every email address matches some regexp like: [A-Za-z0-9]+@2600\.com

If there's a problem, you'll hear about it.  If an unauthorized user opens an account, you may not until after he's stolen confidential information, or whatever it is that you feel you need to protect.  Use this technique everywhere.  Don't try to look for weird patterns and rule them out; look for normal ones and allow them exclusively.

In general, don't believe anything your users tell you.

If you're selling something, don't pass the price in URL or the POST data; just pass the item ID and look up the price in your own database.

Use session keys; don't have the user pass the same authentication over and over where it's vulnerable to replay attacks.

Don't assume that nobody will tamper with the POST data, or nobody will edit their cookies.  Somebody will, and even if somebody doesn't, somebody else will read your code and laugh at you.

Also, don't reinvent the wheel, unless you're either really good or you just don't care.  Don't invent your own new kind of encryption that looks pretty good to you.  Don't even implement something you read about in cryptography class yourself.  Why bother?  People more paranoid than you or me devote their lives to doing it securely.  Why not use their work?

Don't write your own forum software; download an open-source package.  They'll have more features than you have time to implement, a prettier look than you would have the patience to perfect and they'll have more eyeballs examining the code for bugs than you could ever have.

Just make sure to keep the software up to date.  A widely-deployed package with a well-known security hole is extremely dangerous, since script kiddies and worms will find you on Google and pick on you.

HTML, Perl, and PHP are easy.

Downloading phpBB2 tarballs from the Internet and typing tar -xfz is even easier.

Keeping your websites secure takes practice, but it's not impossible.

Web design is one of the few fields in which it's possible to achieve greater security without compromising convenience and usability, so there's no reason to leave yourself (and your web host) vulnerable to attack.

Return to $2600 Index