PHP 411

Variables
  • Always initialise variables, particularly if register_globals is enabled.
Ensure input is filtered
  • All user-supplied data must be inspected to ensure that it is valid before it is accepted for use. This includes all $_GET, $_POST (including hidden fields!), cookie (and session?) variables.
  • Use a 'whitelist' approach: Data is considered invalid unless it can be proven to be valid.
    • Check all required variables are present.
    • Check that values have been assigned.
    • Check the data type is as expected. Functions include:
      • is_string()
      • is_numeric()
      • is_float()
      • is_array()
      • is_object()
      • Ctype functions permit more specific screening of input (see PHP manual).
    • Check the value is within acceptable ranges. For example:
      • A select box should only return one of the listed values.
      • Names should only include alphanumeric characters.
    • Reject data that does not conform to expectations.
Eliminating SQL injection
  • An SQL injection vulnerability exists whenever you used un-escaped data in an SQL query.
  • Use msql_real_escape_string() to escape output.
    • $username = mysql_real_escape_string( $previously_filtered_data[ 'username' ] );
  • All values within a query should be contained within quotes regardless of data type.
  • Queries that alter the database should be within a $_POST request rather than $_GET.
Cross-site scripting (maybe should be called 'html injection')
  • A vulnerability exists whenever un-escaped data is output, eg:
    • echo $_POST[ 'user_input' ] // what if user submitted something nasty?
  • Escape the data with htmlentities:
    • $html[ 'user_input' ] = htmlentities( $_POST[ 'user_input', ENT_QUOTES, 'UTF-8');
    • echo $html;
  • URLs containing variables that could potentially have been manipulated by users need to be escaped twice:
    • $URL[ 'value' ] = urlencode( $value ); // escapes the value variable
    • $link = "http://www.link.com?variable={$url[ 'value' ]}";
    • $html[ 'link' = htmlentities( $link, ENT_QUOTES, 'UTF-8' ); // escapes the html
Session fixation
  • May be conducted as a prelude to session hijacking. To prevent, regenerate the session identifier with session_regenerate_id() whenever there is an escalation of privilege (eg. logging in).
Filenames
  • Be wary of opening files with user-supplied 'filename data'. Users may pass something nasty instead, like a relative path to a sensitive local file or a URL to open a remote file with exploit code. Don't forget that fopen(), include() and require() all accept URLs as arguments. To prevent problems:
    • Disable remote file access (allow_url_fopen).
    • Use the open_basedir option in PHP to restrict filesystem access.
    • Check filenames with realpath() and basename().
  • If you have to allow users to specify a file name, use a combination of realpath() and basename() to verify the relative path to the file on your site:
    • realpath() returns the full path to a file, resolving any special characters like directory traversals.
    • Basename() just returns the file name from the path.
    • Combine them to verify the file name by resolving the full path to the file then extracting the file name and comparing it with the user-supplied one:
      •         $filename = $_POST[ 'filename' ];
                $verified_file_name  =  basename( realpath ($filename ) );
                if ($suspect_file_name !== cleaned_file_name) {
                    //error
                }
                
File uploads
  • Don't use user-supplied filenames sent by a browser. Create your own temporary file name to handle it.
  • Set a maximum uploadable file size with post_max_size in php.ini to avoid DOS attempts to jam your server.
  • Cookies can be used to overwrite global variables in GET and POST. Check that the uploaded file really *has* been uploaded using is_uploaded_file()
  • Use PHP's move_uploaded_file() which moves a file only if it was uploaded. Use this in preference to copy() or system level functions.
File access
  • Restrict filesystem acess to a specific directory using the open_basedir in php.ini.
  • Store sensitive data in the database in preference to files [perhaps trust_path is a better option in Impress?].
  • If you are on a shared server ask the hosting company to store your session files in your own session directory, because otherwise you are probably sharing a session directory with all the other people on the server and everyone's scripts can access everyone else's session files. This involves setting a session path in the VirtualHost block in Apache's httpd.conf.
    • php_value session.save_path /myown/path
  • If you have .htaccess rights and Apache is configured to let you over-ride options you may be able to make this change yourself.
PHP code
  • Disable dangerous function calls like system() and eval() by setting disable_functions in php.ini.
    • disable_functions system, eval
Environment
  • Disable the following in php.ini:
    • register_globals
    • magic_quotes_gpc
    • allow_url_fopen

Videos
Kaiyo
March 22, 2008
Hits 2137
Ayumi Hamasaki - Free & Easy
May 14, 2011
Hits 1977
BoA - Amazing Kiss
June 06, 2008
Hits 3601
© Copyright 2013 Eyenet Designs. All Rights Reserved.