Go: How to prevent SQL injection in PHP

Source: Internet
Author: User
Tags file handling how to prevent sql injection html tags pear phpinfo sql injection apache log web hosting

"One, server-side Configuration"

Security, PHP code writing is on the one hand, PHP configuration is very critical.

We PHP hand-installed, PHP default configuration file in/usr/local/apache2/conf/php.ini, we mostly want to configure the content in PHP.ini, let us execute PHP can be more secure. The security settings throughout PHP are primarily designed to prevent Phpshell and SQL injection attacks, and we'll explore them slowly. We will first use any editing tools to open the/etc/local/apache2/conf/php.ini, if you are installed in another way, the configuration file may not be in this directory.

(1) Open PHP Safe mode

PHP's security model is a very important embedded security mechanism to control some functions in PHP, such as System (),

At the same time, a lot of file operation functions have permission control, also does not allow the files for some key files, such as/etc/passwd,

But the default php.ini is not open in Safe mode, we turn it on:

Safe_mode = On

(2) User group security

When Safe_mode is turned on, Safe_mode_gid is turned off, and the PHP script is able to access the file, and the same

Users of the group are also able to access the files.

The recommended setting is:

Safe_mode_gid = Off

If we do not set up, we may not be able to operate the files in our server web directory, for example, we need to

When you are working on a file.

(3) Execute Program home directory in Safe mode

If Safe mode is turned on, but you want to execute some programs, you can specify the home directory where you want to execute the program:

Safe_mode_exec_dir = D:/usr/bin

In general, do not need to execute what program, so it is recommended not to execute the System program directory, can point to a directory,

Then copy the program that needs to be executed, such as:

Safe_mode_exec_dir = D:/tmp/cmd

However, I recommend that you do not execute any programs, then you can point to our web directory:

Safe_mode_exec_dir = d:/usr/www

(4) Include files in Safe mode

If you want to include some common files in Safe mode, then modify the options:

Safe_mode_include_dir = d:/usr/www/include/

In fact, the general PHP script contains files are in the program itself has been written, this can be set according to the specific needs.

(5) control the directory that PHP scripts can access

Use the OPEN_BASEDIR option to control the PHP script to access only the specified directory, which avoids the PHP script access

The files that should not be accessed to some extent limit the harm of phpshell, we can generally be set to only access the site directory:

Open_basedir = d:/usr/www

(6) Close danger function

If Safe mode is turned on, then the function prohibition is not necessary, but we consider it to be safe. Like what

We don't want to execute PHP functions that include the system (), or the ability to execute commands, or the ability to view PHP information

Phpinfo () and so on, then we can disable them:

Disable_functions = System,passthru,exec,shell_exec,popen,phpinfo

If you want to disable the operation of any files and directories, you can close many file operations

Disable_functions = Chdir,chroot,dir,getcwd,opendir,readdir,scandir,fopen,unlink,delete,copy,mkdir, Rmdir,rename, File,file_get_contents,fputs,fwrite,chgrp,chmod,chown

These are just a few of the most commonly used file handling functions, and you can also combine the above command functions with this function,

will be able to resist most of the Phpshell.

(7) Close the PHP version information in the HTTP header leak

In order to prevent hackers from getting the PHP version of the server information, you can close the information ramp in the HTTP header:

expose_php = Off

For example, when the hacker in Telnet www.12345.com 80, then will not see the PHP information.

(8) Close registered global variables

Variables submitted in PHP, including those that use post or get commits, are automatically registered as global variables and can be accessed directly,

This is very insecure for the server, so we can't register it as a global variable, and turn off the Register global variables option:

Register_globals = Off

Of course, if this is set, then the corresponding variable should be taken in a reasonable way, such as get the variable var of get commit,

Then you need to use $_get[' var ' to get it, this PHP programmer should pay attention to.

(9) Open MAGIC_QUOTES_GPC to prevent SQL injection

SQL injection is a very dangerous problem, small site background was invaded, heavy the entire server fell,

So be sure to be careful. There is a setting in php.ini:


This is off by default, and if it is turned on, it will automatically convert the query that the user commits to SQL.

For example, "switch to \" And so on, which is important to prevent SQL injection. So we recommend setting it to:


(10) Error Message control

In general, PHP is not connected to the database or in other cases there will be a prompt error, the general error message will contain PHP script when

Before the path information or query SQL statements and other information, such information provided to the hacker is not secure, so the general server recommends that you suppress the error prompt:

Display_errors = Off

If you are trying to display an error message, be sure to set the level of display errors, such as displaying only the information above the warning:

error_reporting = e_warning & E_error

Of course, I recommend turning off the error prompt.

(11) Error log

It is recommended to log the error message after closing the display_errors to find out why the server is running:

Log_errors = On

Also set the directory where the error log is stored, suggesting that the root Apache log exists together:

Error_log = D:/usr/local/apache2/logs/php_error.log

Note: The to file must allow Apache users and groups to have write permissions.

MySQL's Down right run

Create a new user such as Mysqlstart

NET user Mysqlstart Fuckmicrosoft/add

net localgroup users Mysqlstart/del

Does not belong to any group

If MySQL is installed in D:\mysql, then give Mysqlstart Full control of the permissions

Then set in the system service, MySQL service properties, in the login properties, select this user Mysqlstart and then enter the password, OK.

Restart the MySQL service, and then MySQL runs under low authority.

If the Apache is built under the WinDOS platform, we also need to note that Apache default operation is the system permission,

It's horrible, and it makes you feel uncomfortable. Let's give Apache permission to drop it.

NET user Apache Fuckmicrosoft/add

net localgroup users Apache/del

Ok. We have created a user apche that does not belong to any group.

We open the Computer Manager, select the service, point to the properties of the Apache service, we select Log on, choose this account, we fill in the accounts and passwords established above,

Restart the Apache service, Ok,apache running under low authority.

In fact, we can also set individual folder permissions, so that Apache users can only do what we want it to do, to each directory to create a separate read and write users.

This is also a popular configuration method for many current web hosting providers, but this method is used to prevent a bit of overkill here.

"Two, write in PHP code"

        Although many PHP programmers in the country still rely on addslashes to prevent SQL injection, it is recommended to strengthen Chinese to prevent SQL injection check. The problem with addslashes is that hackers can use 0xbf27 instead of single quotes, and addslashes just modifies 0xbf27 to 0xbf5c27 as a valid multibyte character, where 0xbf5c is still considered a single quote, So addslashes can't intercept successfully.
        Of course addslashes is not useless, it is used for single-byte string processing, multibyte characters or mysql_real_escape_ String Bar.
        Another example of GET_MAGIC_QUOTES_GPC in the PHP Manual:
$lastname = addslashes ($_post[' LastName '));
} else {
$lastname = $_post[' LastName ');

It is best to check the $_post[' LastName ' If the MAGIC_QUOTES_GPC is already open.
Again, the difference between the 2 functions of mysql_real_escape_string and mysql_escape_string:
Mysql_real_escape_string must be used in cases (PHP 4 >= 4.3.0, PHP 5). Otherwise only with mysql_escape_string, the difference between the two is: Mysql_real_escape_string considering the connected
The current character set, while Mysql_escape_string is not considered.
To summarize:
* Addslashes () is forcibly added \;
* Mysql_real_escape_string () will determine the character set, but the PHP version is required;
* Mysql_escape_string does not consider the current character set of the connection.
In PHP code, if you consider some of the more basic security issues, first of all:
1. Initialize your variables
Why do you say that? Let's look at the following code:
PHP code

<?php         if ($admin)         {         echo ' Landing succeeded! ';         Include (' admin.php ');         }         else         {         echo ' you are not an administrator and cannot be managed! ';         }         ? >

      Well, we look at the code above as if it's working, no problem, then join me to commit an illegal argument in the past, so what will the effect be? For example, this page of ours is http://daybook.diandian.com/login.php, then we submit: Http://daybook.diandian.com/login.php?admin=1, hehe, you want some, We are directly the administrator, direct management.
      Of course, we may not make such a simple mistake, then some very secret errors can lead to this problem, such as the Phpwind forum has a loophole, resulting in the ability to directly get administrator rights, because there is a $ The skin variable is not initialized, resulting in a series of subsequent problems. So how do we avoid the above problem? First of all, from the php.ini, php.ini inside the Register_global =off, is not all the registered variables for the global, then you can avoid. However, we are not a server administrator, only improved from the code, then how can we improve the above code? We rewrite the following:
PHP code       

  <?php         $admin = 0;//Initialize variable         if ($_post[' Admin_user ') && $_post[' Admin_pass '])         {         // Determine if the submitted admin username and password are correct for the corresponding processing code         //...         $admin = 1;         }         else         {         $admin = 0;         }         if ($admin)         {         echo ' landed successfully! ';         Include (' admin.php ');         }         else         {         echo ' you are not an administrator and cannot be managed! ';         }         ? >

     Then it's not good for you to commit http://daybook.diandian.com/login.php?admin=1 at this time, because we initially initialized the variable to $ admin = 0, then you will not be able to get administrator privileges through this vulnerability.
2. Prevent SQL injection (SQL injection)
    sql injection should be the most harmful to the current program, including the earliest from ASP to PHP, is basically the domestic two years of popular technology, The rationale is to inject points by not filtering the commit variable and then enable a malicious user to submit some SQL query statements, leading to the theft of important data, loss or corruption of data, or intrusion into the background management.
     So now that we know the basic way of injecting intrusion, how do we prevent it? This should be our code to start with.
    We know there are two ways to submit data on the Web, one is get, one is post, so many common SQL injections start with GET, and the injected statement must contain some SQL statements, Because there is no SQL statement, then how to proceed, the SQL statement has four main sentences: Select, update, delete, insert, then we can avoid these problems if we filter in the data we submit? The
then we use the regular to build the following function:
PHP code

   <?php              function Inject_check ($sql _str)         {         return eregi (' select|insert|update|delete| ' |         function verify_id ($id =null)         {         if (! $id) {exit (' no submit parameter!) ‘); }//Is null-judged         ElseIf (Inject_check ($id)) {exit (' The argument submitted is illegal! ‘); }//Injection judgment         ElseIf (!is_numeric ($id)) {exit (' The argument submitted is illegal! ‘); }//Digital judgment         $id = Intval ($id);//integer             return $id;         }         ? >

Well, then we will be able to verify, so our above program code becomes the following:
PHP code

<?php         if (Inject_check ($_get[' id '))         {         exit (' The data you submitted is illegal, please check and resubmit! ');         }         else         {         $id = verify_id ($_get[' id ');//Here we filter the function, the $id filter         Echo ' submitted data is valid, please continue! ';         }         ? >

OK, the problem seems to have been solved here, but we have not considered the post-submitted data, large quantities of data?
For example, some characters may be harmful to the database, such as ' _ ', '% ', these characters have special meaning, then if we control it? Another point is that when our php.ini inside the MAGIC_QUOTES_GPC = off, then the data submitted by the database does not conform to the rules are not automatically added to the front, then we have to control these problems, and then build the following function:
PHP code

  <?php            function Str_check ($str)         {         if (!GET_MAGIC_QUOTES_GPC ())//Determine if MAGIC_QUOTES_GPC open         {         $ str = addslashes ($STR); Filter         }         $str = Str_replace ("_", "\_", $str),//filter out ' _ '         $str = str_replace ("%", "\%", $str);//Remove '% ' to filter out 
   return $str;         }         ? >

Once again, we avoided the danger of the server being overrun.
Finally, consider submitting some large quantities of data, such as posts, or writing articles, news, we need some functions to help us filter and transform, and then on the basis of the above function, we construct the following function:
PHP code

<?php          function Post_check ($post)         {         if (!GET_MAGIC_QUOTES_GPC ())//Determine if MAGIC_QUOTES_GPC is open         {         $post = addslashes ($post);//MAGIC_QUOTES_GPC No open conditions for the submission of data filtering         }         $post = Str_replace ("_", "\_", $post); Filter out the ' _ '         $post = str_replace ("%", "\%", $post),//remove '% '         $post = NL2BR ($post);//Enter conversion         $post = Htmlspeci Alchars ($post); HTML tags convert            return $post;         }         ? >

Oh, basic to here, we have said some of the situation, in fact, I feel that I speak very little, at least I only speak two aspects, and then the whole security is very little content, consider the next time to speak more, including PHP security Configuration, Apache security and so on, so that our security is a whole, To be the safest.
In the end, I'm telling you the above expression: 1. Initialize your variable 2. You must remember to filter your variables.

One is not filtering the input data (filtering the input), and one is not escaping the data sent to the database (escaped output). These two important steps are indispensable and require special attention at the same time to reduce procedural errors.
For attackers, SQL injection attacks need to be considered and tested, and it is necessary to substantiated the database schema (assuming that the attacker does not see your source program and database schema), consider the following simple login form:

Copy CodeThe code is as follows:
<form action= "/login.php" method= "POST" >
<p>username: <input type= "text" name= "Username"/></p>
<p>password: <input type= "Password" name= "Password"/></p>
<p><input type= "Submit" value= "Log in"/></p>

As an attacker, he starts with a query statement that presumably validates the user name and password. By looking at the source file, he can begin to guess your habits.
Like naming habits. It is usually assumed that the field name in your form is the same as the field name in the datasheet. Of course, ensuring that they are different is not necessarily a reliable security measure.
For the first time guess, the query in the following example is generally used:

Copy CodeThe code is as follows:
$password _hash = MD5 ($_post[' password ');

$sql = "SELECT count (*)
From users
WHERE username = ' {$_post[' username '} '
and password = ' $password _hash ' ";

Using the MD5 value of the user's password turns out to be a common practice, but it's not particularly safe now. Recent studies have shown that the MD5 algorithm is flawed, and that a large number of MD5 databases reduce the difficulty of MD5 reverse cracking. Visit http://md5.rednoize.com/to view the demo (in this case, a study by Professor Xiao of Shandong University shows that MD5 "collisions" can be quickly found, that is, different two files and strings that produce the same MD5 values. MD5 is the information digest algorithm, not the encryption algorithm, the reverse crack also can not talk about. However, according to this result, in the above exception, the direct use of MD5 is dangerous. )。
The best way to protect it is to attach a string of your own definition to the password, for example:

Copy CodeThe code is as follows:
$salt = ' Shiflett ';
$password _hash = MD5 ($salt. MD5 ($_post[' password ']. $salt));

Of course, attackers may not be able to guess the first time, and they often need to do some experiments. One of the better ways to experiment is to enter single quotes as usernames, because this may expose some important information. There are a lot of developers who call function Mysql_error () to report an error when a MySQL statement executes incorrectly. See the following example:

Copy CodeThe code is as follows:
mysql_query ($sql) or exit (Mysql_error ());

While this approach is useful in development, it can expose important information to attackers. If an attacker puts a single quotation mark as a user name and Mypass as a password, the query statement becomes:

Copy CodeThe code is as follows:
$sql = "SELECT *
From users
WHERE username = "'
and password = ' a029d0df84eb5549c641e04a9ef389e5 ' ";

When the statement is sent to MySQL, the system displays the following error message:

Copy CodeThe code is as follows:
You have a error in your SQL syntax. Check the manual, corresponds to your
MySQL Server version for the right syntax to use near ' WHERE username = ' and
Password = ' a029d0df84eb55

Effortlessly, attackers already know the two field names (username and password) and the order in which they appear in the query. In addition, the attacker knew that the data was not properly filtered (the program did not prompt for an illegal user name) and escaped (a database error occurred), and that the format of the entire where condition was exposed, so that an attacker could attempt to manipulate records that conformed to the query.
At this point, attackers have many options. One is to try to fill in a special user name, so that the query regardless of whether the user name password is consistent, can be matched:

Copy CodeThe code is as follows:
MyUser ' or ' foo ' = ' foo '--

Assuming that Mypass is a password, the entire query becomes:

Copy CodeThe code is as follows:

$sql = "SELECT *
From users
WHERE username = ' myuser ' or ' foo ' = ' foo '--
and password = ' a029d0df84eb5549c641e04a9ef389e5 ' ";


Fortunately, SQL injection is easy to avoid. As mentioned earlier, you must persist in filtering the input and escaping the output.
Although two steps cannot be omitted, it is possible to eliminate most of the SQL injection risk by implementing one of them. If you just filter the input without escaping the output, you are likely to encounter database errors (legitimate data may also affect the correct format of the SQL query), but this is unreliable, and legitimate data can also alter the behavior of SQL statements. On the other hand, if you escape the output without filtering the input, you can guarantee that the data will not affect the format of the SQL statement, and also prevent many common methods of SQL injection attacks.
Of course, you should stick with both steps at the same time. The way the input is filtered depends entirely on the type of input data (see the example in Chapter one), but escaping the output data used to send to the database can only be done using the same function. For MySQL users, you can use the function mysql_real_escape_string ():

Copy CodeThe code is as follows:
$clean = Array ();
$mysql = Array ();

$clean [' last_name '] = "O ' Reilly";
$mysql [' last_name '] = mysql_real_escape_string ($clean [' last_name ']);

$sql = "INSERT
into User (last_name)
VALUES (' {$mysql [' last_name ']} ');

Try to use the escape function designed for your database. If not, using the function addslashes () is the final good method.
When all the data used to create an SQL statement is properly filtered and escaped, the risk of SQL injection is actually avoided. If you're using a database operation class that supports parameterized query statements and placeholders (such as pear::D B, PDO, and so on), you'll get a bit more protection. See below for an example of using pear::D B:

Copy CodeThe code is as follows:
$sql = ' INSERT
into User (last_name)
VALUES (?) ';
$DBH->query ($sql, Array ($clean [' last_name ']));

Because the data in the previous example does not directly affect the format of the query statement, the risk of SQL injection is reduced. PEAR::D B is automatically escaped according to your database requirements, so you only need to filter the output.
If you are using parameterized query statements, the input will only be processed as data. There is no need to escape, although you might think it is a necessary step (if you want to persist in escaping the output habit). In fact, there is essentially no impact when escaping, because there are no special characters that need to be converted. In preventing SQL injection, parameterized query statements provide powerful protection for your program.
NOTE: Regarding SQL injection, it must be said that most of the virtual host will now open the MAGIC_QUOTES_GPC option, in which case all the client get and post data will be automatically addslashes processing, so at this time the SQL injection of the string value is not feasible , but to prevent SQL injection of numeric values, such as functions such as intval (). But if you are writing generic software, you need to read the server's MAGIC_QUOTES_GPC and handle it accordingly.

Go: How to prevent SQL injection in PHP

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.