With PHP scripts, the security aspects are essentially focused on two points: preventing cross-site scripting (CSS or XSS) and preventing data sniffing or code infiltration. To offer adequate protection, it is necessary to check all external data that your scripts process. This includes data provided in the URL, form data, cookies and uploaded files.

Please note: The list of safety precautions mentioned here is not to be regarded as complete, but serves to detect some fundamental risks.

A security concept must consider all the factors that could lead to a potential vulnerability. Securing scripts is only one component of the overall concept.

Insert Code Using the include() Function

A common vulnerability is that the include() function is used with variable parameters. In this case, an attacker can inject foreign code by passing a URL as a parameter (e.g. http://evil-site.tld/exploit.txt). This code, or URL, is then executed as if it were part of the script. Avoid calling include() with a variable value and use constants instead of variables. If the use of variables is unavoidable, filter their contents accordingly. This can be done with the following code, for example.

if (strpos($variable, '://') !== FALSE || strpos($variable, '../') !== FALSE)
die('Illegal string'); 

This code checks if the $variable string contains :// (as in http:// or ftp://), or ../ (as in ../../secret/passwords), and terminates execution if necessary.

SQL Injection

When a script uses database queries, it is relatively easy for an attacker to inject arbitrary SQL code if the script does not include some security checks. This enables a potential attacker to read, change or even delete data.

Suppose you use the following code in a script:

[...]
$sql = "SELECT * FROM adressen WHERE name='".$_GET['name']."'";
$result = mysql_query($sql);
[...]        

This or a similar query may appear if you want to filter out the address for a particular name from a table containing addresses.

The attacker can now access the PHP page that contains the code for performing the query, and inject additional SQL commands. If the page containing the SQL query code is 'select.php' and your website is 'example.com', the attacker could put the following URL into the browser and inject SQL commands: http://example.com/select.php?name=';DELETE FROM addresses WHERE 1=1 OR name='.

This results in the SQL query SELECT * FROM addresses WHERE name=''; DELETE FROM addresses WHERE 1=1 OR name='';.

First, the database server selects all records for which the Name field contains an empty string. This bypasses your scripts intended purpose.  The injected command then delets all records from the table. It's also possible to for the attacker to use this type of vulnerability to read or change data in the database as well.

To protect against this, variables in SQL queries should always be transformed using the mysql_real_escape_string() function. Special characters such as the single quotation mark are masked, so that they are not interpreted as part of the PHP or SQL code. If values are passed outside quotation marks (e.g. numeric values), use the intval() function if possible. This ensures that only one numeric value is actually used.

Transfer of Parameters in URLs

Passing parameters in URLs (e.g. http://example.com/script.php?id=1) is a common way to pass arguments to scripts. However, you should always be aware that these arguments can be set at will by the user. This means that its content must be considered untrustworthy. The same applies to data transmitted via HTTP mail and cookies.

This is important when redirecting from one script to another and passing parameters in the URL or as a cookie. The new script cannot consider these parameters as trustworthy, but has to check them all again. Often it is easier to use the session functions of PHP. Data that has been checked and stored in the session can now be classified and used as secure. The user has no possibility to change the content of the session directly.

The session identifier is passed as a parameter with the URL. Since this is a randomly generated string, the probability that an attacker can guess the identifier of a foreign session is extremely low.

Global Variables

In older versions of PHP, parameters passed from forms or in the URL were entered in global variables. For reasons of compatibility, however, current versions still reproduce this behavior on most systems.
For example, if the URL http://example.com/script.php?variable=content is called, a variable with the name $variable and the content content is set in the script.

This can become a problem if you use global variables internally without initializing them correctly beforehand.

Example:

<?php
if ($_GET['password'] == 'secretpassword') {
$admin = true;
}

[...]

if ($admin) {
// Actions reserved for an administrator who knows the password.
[...]
}
?>

An attacker could simply call the URL http://example.com/script.php?admin=1 and immediately have administrator rights, because the variable $admin returns true.

With correct initialization, this can be prevented.

<?php
$admin = false;

if ($_GET['password'] == 'secretpassword') {
$admin = true;
}

[...]

if ($admin) {
// Actions reserved for an administrator who knows the password.
[...]
}
?>

Now the value for $admin is always set to false in the beginning, and only set to true if the password has actually been passed.

In other scenarios, the omission of the initialization can also be used for SQL injections. For this reason you should get used to initializing all variables, although the syntax of PHP does not require this.

Cross-site Scripting

Cross-site scripting is  where an attacker inserts JavaScript code into a foreign site to obtain sensitive information. This can be used to access other session IDs or to determine user names.

To do this, an attacker creates a URL in which he sets parameters that are immediately displayed in the text of the page. If this text now contains script code, it is executed in the security context of the page, e.g. it can read cookies that have been set by this page. The danger of this type of attack is that it is almost invisible to the user when it occurs in a hidden frame.

The solution is to use the htmlentities() function in the script for all variables to be output (especially those containing user input). This replaces characters with special meaning in HTML, such as < or >, with the corresponding entities. This simple measure allows you to eliminate most of the attack possibilities for cross-site scripting.