Devlogs
Application must filter all possible forms of input data, either provided by the user or obtained from environment, database systems, web services or any other external systems.
Whole filtering must be made or repeated at server side. Client-side filtering can NEVER be trusted as it can be easily bypassed by malicious user. Do not assume that form's hidden fields, checkboxes, radio buttons or selection boxes are safe.
All input data must be filtered prior to use. It must be proved to match expected form and meet actual business rules, i.e. it must be not only of correct type, size (including length and range) and syntax, but also has proper meaning (e.g. credit card number).
Filtering strategies
Filtering approaches
Safer approach is always whitelist.
Input data sources
Identify untrusted input sources
$REQUEST should never be used to fetch input data (it introduces similar problems to registerglobals as it practically combines GET and POST arrays as well as cookies into a single array).
Numeric data
Casting to desired numeric type, e.g. (int)$GET['id'], (float)$GET['price']. Cast forces converting string to desired numeric type. But: Casting does not work for hexadecimal numbers, octal numbers and scientific
notation. is_numeric() is lower but more flexible
Range issues: * integer - if potential value exceeds max available integer then cast to float and cut everything after decimal, on 32-bit system max integer is merely 2147483647 (PHPINTMAX) * float - stores big numbers in scientific notation
Strings
Filtering strings is usually a little complex and involves using a number of various ways and functions depending on what type of data variable should represent (URI, phone number, credit card number, username, date, time, etc).
File uploads
Turn off file uploads if you don't use them (file_uploads = off).
Limit the maximum size of an uploaded file using uploadmaxfilesize directive. Be aware that postmaxsize and memory_limit may affect this setting.
Change directory where uploads are stored (uploadtmpdir = "path/to/safe/dir") as PHP uses world-readable temporary directory by default. Any user from given shared host or simply Apache process has usually permission to read and write to the files in this directory. Note that using Suhosin cookie and session data are encrypted.
$_FILES contains data for each uploaded file. It should be handled with care.
Prior to filtering anything, use isuploadedfile() to check whether file was actually uploaded.
All uploaded file should be moved to desired destination directory only using moveuploadedfile(). It may be necessary to call it at the beginning to avoid
openbasedir and safemode restrictions.
Serialized data
Use checksum (generated by hash_hmac()) to validate serialized data. Check checksum before unserializing. Secret key used for hashing should be random and at least 10-chars long.
Output
Output is HTML, JavaScript, JSON, databases, XML, feeds, shell commands, etc/
Ensure you escape (and encode special characters into corresponding HTML entities) all data before displaying it (prior to sending the output).
Integrity checks
Integrity checks - ensure that the data has not been tampered with/corrupted and is the same as before [OWASP05]. Integrity control types: checksum, HMAC, encryption, digital signaure depending on the security level. The preferred integrity control should be at least a HMAC using SHA-256 or preferably digitally signed or encrypted using PGP [OWASP05].
References / Further Reading
$_REQUEST is all $_POST, $_GET and $_COOKIE array combined together in one big array in order configured by variables_order. It can result in ugly bugs when you have name conflicts, some values from one array will overwrite values from other array, eg. when you have $_GET['type'] and $_COOKIE['type'], which do different things, then for a given request, if you haven't set $_GET['type'], $_COOKIE['type'] will be taken, when $_REQUEST['type'] is used. Maybe it's not serious security flaw, but for the sake of clarity and your own tranqullity, you should be aware what is your actual real input source.
Typo has been corrected. Thanks.
over 1 year ago David R http://blog.davr.org #0
Nice summary of issues.
What's wrong exactly with $_REQUEST? As long as you filter the data correctly, how is it unsafe compared to getting the data from a cookie or from GET/POST?
Also there's a typo under your 'whitelist' definition. The last word 'valid' should be 'invalid'