One, CGI mode installation security
Second, the Apache module to install security
When PHP is installed as an Apache module, it inherits the privileges of the Apache user (usually "nobody"). This has some impact on security and authentication. For example, if you use PHP to access a database, unless the database has its own access control, you should enable "nobody" users to access the database. This means that malicious scripts may access and modify the database without providing a username and password. A web Spider is also entirely likely to stumble across the management page of the database and delete all databases. You can avoid this problem with Apache authentication, or design your own anti-questioning model with LDAP,. htaccess, and use this code as part of your PHP script
A common mistake for security is to have Apache have root privileges, or to use other channels to give Apache more powerful functionality.
Raising the rights of Apache users to root is an extremely risky practice and can compromise the security of the entire system. So you should never consider using Su,chroot or running as root, unless you are a security professional.
In addition, there are some simple solutions. For example, you can use Open_basedir to restrict which directories can be used by PHP. You can also set the exclusive area of Apache to restrict all web activity to non-user and non-system files.
Third, file system security
PHP complies with the security mechanisms in most server systems regarding file and directory permissions. This allows administrators to control which files are readable within the file system. Special attention must be paid to the global readable file and to ensure that every user with permission to read these files is safe.
PHP is designed to access the file system at the user level, so it is entirely possible to write a section of PHP code to read system files such as/etc/passwd, change network connections, and send a large number of print tasks, and so on. Therefore, you must ensure that the PHP code reads and writes the appropriate files.
Two important measures to prevent such problems.
# only limited permissions are given to PHP's web users.
# Check all the submitted variables.
$username = $_server[' Remote_user ']; Use authentication mechanism
$userfile = $_post[' User_submitted_filename '];
$homedir = "/home/$username";
$filepath = "$homedir/$userfile";
if (!ctype_alnum ($username) | | |!preg_match ('/^ (?: [A-z0-9_-]|\. \.)) +$/id ', $userfile)) {
die ("Bad username/filename");
}
* NULL character problem
Because the file system operation of PHP is based on the C language function, it may handle Null characters in unexpected ways. A null character is used in C to identify the end of a string, and a complete string is from its beginning until it meets a Null character.
# code that will be attacked by a Null character problem:
$file = $_get[' file ']; "Http://www.cnblogs.com/etc/passwd\0"
if (file_exists ('/home/wwwrun/'. $file.) php ')) {
//File_exists'll return True as the FILE/HOME/WWWRUN/HTTP://WWW.CNBLOGS.COM/ETC/PASSWD exists
Include '/home/wwwrun/'. $file. '. PHP ';
The FILE/ETC/PASSWD would be included
}
# Validate input for correct practices
$file = $_get[' file '];
White list Check for strings
switch ($file) {case '
main ': Case
' foo ': Case
' bar ':
include '/home/wwwrun/ include/'. $file. PHP ';
break;
Default:
include '/home/wwwrun/include/main.php ';
}
Iv. Database Security
* Design Database
The first step is generally to create a database, unless you are using a Third-party database service. When a database is created, an owner is assigned to execute and create a new statement. In general, only the owner (or superuser) has permission to manipulate objects in the database arbitrarily. If you want to make it available to other users, you must give them permission.
Applications should never use the database owner or Superuser account to connect to the database because they can perform arbitrary actions, such as modifying the database structure (such as deleting a table) or emptying the contents of the entire database.
You should create different database accounts for each aspect of your program and give you very limited permissions on database objects. Assign only the permissions that are required to complete its function, and avoid the same user being able to accomplish another user's business. This way, even if an attacker exploits a program vulnerability to gain access to the database, it can only be as affected as the program.
Users are encouraged not to use all of the transaction logic in a Web application (that is, a user's script). It is best to use views, triggers (trigger), or rules (rule) to complete at the database level. When the system upgrades, need to open a new interface for the database, then must redo all the database client. In addition, triggers can transparently and automatically process fields and provide useful information when debugging programs and tracking facts.
* Connect to the database
Establishing a connection on SSL encryption can increase the security of client and server-side communication, or SSH can also be used to encrypt the connection between the client and the database. If these techniques are used, it is difficult for an attacker to monitor the server's communications or get information about the database.
* Encrypted storage model
Ssl/ssh can protect data exchanged between client and server, but Ssl/ssh does not protect the data already in the database. SSL is just a protocol that encrypts network data streams.
If an attacker obtains permission to access the database directly (bypassing the Web server), sensitive data may be exposed or misused unless the database itself protects the information. Encrypting data within a database is an effective way to reduce this type of risk, but only a few databases provide these encryption capabilities.
A simple solution to this problem is to create your own encryption mechanism and then use it in a PHP program. PHP has several extension libraries to do this, such as Mcrypt and Mhash, which contain a variety of cryptographic algorithms. The script encrypts the data before it is inserted into the database and then decrypts it later when it is extracted.
For some really hidden data, if you do not need to exist in the form of plaintext (that is, do not display), you can consider hashing algorithm. The most common example of using a hashing algorithm is to place the password in a MD5 encrypted hash into the database instead of the original plaintext password. See Crypt () and MD5 ().
* SQL injection
Many web developers do not notice that SQL queries can be tampered with, thus making SQL queries a trustworthy command. SQL queries can bypass access control, bypassing authentication and permission checking. What's more, it is possible to run host operating system-level commands through SQL queries.
Direct SQL command injection is a technique commonly used by attackers to create or modify existing SQL statements to achieve hidden data, or to overwrite critical values, or even to execute database host operating system commands. This is accomplished by using the application to obtain user input and combining static parameters into SQL queries. Some real examples will be given below.
An attacker could create a new superuser in the database because of the lack of validation of the input data and the use of a superuser or other database account that has the right to create a new user.
Example #1 A piece of code that implements data paging ... It can also be used to create a super User (PostgreSQL system).
<?php
$offset = $argv [0];//note, no input validation!
$query = "SELECT ID, name from [Order by name LIMIT OFFSET $offset;";
$result = Pg_query ($conn, $query);
>
The average user clicks on the "Back Page" and "next page" link of the bin value $offset. The original code would only think that $offset is a numeric value. However, if someone tries to process the following statement first by UrlEncode () and then adding the URL:
0;
Insert into Pg_shadow (USENAME,USESYSID,USESUPER,USECATUPD,PASSWD)
Select ' Crack ', usesysid, ' t ', ' t ', ' crack '
From Pg_shadow where usename= ' postgres ';
--Then he can create a super user. Notice that 0, just to provide a correct offset to complement the original query so that it doesn't go wrong.
Note:
--is a SQL annotation tag that can be used to tell the SQL interpreter to ignore the following statements.
A possible way to get a password is to start a page that displays search results. The only thing an attacker would have to do was to find out which of the submitted variables were used for SQL statements and mishandled them. Variables of this type are usually used for conditional statements in a select query, such as where, order by, LIMIT, and OFFSET. If the database supports the union construct, an attacker might also attach a complete SQL query to the original statement to get the password from any data table. Therefore, it is important to encrypt the password field.
Example #2 Show Articles ... and some passwords (any database system)
Copy Code code as follows:
<?php
$query = "SELECT ID, name, inserted, size from products
WHERE size = ' $size '
ORDER by $order LIMIT $limit, $offset; ";
$result = Odbc_exec ($conn, $query);
?>
You can add another select query based on the original query to get the password:
'
Union select ' 1 ', concat (uname| | ') -'|| passwd) as name, ' 1971-01-01 ', ' 0 ' from usertable;
If the above statement (using ' and--) is added to any variable in the $query, then it is troublesome.
UPDATE in SQL can also be attacked. This query may also be inserted or appended to another complete request as the example above. But attackers are more likely to start with set clauses, so they can change some data in the datasheet. In this case, you must know the structure of the database in order to modify the query successfully. You can guess the field by the variable name on the form or brute force. There are not many named methods for fields that hold user names and passwords.
Example #3 Reset Password from ... To get more permissions (any database system)
Copy Code code as follows:
<?php
$query = "UPDATE usertable SET pwd= ' $pwd ' WHERE uid= ' $uid ';";
?>
But a malicious user would put ' or uid like '%admin% '; --The value of the variable is submitted to the $uid to change the password of the admin, or the $PWD value is submitted as "Hehehe ', admin= ' yes ', trusted=100" (followed by a space) to obtain more permissions. By doing so, the query statement actually becomes:
Copy Code code as follows:
<?php
$uid = = ' or uid like '%admin% '; --
$query = "UPDATE usertable SET pwd= ' ... ' WHERE uid= ' or uid like '%admin% '; --";
$pwd = = "Hehehe ', admin= ' yes ', trusted=100"
$query = "UPDATE usertable SET pwd= ' hehehe ', admin= ' yes ', trusted=100 WHERE
...;";
?>
The following gruesome example will show how to execute system commands on some databases.
Example #4 Attack the operating system of the host on which the database resides (MSSQL Server)
Copy Code code as follows:
<?php
$query = "SELECT * from the products WHERE id like '% $prod% '";
$result = Mssql_query ($query);
?>
If the attack is submitted a% ' exec master. xp_cmdshell ' net user Test Testpass/add '-the value $prod as a variable, then $query will become
Copy Code code as follows:
<?php
$query = "SELECT * FROM Products
WHERE id like '%a% '
EXEC master.. xp_cmdshell ' net user Test Testpass/add '-';
$result = Mssql_query ($query);
?>
The MSSQL server executes this SQL statement, including the command that is used to add users to the system. If the program is run with SA and the MSSQLServer service has sufficient privileges, the attacker can obtain a system account to access the host.
Note:
Although the above examples are for a particular database system, this does not mean that you cannot perform similar attacks on other database systems. Using different methods, all kinds of databases are likely to suffer.
Preventive measures
Perhaps some would comfort themselves by saying that the attacker would have to know the structure of the database to implement the attack. Yes, indeed. But no one can guarantee that the attackers will not be able to get the information, but they get the risk that the database will be compromised. If you are using an Open-source package to access a database, such as a forum program, the attacker would be very tolerant of the relevant code. If the code is poorly designed, the risk is even greater.
These attacks are always based on the discovery of code that is not strong in security sense. Therefore, never trust data entered by the outside world, especially from clients, including selection boxes, form hiding fields, and cookies. As the first example above, even a normal query can cause disaster.
• Never use a superuser or owner account to connect to a database. The account to be strictly restricted with permissions.
• Check that the data entered has the desired data format. PHP has a number of functions that can be used to check input, from simple variable functions and character type functions (such as is_numeric (), Ctype_digit ()) to complex Perl-compatible regular expression functions to do this work.
• If the program waits to enter a number, consider using Is_numeric () to check it, or use Settype () directly to convert its type, or use sprintf () to format it as a number.
Example #5 A more secure way to achieve pagination
Copy Code code as follows:
<?php
Settype ($offset, ' Integer ');
$query = "SELECT ID, name from [Order by name LIMIT OFFSET $offset;";
Note that%d in the format string is meaningless if you use%s
$query = sprintf ("Select ID, name from [] LIMIT OFFSET%d;",
$offset);
?>
• Use database-specific sensitive word escape functions (such as mysql_escape_string () and sql_escape_string ()) to escape User submissions for Non-numeric data. Addslashes () and Str_replace () can replace the completion of this work if the database does not have a dedicated, sensitive character escape function. Take a look at the first example, which shows that it is not enough to enclose the static part of the query, and that the query is easily compromised.
• Do whatever it takes to avoid displaying any confidence in the database, especially the database structure. See Error reporting and error handling functions.
• You can also choose to abstract several library accesses using attributes such as database stored procedures and predefined pointers, so that users cannot directly access data tables and views. But this approach has other implications.
In addition, it is also a good idea to use code or database systems to save query logs, if allowed. Obviously, the log does not prevent any attack, but it can be used to track which program has been tried to attack before. The log itself is useless, and you need to review the information contained therein. After all, more information is better than nothing.
V. Error Reporting
Error reporting is a double-edged sword for PHP security. On the one hand can improve security, on the other hand harmful.
The trick that is often used when attacking a system is to enter incorrect data, and then look at the type and context of the error message. This helps the attacker to gather information about the server in order to find vulnerabilities. For example, if an attacker knew the form information that a page was based on, he would try to modify the variable:
Example #1 attack variables with a custom HTML page
Copy Code code as follows:
<form method= "POST" action= "Attacktarget?username=badfoo&password=badfoo" >
<input type= "hidden" name= "username" value= "Badfoo"/>
<input type= "hidden" name= "password" value= "Badfoo"/>
</form>
Usually the error prompts that PHP returns can help the developer debug the program, it will ask which function or code of the file is wrong, and indicate the error occurred in the first few lines of the file, which is the information that PHP itself can give. Many PHP developers use the Show_source (), highlight_string (), or highlight_file () functions to debug the code, but in a properly run Web site, this practice may expose hidden variables, Unchecked syntax and other information that could compromise the security of the system. It is dangerous to run some programs that have internal debugging processing, or to use common debugging techniques. If the attacker determines which specific debugging technique the program is using, they try to send a variable to turn on the debugging feature:
Example #2 use variable to open the Mode function
Copy Code code as follows:
<form method= "POST" action= "Attacktarget?errors=y&showerrors=1&debug=1" >
<input type= "hidden" name= "errors" value= "Y"/>
<input type= "hidden" name= "ShowErrors" value= "1"/>
<input type= "hidden" name= "Debug" value= "1"/>
</form>
Regardless of the error-handling mechanism, the ability to detect system errors can provide more information to attackers.
For example, PHP's unique error hint style can indicate that the system is running PHP. If an attacker is looking for a. html as a page, and wants to know the technology behind it (in order to find a system weakness), they will submit the wrong data and then have the knowledge that the system is based on PHP.
A function error can expose a database that the system is using, or provide an attacker with useful information about a Web page, program, or design. Attackers tend to track down open database ports and some bugs or vulnerabilities on the page. For example, an attacker could cause a program to fail with some abnormal data to detect the sequence of authentication in the script (by the number of line numbers by error) and the information that might be leaked elsewhere in the script.
A file system or PHP error exposes what permissions the Web server has and how the file is organized on the server. The error code written by the developer will exacerbate the problem, resulting in the disclosure of information that was originally hidden.
There are three common ways to deal with these problems. The first is to thoroughly check all functions and try to make up for most errors. The second is to completely turn off error reporting on the online system. The third is to create your own error-handling mechanism using PHP's custom error-handling functions. Depending on the security policy, three methods may apply.
One way to prevent this problem in advance is to use error_reporting () to help make the code more secure and to discover the dangers of variable use. Before you release the program, open the E_all test code, which will help you quickly find out where the variable is not being used. Once the official release is ready, the error_reporting () parameter should be set to 0来 completely shut down the error report or the display_errors in php.ini to turn off all error displays to isolate the code from the probe. Of course, if you want to do this later, don't forget to open the log_errors option in the INI file and specify the file to log the error message through Error_log.
Example #3 use E_all to find dangerous variables.
Copy Code code as follows:
<?php
if ($username) {//not initialized or checked before usage
$good _login = 1;
}
if ($good _login = = 1) {//If above test fails, not initialized or checked before
ReadFile ("/highly/sensitive/data/index.html");
}
?>
Vi. Use of Register Globals
Perhaps the most controversial change in PHP is that the default value for Register_globals from the php»4.2.0 version of the configuration file is changed from on to off. The dependency on this option is so pervasive that many people simply don't know it exists and think that PHP is the way it works. This section will explain how to write unsafe code with this instruction, but know that the instruction itself is not unsafe and will be misused.
When Register_globals is opened, various variables are injected into the code, such as request variables from the HTML form. Plus, PHP doesn't need to initialize before using variables, which makes it easier to write unsafe code. It was a tough decision, but the PHP community decided to turn this option off by default. When open, people do not know where the variable comes from when they use the variable, only take it for granted. But the shutdown of register_globals changed the bad case that the code internal variables were mixed with the variables sent by the client. Here's an example of using register_globals incorrectly:
Example #1 error using Register_globals = on example
Copy Code code as follows:
<?php
Assignment $authorized = True when the user is legitimate
if (Authenticated_user ()) {
$authorized = true;
}
Since the $authorized was not initialized to false in advance,
When Register_globals is open, the value of the variable may be defined by a get auth.php?authorized=1
So anyone can bypass the authentication
if ($authorized) {
Include "/highly/sensitive/data.php";
}
?>
When register_globals = ON, the code above can be dangerous. If off, the $authorized cannot be changed by such means as URL requests, which is much better, although initializing variables is a good programming habit. For example, if you add $authorized = False before the above code executes, whether Register_globals is on or off, because the user state is initialized to unauthenticated.
Another example is about the session. When register_globals = ON, $username can also be used in the following code, but be aware that $username may also come in from other sources, such as through the URL of get.
Example #2 Example of compatible register_globals on and off while using a session
Copy Code code as follows:
<?php
We don't know the source of $username, but it's clear $_session is
From session data
if (isset ($_session[' username ')) {
echo "Hello <b>{$_session[' username ']}</b>";
} else {
echo "Hello <b>guest</b><br/>";
echo "Would" to login?
}
?>
It is entirely possible to take appropriate precautions to give warning when forging variable inputs. If you know exactly where the variable comes from, you can check that the submitted data is submitted from an improper form. However, this does not guarantee that the variable is not forged, which requires an attacker to guess how to forge it. If you don't care about the request data source, you can use the $_request array, which includes all the data for Get, POST, and cookies. For more information, see variables from outside of PHP in this manual.
Example #3 Detect Harmful variables
Copy Code code as follows:
<?php
if (Isset ($_cookie[' Magic_cookie ')) {
Magic_cookie from Cookies
This is to make sure that the data from the cookie
} elseif (Isset ($_get[' Magic_cookie ')) | | isset ($_post[' Magic_cookie '])) {
Mail ("admin@example.com", "Possible breakin attempt", $_server[' remote_addr ']);
echo "Security violation, admin has been alerted."
Exit
} else {
The Magic_cookie variable is not set in this request
}
?>
Of course, simply shutting down register_globals does not mean that all code is safe. For each piece of data submitted, you have to do a specific check. Always validate user data and initialize variables! Set the error_reporting () to the E_notice level to check for uninitialized variables.
For more information about simulating register_globals on or off, see this FAQ.
Note:superglobal Availability Description:
You can use Superglobal arrays from PHP 4.1.0, such as $_get,$_post, and $_server, and so on. For more information, read the Superglobals section in the manual.
Vii. data submitted by users
Many PHP programs have a major weakness is not the problem of PHP language itself, but the programmer's security awareness is not high. Therefore, you must always pay attention to the possible problems of each piece of code to discover the possible impact of incorrect data submission.
Example #1 Dangerous variable usage
Copy Code code as follows:
<?php
Delete a file from the user directory, or ... Can delete more things?
Unlink ($evil _var);
Log the user's login, or ... Can I add data to/etc/passwd?
Fwrite ($fp, $evil _var);
Execute some ordinary commands, or ... Can execute RM-RF *?
System ($evil _var);
EXEC ($evil _var);
?>
You must always be aware of your code to ensure that every variable submitted from the client is properly checked, and then ask yourself the following questions:
• Does this script affect only the files that you expect?
• Can the abnormal data be brought into effect after being submitted?
• Can this script be used for unplanned purposes?
• Can this script be combined with other scripts to do bad things?
• Are all the transactions fully documented?
Ask yourself these questions while writing the code, or you might want to rewrite the code for added security later. If you pay attention to these problems, you may not be able to guarantee the security of the system, but at least it will improve security.
You can also consider turning off register_globals,magic_quotes or other settings that make programming easier but will cause the legality, source, and value of a variable to be messed up. At development time, you can use the error_reporting (E_all) pattern to help check whether a variable is checked or initialized before it is used, which prevents some abnormal data from being scratched.
Eight, Magic quotes
* Magic Quotes
When opened, all ' (single quotes), "(double quotes), \ (backslash), and NULL characters are automatically escaped with a backslash. This is exactly the same as the addslashes () function.
A total of three magic quote instructions:
MAGIC_QUOTES_GPC affects HTTP request data (Get,post and cookies). Cannot be changed at run time. In PHP, the default value is on. See GET_MAGIC_QUOTES_GPC ().
Magic_quotes_runtime if opened, most of the data returned from external sources, including from the database and text files, will be escaped by backslashes. This option can be changed at run time, and the default value in PHP is off. See Set_magic_quotes_runtime () and Get_magic_quotes_runtime ().
Magic_quotes_sybase if opened, the single quotation marks are used to escape instead of the backslash. This option will completely overwrite MAGIC_QUOTES_GPC. If you open two options at the same time, the single quote will be escaped as '. Double quotes, backslashes, and NULL characters are not escaped. How to get its value see Ini_get ().
* The role of Magic quotes
Advantages:
Useful for beginners magic quotes are used in PHP to avoid more dangerous code for beginners. Although SQL injection is still possible with magic quotes open, at least the risk of the system is reduced by a lot.
Easy to use when inserting data into a database, what magic quotes do is automatically apply the Addslashes () function to all get, POST, and COOKIE data
Disadvantages:
Portability is considered to be open or closed when porting programming. You can use GET_MAGIC_QUOTES_GPC () to check whether it is open and program accordingly.
Performance because not every segment of the escaped data to be inserted into the database, if all the data into PHP is escaped, then the execution efficiency of the program will have a certain impact. It is more efficient to invoke escape functions (such as addslashes ()) at run time. Although Php.ini-dist opens this option by default, php.ini-recommended closes it by default, mainly for performance reasons.
Inconvenience because not all data needs to be escaped, it is annoying to see escaped data where there is no need to escape. For example, send mail through the form, and see a lot of \ '. For this problem, you can use the Stripslashes () function to handle
* Close Magic Quotes
The MAGIC_QUOTES_GPC instruction can only be shut down at the system level, not at run time. That means you can't use Ini_set ().
Example #1 Turn off Magic quotes on the server side
The following is an example of setting these options to off via the php.ini file. For more information, see How to modify configuration settings in this manual.
; Magic Quotes
;
; Magic quotes for incoming Get/post/cookie data.
MAGIC_QUOTES_GPC = Off
; Magic quotes for runtime-generated data, e.g. data to SQL, from exec (), etc.
Magic_quotes_runtime = Off
; Use Sybase-style Magic quotes (escape ' with ' instead of \ ').
Magic_quotes_sybase = Off
If you cannot modify the server-side configuration file, you can use. htaccess. Examples are as follows:
Php_flag MAGIC_QUOTES_GPC off
In order to write code that is highly portable (which can run in any environment), such as inability to modify the server configuration, the following example can turn off MAGIC_QUOTES_GPC at run time. But this is relatively inefficient, the appropriate modification of the configuration is a better way.
Example #2 turn off magic quotes at run time
Copy Code code as follows:
<?php
if (GET_MAGIC_QUOTES_GPC ()) {
function Stripslashes_deep ($value)
{
$value = Is_array ($value)?
Array_map (' Stripslashes_deep ', $value):
Stripslashes ($value);
return $value;
}
$_post = Array_map (' Stripslashes_deep ', $_post);
$_get = Array_map (' Stripslashes_deep ', $_get);
$_cookie = Array_map (' Stripslashes_deep ', $_cookie);
$_request = Array_map (' Stripslashes_deep ', $_request);
}
?>
Nine, Hide PHP
In general, improving security by means of concealment is considered a less useful practice. But in some cases, it is worthwhile to add as much security as possible.
Some simple ways to help hide PHP can make it more difficult for attackers to discover system vulnerabilities. Setting expose_php = off in the php.ini file can reduce the useful information they can get.
Another strategy is to have the Web server parse different extensions in PHP. Either through the. htaccess file or the Apache configuration file, you can set a file extension that can mislead an attacker:
Example #1 to hide PHP as another language
# make PHP look like any other programming language
AddType application/x-httpd-php. asp. py. pl or simply completely hide it:
Example #2 Use an unknown extension as the extension of PHP
# make PHP look like an unknown file type
AddType application/x-httpd-php. Bop foo. 133t or hide it as an HTML page, so that all HTML files will go through the PHP engine, adding some burden to the server:
Example #3 use HTML to make PHP file suffixes
# make PHP code look like an HTML page
AddType application/x-httpd-php. htm. html to make this method effective, you must change the extension of the PHP file to the extension above. This improves security by hiding, albeit with low defense and some drawbacks.
Ten, keep the update
PHP, like other large systems, is in constant research and improvement. Each version will have more or less improvements to enhance security and fix any bugs, configuration problems, and any problems that can affect the security and performance of the entire system.
As with other system-level scripting languages, the best approach is to update regularly and keep an eye on the latest version and its changes