ZCE 5.3



	// Only $_SESSION is safe.
	// Whitelists filtering better than blacklists
	// Filter input with ctype_*
	// Escape html output with htmlentities()
	// Escape sql with mysql_escape_string($sql)
	// Register_globals must be off

* Superglobals

All of PHP's superglobals arrays should be considered tainted.
Even $_SERVER array is not fully safe, because it contains some data provided by the client. 
Only $_SESSION is safe.

* Whitelist Filtering

Whitelists afford stronger protection against attacks than blacklists

* Filter Input

Server-side filtering is important for security, while client-side validation is important for usability. 

<?php // You should force the user to provide correct information // use ctype_* <form method="POST"> Username: <input type="text" name="username" /><br /> Password: <input type="text" name="password" /><br /> Collour: <select name="colour"> <option>Red</option> <option>Blue</option> <option>Yellow</option> <option>Green</option> </select><br /> <input type="submit" name="btn_submit"/> </form> <?php /* This form contains three input elements: username, password, and colour. Whitelist filtering: - username should contain only alphabetic characters - password should contain only alphanumeric characters - colour should contain any of "Red", "Blue", "Yellow", "Green" */ if (isset($_POST['btn_submit'])) { // Later in your code, when encountering the variable $clean[?], // you can be certain that this value has been filtered $clean = array(); // ctype functions are always preferred over regular expressions, // and even to some equivalent "str_*" and "is_*" functions // This is because of the fact that ctype uses a native C library // and thus processes significantly faster if (ctype_alpha($_POST['username'])) { $clean['username'] = $_POST['username']; } if (ctype_alnum($_POST['password'])) { $clean['password'] = $_POST['password']; } if (in_array($_POST['colour'], array("Red", "Blue", "Yellow", "Green"))) { $clean['colour'] = $_POST['colour']; } // var_dump($clean); }
  * Escape Output Escaping output protects the client and user from potentially damaging commands. For Html escape use htmlentities(). For sql escape use mysql_escape_string($sql).
<?php // For Html escape use htmlentities() $html = array(); $html['message'] = htmlentities($user_message, ENT_QUOTES, 'UTF-8'); // Assume that the value for $user_message comes from a database result set // Will convert both double and single quotes // Optional third argument encoding which defines encoding used in conversion <?php $message = "John's message is "Hellow World!""; echo htmlentities($message); // Source output: John's message is &quot;Hellow World!&quot; // default ENT_COMPAT // Will convert double-quotes and leave single-quotes alone echo htmlentities($message, ENT_QUOTES); // Source output: John&#039;s message is &quot;Hellow World!&quot; // ENT_QUOTES // Will convert both double and single quotes <?php echo '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />'; $message = "?tefan's message"; echo htmlentities($message, ENT_QUOTES, 'UTF-8'); // ?tefan&#039;s message <?php // For sql escape use mysql_escape_string($sql)
Register Globals When set to On, the register_globals configuration directive automatically injects variables into scripts.
<?php // Register_globals = on (security risks) <form method="POST"> Username: <input type="text" name="username" value="111aaa"/> <input type="submit" name="btn_submit"/> <input type='hidden' name='cleanUsername' value='1'> </form> <?php error_reporting(E_ALL & ~E_NOTICE); // register_globals = on (php.ini) / default is off if (isset($_POST['btn_submit'])) { if (ctype_alpha($_POST['username'])) { $cleanUsername = true; } if ($cleanUsername) { // will be loaded from globals echo $cleanUsername ? "Accepted" : "Denied"; // output accepted every time !!! } }
  A best practice for maintainable and manageable code is to use the appropriate superglobal $_GET, $_POST, $_COOKIE Before PHP 4.2.0, the register_globals configuration directive was set to On by default. Since then, this directive has been set to Off by default; as of PHP 6, it will no longer exist.