Security – PHP Certification Exam Series [6]


PHP Security - PHP Certification exam

Introduction: This is the sixth part of my study notes for the Zend PHP Certification Exam. You can read more about my PHP Certification exam journey here.

PHP Server Security Measures

CGI Binary

  • Prevent Accessing System Files: PHP doesn’t interpret command line arguments passed by the interpreter (e.g. http://my.host/cgi-bin/php?/etc/passwd)
  • Prevent Accessing Private Documents: use cgi.force_redirect, doc_root (only files inside will be executed) and user_dir (a directory under doc_root) (e.g. http://my.host/cgi-bin/php/secret/doc.html needs to be redirected)
  • Prevent Accessing Public Files (no access control): –-enable-force-cgi-redirect can be added to ensure a request has been safely redirected
  • Prevent Directly Calling PHP: cgi.force_redirect blocks calling PHP directly from URL
  • Safeguard the Parser: place the parser outside of web tree, e.g. in  /usr/local/bin, the parser needs to compile with the –enable-discard-path option
  • Safeguard Active Contents (scripts, executables): put scripts and executables in a separate directory to prevent displaying the contents as html; set doc_root/PHP_DOCUMENT_ROOT to be outside web root, or user_dir to open file in the user’s directory only

Apache Module

  • Will inherit the permission structure of the Apache server
  • Set the Apache authorization (instead of the default ‘nobody’ setting)
  • Create an access model using .htaccess files, LDAP, …
  • Do not endow the user with root permission (which would permit sudo, chroot, etc.), rather use open_basedir (limit the files that can be open by e.g. fopen) to control directory use for file manipulation, open_basedir can be tightened at runtime with ini_set()
  • doc_root to be used with safe_mode to restrict files to be served only from the designated root directory

General Settings

  • A system is only as good as the weakest link in a chain
  • register_globals = off;
  • error_reporting = E_ALL & ~E_DEPRECATED; (when coding, enable also E_STRICT)
  • to scrutinize all functions, and attempt to compensate for the bulk of the errors
  • to disable error reporting entirely on the running code (display_errors = off; log_errors = on; error_log=$path;)
  • to use PHP’s custom error handling functions to create your own error handler.
  • allow_url_include = off; allow_url_fopen = off (on by default) – network resources will still be accessible through fsockopen or CURL functions.;
  • expose_php= off; in php.ini file, the amount of information available is reduced
  • safe_mode will be discarded in PHP6
  • may use .htaccess to parse every file (including .html,etc.) by php so as to hide PHP from possible attackers
  • keep PHP up-to-date
  • open_basedir – Restricts PHP’s file acces to one or more specified directories, can be tightened at runtime
  • safe_mode – limits file access based on uid/gid of running script and file to be accessed. Slower, doesn’t work well with uploaded files.
  • disable_functions – This directive allows you to disable certain functions for security reasons. It takes on a comma-delimited list of function names, e.g. disable_functions=exec,passthru,shell_exec,system
  • disable_classes – This directive allows you to disable certain classes for security reasons. It takes on a comma-delimited list of class names
  • HTTP authenticationIn the HTTP authentication, the header() function is used for sending an “Authentication Required” (Error 401) message to the client browser, which asks for Username/Password. When the user fills his username and password, the URL containing the PHP script will be called with pre-defined variables PHP_AUTH_USER, PHP_AUTH_PW, and AUTH_TYPE. These variables can be retrieved in the $_SERVER and $HTTP_SERVER_VARS arrays.

Magic Quotes

  • all ‘ (single-quote), ” (double quote), \ (backslash) and NULL characters are escaped with a backslash automatically
  • identical to addslashes()
  • magic_quotes_gpc: after GET, POST, COOKIES only
  • magic_quotes_runtime: most functions that return data from an external source, including databases and text files, will have quotes escaped with a backslash
  • magic_quotes_sybase: a single-quote is escaped with a single-quote instead of a backslash, overrides magic_quote_gpc
  • is disabled by default in PHP5 and removed from PHP5.5, to maintain backward compatibility may need to use the following code:  if(get_magic_quotes_gpc()) {$string = stripslashes($string);}

Input Filtering and Validation

  • Validation or Filtering is the process by which you subject data to a series of rules, either it passes (validates) or does not
  • attackers may use non-standard char set which may be missed by filtering functions
  • null bytes (\0) attached to string will create vulnerability
  • need to convert the charsets before filtering, use native database filtering functions
  • never rely on client side javascript filtering
  • filter_input ( $type, $variable_name, $filter, $option ) – gets a specific external variable by name and optionally filters it, $type: INPUT_GET, INPUT_POST, INPUT_COOKIE, INPUT_ENV, INPUT_SERVER, $filter: FILTER_VALIDATE_BOOLEAN, FILTER_VALIDATE_EMAIL, FILTER_VALIDATE_URL,
    FILTER_VALIDATE_REGEXP,FILTER_SANITIZE_EMAIL, FILTER_SANITIZE_ENCODED, FILTER_SANITIZE_SPECIAL_CHARS, FILTER_SANITIZE_MAGIC_QUOTES, etc.; e.g. $search_url = filter_input(INPUT_GET, ‘search’, FILTER_SANITIZE_ENCODED);
  • bool ctype_alnum ( string $text ) – Check for alphanumeric character(s)
  • ctype_alpha – Check for alphabetic character(s)
  • ctype_cntrl – Check for control character(s)
  • ctype_digit – Check for numeric character(s)
  • ctype_graph – Check for any printable character(s) except space
  • ctype_lower – Check for lowercase character(s)
  • ctype_print – Check for printable character(s)
  • ctype_punct – Check for any printable character which is not whitespace or an alphanumeric character
  • ctype_space – Check for whitespace character(s)
  • ctype_upper – Check for uppercase character(s)
  • ctype_xdigit – Check for character(s) representing a hexadecimal digit

Output Escaping

  • Escaping is the process by which you prepare data for a specific resource by “escaping” certain portions of the data to avoid confusion of instruction and data (e.g. sql)
  • string strip_tags ( string $str [, string $allowable_tags ] ) – Remove anything that looks like an HTML tag from a string
  • string htmlentities ( string $string [, int $quote_style = ENT_COMPAT [, string $charset [, bool $double_encode = true ]]] ) – Convert any character that has a specific HTML entity into it
  • ENT_COMPAT – convert double-quotes and leave single-quotes alone
  • ENT_QUOTES – convert both double and single quotes
  • ENT_NOQUOTES – leave both double and single quotes unconverted
  • string htmlspecialchars ( string $string [, int $quote_style = ENT_COMPAT [, string $charset [, bool $double_encode = true ]]] ) – Convert &, “, ‘, <, >into their entities

Email Injection

  • not to provide open relays [An open mail relay is an SMTP server configured in such a way that it allows anyone on the Internet to send e-mail through it, not just mail destined to or originating from known users. This used to be the default configuration in many mail servers]
  • open the SMTP port only if necessary
  • a malicious user may exploit the MIME format to append additional information to the message being sent, such as a new list of recipients or a completely different message body
  • could utilize “tarpits” to delay incoming connections with delayed response (not work with HTTP requests)
  • by entering hexadecimal characters in the form field they are able to add carriage returns and spaces. So the following string entered in a form field such as “Your Email”:
  • [email protected]%0ACc:[email protected]%0ABcc:[email protected],[email protected]
  • will result in a carbon copy of the email being sent to [email protected] and a blind carbon copy being sent to v[email protected] and [email protected]

Remote Code Injection

  • PHP provides great power with the exec(), system() and passthru() functions, as well as the ‘ (backtick) operator
  • exploit include OR require functions, or the eval() function on user supplied data
  • or preg_replace with the /e pattern modifier [to evaluate expression, not statement] and the create_function()
  • Include Files Attacks: possible from remote servers; check data against a whitelist (for codes), remove paths using basename() and use include_path instead, set allow_url_fopen = off in php.ini
  • Dynamic Data Call Attacks: code injection when using dynamic data in system(), etc. calls; do not use system(), escapeshellargs() to escape arguments, escapeshellcmd() to escape commands (characters are preceded by a backslash: #&;`|*?~<>^()[]{}$\, \x0A and \xFF. ‘ and ” are escaped only if they are not paired)

SQL Injection

  • defend in depth
  • custom SQL code is injected into normal queries to perform any tasks the database user is privileged
  • e.g. SELECT * FROM users WHERE username=’$user’, the attacker passes or ”=’ for $user to view all the data in the users table
  • can be prevented by prepared statements or database specific escape functions, e.g. mysqli_real_escape_string() [to escape all special characters including ‘”, note: addslashes() is NOT sufficient ]

Cross-site Scripting XSS

  • attacker injects code/link through html/css/javascript into your page that re-writes the page to do something malicious
  • can be prevented through proper escaping and data validation, e.g. htmlspecialchars(), htmlentities() or strip_tags()

Cross-site Request Forgeries CSRF

  • attacker exploits another sites to execute HTTP requests and transmit sensitive information to the attacker
  • relies on website trust of logged-in users
  • executed via Iframe, XMLHttpRequest requests or <script>, <object>, <embed>, <img>, etc.
  • can be prevented by setting a unique token (generate a random string stored $_SESSION and add to the form in a hidden input field) in the request form or require re-login when accessing sensitive operations
  • ensure there’s no crossdomain.xml file granting unintended access to Flash movies
  • check the HTTP referrer header
  • limit the lifetime of authentication cookies

Session Attacks

  • Basically, combine cookies containing a session ID with a local(ish) data store corresponding to that session id
  • If the session id is compromised, or the data store is not secure (/tmp on a shared machine) sessions are vulnerable to attack

Session Fixation

  • a user gets a “fixed” session ID
  • an attacker tricks a user into clicking on a link with a fixed session id

Session Hijacking

  • the session ID is stolen
  • released by the link containing the session id or the cookie containing the session id gets stolen

Security Measures

  • by default the cookie name is PHPSESSID, may use session_name() or setting in php.ini to change the cookie name
  • session_regenerate_id(false|true) upon login and before authentication and before critical operations (may need reenter password), true will delete the session info
  • may check User-Agent header which should be fixed for a particular session ($_SESSION[‘user_agent] =  $_SERVER[‘HTTP_USER_AGENT’];)
  • use SSL for login
  • populate a hidden random key in the login form (not quite secure)
  • check IP address remains the same across different requests
  • use short session timeout (session.gc_maxlifetime is a way to set, but not quite reliable as it depends on the execution of garbage collector), may need to use a custom function to set inactive time
  • restrict to use cookie only: session.use_only_cookies = TRUE

Encryption, Hashing algorithms

  • Use hash values to store sensitive data: md5( ) 32 char, hexadecimal, sha1( ) 40 char, hexadecimal, cannot be reversed but vulnerable to a brute-force attack
  • Use crypt($string,$optional_salt) for password storage
  • – one-way encryption of $string, return a hashed string using the standard Unix DES-based algorithm or alternative algorithms that may be available on the system (from PHP 5.3, PHP contains its now implementation of algorithms), e.g. $hashed_password = crypt(‘mypassword’); if (crypt($user_input, $hashed_password) == $hashed_password) { echo “Password verified!”; }

File uploads

  • Assign 0770 or 0600 permission to upload folder
  • Check the file using PHP functions (basename(), is_uploaded_file() and move_uploaded_file(), $_FILES[‘example’][‘error’]==UPLOAD_ERR_OK, etc.)
  • Ignore the MIME type
  • Disable directory indexes and script exection (using .htaccess or server settings)
  • Place the upload folder outside WWW root
  • If you are allowing your users to upload image files (jpg,gif,png), you should calculate the size using getimagesize() function with PHP. If the uploaded file is really an image file, it returns true as otherwise it fails.

Database storage

  • beware of SQL injection
  • limit the privileges/connection of database user, use a different user account (with limited privileges) when accessing the database
  • all business logics should better be done in views/triggers in the database
  • continuous monitoring for irregularities
  • Secure Shell Protocol encrypts the connection between the client and the server
  • log all user inputs and examine from time to time
  • use mcrypt() and mhash() to encrypt the sensitive data first (need to install mcrypt extension)
<?php
key = "this is a secret key";
$input = "Let us meet at 9 o'clock at the secret place.";

$td = mcrypt_module_open('tripledes', '', 'ecb', '');
$iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
mcrypt_generic_init($td, $key, $iv);
$encrypted_data = mcrypt_generic($td, $input);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
mhash($hash , $data [, $key ]) to return the resulting hash (also called digest) or HMAC [if $key is set] as a string, or FALSE on error, $hash is the hash ID
?>

 

 

You can read more about my PHP Certification exam journey here.

GreyCampus PMP online training course bundle for US$149 only

Support website running for FREE, thanks!

If you find this post helpful and if you are thinking of buying from Amazon, please support the running cost of this website at no extra cost to you by searching and buying through the search box below. Thank you very much for your help!

Edward Chung

Edward Chung aspires to become a full-stack web developer and project manager. In the quest to become a more competent professional, Edward studied for and passed the PMP Certification, ITIL v3 Foundation Certification, PMI-ACP Certification and Zend PHP Certification. Edward shares his certification experience and resources here in the hope of helping others who are pursuing these certification exams to achieve exam success.

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *

2 Responses

  1. mahak says:

    I want to give zend php exam.and I am reffering to your notes.can a fresher clear the zend exam.like how tough is it?
    and what are the test series that I should refer to.