PHP gives developers great flexibility, but this also brings potential hidden dangers to security. Recently, I need to summarize past issues. Here, I will translate an article and add some of my own development experiences to summarize.

Introduction
When developing an internet service, you must always keep security concepts in mind and reflect them in the code you develop. The PHP scripting language does not care much about security issues, especially for most inexperienced developers. Whenever you are dealing with any transaction involving money or other financial matters, you need to pay special attention to security considerations, such as developing a forum or a shopping cart.
General Points for Security Protection
Do Not Trust Forms
For general JavaScript front-end validation, since you cannot know the user's behavior, such as turning off the browser's JavaScript engine, malicious data can be POSTed to the server. You need to validate on the server side, and for every PHP script, validate the data passed to it, to prevent XSS attacks and SQL injection.
Do Not Trust Users
Assume that every piece of data your website receives contains malicious code and hidden threats, and clean every piece of data.
Turn Off Global Variables
Make the following configuration in the php.ini file:
register_globals = Off
If this configuration option is turned on, there will be great security risks. For example, there is a process.php script file that inserts received data into the database. The form that receives user input data might look like this:
<input name="username" type="text" size="15" maxlength="64">
In this way, after submitting data to process.php, PHP will register a $username variable and submit this variable data to process.php. At the same time, for any POST or GET request parameter, such a variable will be set. If it is not explicitly initialized, the following problem will occur:
<?php
// Define $authorized = true only if user is authenticated
if (authenticated_user()) {
$authorized = true;
}
?>
Here, assuming the authenticated_user function simply checks the value of the $authorized variable, if the register_globals configuration is enabled, any user can send a request to set the $authorized variable to any value, thereby bypassing this verification.
All of this submitted data should be obtained through PHP's predefined built-in global arrays, including $_POST, $_GET, $_FILES, $_SERVER, $_REQUEST, etc. Among them, $_REQUEST is a combined variable of the three arrays $_GET/$_POST/$_COOKIE, and the default order is $_COOKIE, $_POST, $_GET.
- Recommended Security Configuration Options
Set error_reporting to Off: Do not expose error messages to users. During development, it can be set to ON.
Set safe_mode to Off
Set register_globals to Off
Disable the following functions: system, exec, passthru, shell_exec, proc_open, popen
Set open_basedir to /tmp, so that session information has storage permissions, and set up a separate website root directory.
Set expose_php to Off
Set allow_url_fopen to Off
Set allow_url_include to Off
SQL Injection Attack
For SQL statements that operate on a database, special attention must be paid to security, because users may enter specific statements that change the functionality of the original SQL statement. Similar to the example below:
$sql = "select * from pinfo where product = '$product'";
At this point, if the $product parameter entered by the user is:
39'; DROP pinfo; SELECT 'FOO
Then the final SQL statement becomes as follows:
select product from pinfo where product = '39'; DROP pinfo; SELECT 'FOO'
This will become three SQL statements, causing the pinfo table to be deleted, which will lead to serious consequences.
This problem can be simply solved using PHP's built-in functions:
$sql = 'Select * from pinfo where product = '"'
mysql_real_escape_string($product) . '"';
To prevent SQL injection attacks, two things must be done well:
Always perform type validation on input parameters
Always use the mysql_real_escape_string function to escape special characters such as single quotes, double quotes, and backticks.
However, based on development experience, do not enable PHP's Magic Quotes. This feature has been removed in PHP 6. Always escape manually when needed.
Preventing Basic XSS Attacks
XSS attacks are not like other attacks; this attack is carried out on the client side. The most basic XSS attack is to place a piece of JavaScript script on the form page that the user is about to submit, stealing the data and cookies submitted by the user.
XSS attacks are more difficult to defend against than SQL injection. Major company websites have been attacked by XSS. Although this attack is not related to the PHP language, PHP can be used to filter user data to achieve the purpose of protecting user data. Here, the main approach is to filter user data, generally filtering out HTML tags, especially <a> tags. Below is a common filtering method:
function transform_HTML($string, $length = null) {
// Helps prevent XSS attacks
// Remove dead space.
$string = trim($string);
// Prevent potential Unicode codec problems.
$string = utf8_decode($string);
// HTMLize HTML-specific characters.
$string = htmlentities($string, ENT_NOQUOTES);
$string = str_replace("#", "#", $string);
$string = str_replace("%", "%", $string);
$length = intval($length);
if ($length > 0) {
$string = substr($string, 0, $length);
}
return $string;
}
This function converts special HTML characters into HTML entities. When the browser renders this text, it is displayed as plain text. For example, <strong>bold</strong> will be displayed as:
<STRONG>BoldText</STRONG>
The core of the above function is the htmlentities function. This function converts special HTML tags into HTML entity characters, which can filter out most XSS attacks.
However, for experienced XSS attackers, there are more clever ways to attack: encoding their malicious code in hexadecimal or UTF-8 instead of ordinary ASCII text. For example, they can do it in the following way:
<a href="http://host/a.php?variable=%22%3e %3c%53%43%52%49%50%54%3e%44%6f%73%6f%6d%65%74%68%69%6e%67%6d%61%6c%69%63%69%6f%75%73%3c%2f%53%43%52%49%50%54%3e">
In this case, the actual result rendered by the browser is:
<a href="http://host/a.php?variable="> <SCRIPT>Dosomethingmalicious</SCRIPT>
This achieves the purpose of the attack. To prevent this situation, you need to additionally convert # and % to their corresponding entity symbols on the basis of the transform_HTML function, and add the $length parameter to limit the maximum length of the submitted data.
Using SafeHTML to Prevent XSS Attacks
The above protection against XSS attacks is very simple, but it does not include all user tags. At the same time, there are hundreds of ways to bypass the filtering function to submit JavaScript code, and there is no way to completely prevent this situation.
Currently, no single script can guarantee that it will not be breached by attacks, but there are always relatively better protection measures. There are two security protection methods: whitelist and blacklist. Among them, the whitelist is simpler and more effective.
A whitelist solution is SafeHTML, which is smart enough to identify valid HTML and then remove any dangerous tags. This needs to be parsed based on the HTMLSax package.
How to install and use SafeHTML:
1. Go tohttp://pixel-apes.com/safehtml/?page=safehtml Download the latest SafeHTML
2. Put the files into the server's classes directory, which contains all the SafeHTML and HTMLSax libraries.
3. Include the SafeHTML class file in your own script.
4. Create a SafeHTML object.
5. Use the parse method for filtering.
<?php
/* If you're storing the HTMLSax3.php in the /classes directory, along
with the safehtml.php script, define XML_HTMLSAX3 as a null string. */
define(XML_HTMLSAX3, '');
// Include the class file.
require_once('classes/safehtml.php');
// Define some sample bad code.
$data = "This data would raise an alert <script>alert('XSS Attack')</script>";
// Create a safehtml object.
$safehtml = new safehtml();
// Parse and sanitize the data.
$safe_data = $safehtml->parse($data);
// Display result.
echo 'The sanitized data is <br />' . $safe_data;
?>
SafeHTML cannot completely prevent XSS attacks; it is just a relatively complex script-based verification method.
Using One-Way HASH Encryption to Protect Data
One-way hash encryption ensures that each user's password is unique and cannot be deciphered. Only the end user knows the password; the system does not know the original password. One advantage of this is that even if the system is attacked, the attacker cannot know the original password data.
Encryption and hashing are two different processes. Unlike encryption, hash cannot be decrypted; it is one-way. At the same time, two different strings may produce the same hash value, so the uniqueness of the hash value cannot be guaranteed.
Hash values processed by the MD5 function are basically impossible to crack, but there is always a possibility, and there are MD5 hash dictionaries available online.
Using mcrypt to Encrypt Data
The MD5 hash function can display data in a readable form, but when storing users' credit card information, it needs to be encrypted and stored, and it needs to be decrypted later.
The best method is to use the mcrypt module, which contains more than 30 encryption methods to ensure that only the encryptor can decrypt the data.
<?php
$data = "Stuff you want encrypted";
$key = "Secret passphrase used to encrypt your data";
$cipher = "MCRYPT_SERPENT_256";
$mode = "MCRYPT_MODE_CBC";
function encrypt($data, $key, $cipher, $mode) {
// Encrypt data
return (string)
base64_encode
(
mcrypt_encrypt
(
$cipher,
substr(md5($key),0,mcrypt_get_key_size($cipher, $mode)),
$data,
$mode,
substr(md5($key),0,mcrypt_get_block_size($cipher, $mode))
)
);
}
function decrypt($data, $key, $cipher, $mode) {
// Decrypt data
return (string)
mcrypt_decrypt
(
$cipher,
substr(md5($key),0,mcrypt_get_key_size($cipher, $mode)),
base64_decode($data),
$mode,
substr(md5($key),0,mcrypt_get_block_size($cipher, $mode))
);
}
?>
The mcrypt function requires the following information:
1. The data to be encrypted
2. The key used to encrypt and decrypt the data
3. The specific algorithm (cipher) chosen by the user for encrypting data, such asMCRYPT_TWOFISH192,MCRYPT_SERPENT_256, MCRYPT_RC2, MCRYPT_DES, and MCRYPT_LOKI97)
4. The mode used for encryption
5. The encryption seed, the data used to start the encryption process, is an additional binary data used to initialize the encryption algorithm.
6. The lengths of the encryption key and seed can be obtained using the mcrypt_get_key_size function and the mcrypt_get_block_size function.
If both the data and the key are stolen, the attacker can iterate through ciphers to find a way to decrypt. Therefore, we need to apply MD5 to the encryption key once to ensure security. Also, since the encrypted data returned by the mcrypt function is binary data, saving it directly to a database field may cause other errors, so base64encode is used to convert this data into a hexadecimal number for convenient storage.
References: http://www.codeproject.com/Articles/363897/PHP-Security
Article source: http://blog.csdn.net/u010487568/article/details/29828757