1. The magic_quotes_gpc option in the php. ini configuration file of the php tutorial is not enabled and is set to off. 2. The developer does not check and escape the data type.
But in fact, the second point is the most important. In my opinion, it should be the most basic quality for a web programmer to check the data types entered by users and submit the correct data types to the mysql tutorial. But in reality, many small web developers often forget this, leading to a wide open backdoor.
Why is the second most important? Without the second guarantee, the magic_quotes_gpc option may cause SQL injection attacks, whether on or off. The following describes the technical implementation:
1. injection attack when magic_quotes_gpc = off
Magic_quotes_gpc = off is a very insecure option in php. The new php version has changed the default value to on. However, there are still a considerable number of server options that are off. After all, some old servers are also used.
When magic_quotes_gpc = on, it automatically adds all '(single quotes), "(double sign), (backslash), and white space characters in the submitted variables to the front. The official instructions for php are as follows:
View sourceprint?
Magic_quotes_gpc boolean
Sets the magic_quotes state for gpc (get/post/cookie) operations. when magic_quotes are on, all' (single-quote), "(double quote), (backslash) and nul's are escaped with a backslash automatically
If there is no escape, that is, off, attackers can take advantage of it. The following test script is used as an example:
1 <?
2if (isset ($ _ post ["f_login"])
3 {
4 // database connection tutorial...
5 //... Code omitted...
6
7 // check whether the user exists
8 $ t_struname = $ _ post ["f_uname"];
9 $ t_strpwd = $ _ post ["f_pwd"];
10 $ t_strsql = "select * from tbl_users where username = '$ t_struname' and password = '$ t_strpwd' limit ";
11
12 if ($ t_hres = mysql_query ($ t_strsql ))
13 {
14 // processing after successful query...
15}
16}
17?>
18
19 20 <body>
21 <form method = post action = "">
22 username: <input type = "text" name = "f_uname" size = 30> <br>
23 password: <input type = text name = "f_pwd" size = 30> <br>
24
25 <input type = "submit" name = "f_login" value = "login">
26 </form>
27 </body>
In this script, when the user enters the normal user name and password, assuming the values are zhang3 and abc123, the SQL statement submitted is as follows:
1 select * from tbl_users
2 where username = 'hangzhou3' and password = 'abc123' limit
If the attacker enters zhang3 'or 1 = 1 # In the username field and abc123 in the password field, the SQL statement submitted is changed to the following:
1 select * from tbl_users
2 where username = 'hangzhou' or 1 = 1 # 'and password = 'abc123' limit
Because # Is a comment character in mysql, # the subsequent statement is not executed, and the above statement is implemented:
1 select * from tbl_users
2 where username = 'hangzhou3' or 1 = 1
In this way, attackers can bypass authentication. If attackers know the database structure, it is more dangerous to construct a union select statement:
Assume that in username, enter: zhang3 'or 1 = 1 union select cola, colb, cold from tbl_ B #
Enter abc123 in password,
The submitted SQL statement is changed:
1 select * from tbl_users
2 where username = 'hangzhou3'
3 or 1 = 1 union select cola, colb, cold from tbl_ B # 'and password = 'abc123' limit 0, 1
This is quite dangerous. If the agic_quotes_gpc option is on and the quotation marks are escaped, the attack statement constructed by the above attacker will become like this and thus cannot achieve its purpose:
1 select * from tbl_users
2 where username = 'hangzhou' or 1 = 1 #'
3 and password = 'abc123'
4 limit 0, 1
5
6 select * from tbl_users
7 where username = 'hangzhou' or 1 = 1 union select cola, colb, cold from tbl_ B #'
8 and password = 'abc123' limit 0, 1
2. injection attack when magic_quotes_gpc = on
When magic_quotes_gpc = on, attackers cannot perform SQL Injection on fields of the stable type. This does not mean this is safe. In this case, you can use numeric fields for SQL injection.
In mysql 5.x of the latest version, data type input is strictly specified, and automatic type conversion is disabled by default. A numeric field cannot be a quote type marked with quotation marks. That is to say, if the uid is numeric, in the previous mysql version, such a statement is legal:
1 insert into tbl_user set uid = "1 ";
2 select * from tbl_user where uid = "1 ";
In the latest mysql 5.x, the preceding statement is not legal and must be written as follows:
1 insert into tbl_user set uid = 1;
2 select * from tbl_user where uid = 1;
In this case, I think it is correct. As a developer, it is the most basic requirement to submit correct data types that comply with the Rules to the database.
How can attackers attack magic_quotes_gpc = on? It is very simple, that is, SQL injection to numeric fields. The following php script is used as an example:
1 <?
2 if (isset ($ _ post ["f_login"])
3 {
4 // connect to the database...
5 //... Code omitted...
6
7 // check whether the user exists
8 $ t_struid = $ _ post ["f_uid"];
9 $ t_strpwd = $ _ post ["f_pwd"];
10 $ t_strsql = "select * from tbl_users where uid = $ t_struid and password = '$ t_strpwd' limit 0, 1 ";
11 if ($ t_hres = mysql_query ($ t_strsql ))
12 {
13 // processing after successful query...
14}
15
16}
17?>
18 19 <body>
20 <form method = post action = "">
21 user id: <input type = "text" name = "f_uid" size = 30> <br>
22
23 password: <input type = text name = "f_pwd" size = 30> <br>
24 <input type = "submit" name = "f_login" value = "Logon">
25 </form>
26 </body>
The above script requires the user to enter userid and password to log on. A normal statement. The user inputs 1001 and abc123. The SQL statement submitted is as follows:
Select * from tbl_users where userid = 1001 and password = 'abc123' limit
If the attacker inputs 1001 or 1 = 1 # At userid, the SQL statement injected is as follows:
Select * from tbl_users where userid = 1001 or 1 = 1 # and password = 'abc123' limit
The attacker achieved the goal.
Iii. How to Prevent php SQL injection attacks
How to Prevent php SQL injection attacks? In my opinion, the most important thing is to check and escape data types. The following rules are summarized:
The display_errors option in php. ini should be set to display_errors = off. In this way, php scripts do not output errors on web pages, so that attackers can analyze the information.
When calling mysql functions such as mysql_query, add @, I .e. @ mysql_query (...), so that mysql errors will not be output. Similarly, attackers may not analyze useful information. In addition, some programmers are used to output errors and SQL statements when mysql_query errors occur during development, such as: 1 $ t_strsql = "select a from B ....";
2 if (mysql_query ($ t_strsql ))
3 {
4 // Correct Handling
5}
6 else
7 {
8 echo "error! SQL statement: $ t_strsql rn error message ". mysql_query ();
9 exit;
10}
This approach is quite dangerous and stupid. To do this, you 'd better set a global variable or define a macro in the website configuration file and set the debug flag:
1 // in the global configuration file:
2 define ("debug_mode", 0); // 1: debug mode; 0: release mode
3
4 // In the call script:
5 $ t_strsql = "select a from B ....";
6 if (mysql_query ($ t_strsql ))
7 {
8 // Correct Handling
9}
10 else
11 {
12 if (debug_mode)
13 echo "error! SQL statement: $ t_strsql rn error message ". mysql_query ();
14 exit;
15}
Run the convert and type checks on the submitted SQL statements.
4. I wrote a security parameter to obtain the function.
To prevent incorrect data and php + mysql injection, I wrote a function papi_getsafeparam () to obtain the safe parameter values:
1 define ("xh_param_int", 0 );
2 define ("xh_param_txt", 1 );
3 function papi_getsafeparam ($ pi_strname, $ pi_def = "", $ pi_itype = xh_param_txt)
4 {
5 if (isset ($ _ get [$ pi_strname])
6 $ t_val = trim ($ _ get [$ pi_strname]);
7 else if (isset ($ _ post [$ pi_strname])
8 $ t_val = trim ($ _ post [$ pi_strname]);
9 else
10 return $ pi_def;
11
12 // int
13 if (xh_param_int ==$ pi_itype)
14 {
15 if (is_numeric ($ t_val ))
16 return $ t_val;
17 else
18 return $ pi_def;
19}
20
21 // string
22 $ t_val = str_replace ("&", "& amp;", $ t_val );
23 $ t_val = str_replace ("<", "& lt;", $ t_val );
24 $ t_val = str_replace (">", "& gt;", $ t_val );
25 if (get_magic_quotes_gpc ())
26 {
27 $ t_val = str_replace ("", "& quot;", $ t_val );
28 $ t_val = str_replace ("'' "," & #039; ", $ t_val );
29}
30 else
31 {
32 $ t_val = str_replace ("", "& quot;", $ t_val );
33 $ t_val = str_replace ("'", "& #039;", $ t_val );
34}
35 return $ t_val;
36}
In this function, there are three parameters:
$ Pi_strname: variable name
$ Pi_def: Default Value
$ Pi_itype: data type. The optional values are xh_param_int and xh_param_txt, which indicate the numeric type and the text type respectively.
If the request is numeric, call is_numeric () to determine whether the request is Numeric. If not, return the default value specified by the program.
For simplicity, for text strings, I escape all the dangerous characters (including html code) entered by the user. Due to the vulnerability in php function addslashes (), I replaced it directly with str_replace. The get_magic_quotes_gpc () function is a php function used to determine whether the magic_quotes_gpc option is enabled.
The sample code in Section 2 can be called as follows:
1 <?
2 if (isset ($ _ post ["f_login"])
3 {
4 // connect to the database...
5 //... Code omitted...
6
7 // check whether the user exists
8 $ t_struid = papi_getsafeparam ("f_uid", 0, xh_param_int );
9 $ t_strpwd = papi_getsafeparam ("f_pwd", "", xh_param_txt );
10 $ t_strsql = "select * from tbl_users where uid = $ t_struid and password = '$ t_strpwd' limit 0, 1 ";
11 if ($ t_hres = mysql_query ($ t_strsql ))
12 {
13 // processing after successful query...
14}
15}
16?>