(Un)trusted input

All user input is to be considered untrusted. Seemingly “trusted/safe” input, like some $_SERVER variables in PHP, can be easily manipulated by attackers.

To prevent this type of attack

  • Thoroughly filter/escape any untrusted content.
  • If the allowed character set for certain input fields is limited, check that the input is valid before using it.
  • If in doubt about a certain kind of data (e.g. server variable), treat it as untrusted.
  • If you are sure, but there is no real need to treat it as trusted, treat it as untrusted.
  • The request URL (e.g. in environment variables) is untrusted.
  • Data coming from HTTP headers is untrusted.
    • Referer
    • X-Forwarded-For
    • Cookies
    • Server name (!)
  • All POST and GET data is untrusted.
    • Includes non-user-modifiable input fields like select
  • All content validation is to be done server side.

Rationale

Escaping or filtering “trusted” input that should not contain any characters that require escaping will only give you a negligible performance penalty, but you will be on the safe side if the input turns out to be untrusted.

Validating input data using a character whitelist can avoid attacks using unexpected characters (null bytes, UTF-8, control characters used as delimiters in internal representations etc.). Ensure your validation is not too strict, for example you will need to allow both UTF-8 and characters like ' in person name fields.

An attacker is not constrained by the constraints a browser puts on him. Just because an input field is specified with maxlength=20 does not mean that an attacker cannot craft a request with 200 KB of data. The same goes for any JavaScript based constraints.

Further reading

Notes

The original source for this page is the associated Wikibooks article and is shared here under the CC BY-SA 3.0 license.