What is the correct way to make web form input safe for a variety of contexts?


What do you all think is the correct (read: most flexible, loosely coupled, most robust, etc.) way to make user input from the web safe for use in various parts of a web application? Obviously we can just use the respective sanitization functions for each context (database, display on screen, save on disk, etc.), but is there some general "pattern" for handling unsafe data and making it safe? Is there an established way to enforce treating it as unsafe unless it is properly made safe?

8/16/2009 2:48:06 AM

Like it's already been said, there are several things to take into account when you are concerned about web security. Here are some basic principals to take into account:

  • Avoid direct input from users being integrated into queries and variables.

So this means don't have something like $variable = $_POST['user_input']. For any situation like this, you are handing over too much control to the user. If the input affects some database query, always have whitelists to validate user input against. If the query is for a user name, validate against a list of good user names. Do NOT simply make a query with the user input dropped right in.

One (possible) exception is for a search string. In this case, you need to sanitize, simple as that.

  • Avoid storing user input without sanitation.

If the user is creating a profile or uploading info for other users, you have to either have a white-list of what kind of data is acceptable, or strip out anything that could be malicious. This not only for your system's security, but for your other users (See next point.)

  • NEVER output anything from a user to the browser without stripping it.

This is probably the most important thing that security consultants have emphasized to me. You can not simply rely on sanitizing input when it is received by the user. If you did not write the output yourself, always ensure that the output is innocuous by encoding any HTML characters or wrapping it in a <plaintext> tag. It is simple negligence on the part of the developer if user A uploads a bit of javascript that harms any other users that view that page. You will sleep better at night knowing that any and all user output can do nothing but appear as text on all browsers.

  • Never allow anyone but the user control the form.

XSS is easier than it should be and a real pain to cover in one paragraph. Simply put, whenever you create a form, you are giving users access to a script that will handle form data. If I steal someone's session or someone's cookie, I can now talk to the script as though I was on the form page. I know the type of data it expects and the variables names it will look for. I can simply pass it those variables as though I were the user and the script can't tell the difference.

The above is not a matter of sanitation but of user validation. My last point is directly related to this idea.

  • Avoid using cookies for user validation or role validation.

If I can steal a user's cookie, I may be able to do more than make that one user have a bad day. If I notice the cookie has a value called "member", I can very easily change that value to "admin". Maybe it won't work, but for many scripts, I would have instant access to any admin-level info.

Simply put, there is not one easy way to secure a web form, but there are basic principals that simplify what you should be doing, and thus eases the stress of securing your scripts.

Once more for good measure:

  • Sanitize all input
  • Encode all output
  • Validate any input used for execution against a strict whitelist
  • Make sure the input is coming from the actual user
  • Never make any user or role-based validation browser-side/user-modifiable

And never assume that any one person's list is exhaustive or perfect.

8/16/2009 7:27:59 AM

Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow