As a PHP programmer, especially novice, for the Internet sinister always know too little, for the outside of the intrusion there are many times the hands are no way, they do not know how the hacker intrusion, submit intrusion, upload vulnerabilities, SQL injection, cross script attacks and so on. As the most basic precaution you need to pay attention to your external submissions, do the first security mechanism to handle the firewall.
Rule 1: Never trust external data or input
The first thing you must realize about Web application security is that you should not trust external data. External data (outside) includes any data that is not entered directly by the programmer in the PHP code. Any data from any other source, such as a Get variable, form POST, database, configuration file, session variable, or cookie, is not trusted until the action is taken to ensure security.
For example, the following data elements can be considered safe because they are set in PHP.
Listing 1. Safe and Flawless code
Copy Code code as follows:
$myUsername = ' Tmyer ';
$arrayarrayUsers = Array (' Tmyer ', ' Tom ', ' Tommy ');
Define ("greeting", ' Hello there '. $myUsername);
?>
However, the following data elements are flawed.
Listing 2. Unsafe, flawed code
Copy Code code as follows:
$myUsername = $_post[' username ']; tainted!
$arrayarrayUsers = Array ($myUsername, ' Tom ', ' Tommy '); tainted!
Define ("greeting", ' hello there '. $myUsername); tainted!
?>
Why is the first variable $myusername flawed? Because it comes directly from the form POST. Users can enter any string in this input field, including malicious commands for purging files or running previously uploaded files. You might ask, "Can't you avoid this danger by using a client (javascrīpt) Form validation script that accepts only the letter A-Z?" Yes, this is always a good step, but as you'll see later, anyone can download any form to their machine, modify it, and resubmit whatever they need.
The solution is simple: You must run cleanup code on $_post[' username '. If you do not, you may contaminate these objects at any other time using $myusername, such as in arrays or constants. An easy way to clean up user input is to use a regular expression to handle it. In this example, you only want to accept letters. It may also be a good idea to limit the string to a specific number of characters, or to require all letters to be lowercase.
Listing 3. Making user input Secure
Copy Code code as follows:
$myUsername = cleanInput ($_post[' username ')); clean!
$arrayarrayUsers = Array ($myUsername, ' Tom ', ' Tommy '); clean!
Define ("greeting", ' hello there '. $myUsername); clean!
function CleanInput ($input) {$clean = Strtolower ($input);
$clean = Preg_replace ("/[^a-z]/", "", $clean);
$clean = substr ($clean, 0,12); return $clean;
}
?>
Rule 2: Disable PHP settings that make security difficult to implement
You know you can't trust user input, and you should know that you shouldn't trust the way you configure PHP on your machine. For example, be sure to disable register_globals. If you enable Register_globals, you may do something careless, such as using $variable to replace a GET or POST string with the same name. By disabling this setting, PHP forces you to reference the correct variable in the correct namespace. To use a variable from the form POST, you should refer to $_post[' variable '. This will not misunderstand this particular variable as a cookie, session, or get variable.
Rule 3: If you can't understand it, you can't protect it.
Some developers use strange syntax, or organize statements in a compact, short but ambiguous code. This approach can be efficient, but if you don't understand what the code is doing, you can't decide how to protect it. For example, which paragraph of the following two sections of code do you like?
Listing 4. Make code easy to protect
Copy Code code as follows:
obfuscated code
$input = (isset ($_post[' username ')] ($_post[' username '): ");
unobfuscated Code
$input = ";
if (isset ($_post[' username ')) {
$input = $_post[' username '];
}else{
$input = ";
}
In the second clear code snippet, it is easy to see that $input is flawed and needs to be cleaned before it can be safely processed.
rule 4: "Defense in Depth" is a new weapon
This tutorial will use an example to illustrate how to protect online forms while taking the necessary steps in processing the form's PHP code. Also, even if you use a PHP regex to ensure that a get variable is entirely numeric, you can still take steps to ensure that the SQL query uses escaped user input. Defense in depth is not just a good idea, it can make sure you don't get into serious trouble. Now that the basic rules have been discussed, let's look at the first threat: SQL injection attacks.
Preventing SQL injection attacks
In a SQL injection attack, a user adds information to a database query by manipulating the form or get query string. For example, suppose you have a simple login database. Each record in this database has a username and a password field. Build a login form that allows users to log in.
Copy Code code as follows:
<title>Login</title>
<body>
<form action= "verify.php" method= "POST" >
<p><label for= ' user ' >Username</label>
<input type= ' text ' name= ' user ' id= ' user '/>
</p> <p><label for= ' pw ' >Password</label>
<input type= ' password ' name= ' pw ' id= ' PW '
</p> <p><input type= ' submit ' value= ' login '/></p>
</form>
</body>
This form accepts the user name and password entered by the user and submits the user input to the file named verify.php. In this file, PHP processes data from the login form, as follows:
Listing 5. Unsafe PHP Form handling code
Copy Code code as follows:
<?php
$okay = 0;
$username = $_post[' user '];
$PW = $_post[' pw '];
$sql = "SELECT count (*) as Ctr from users where Username= '
". $username." ' and password= '. $PW. "' Limit 1″;
$result = mysql_query ($sql);
while ($data = Mysql_fetch_object ($result)) {
if ($data->ctr = = 1) {
They ' re okay to enter the application!
$okay = 1;
}
}
if ($okay) {
$_session[' Loginokay '] = true;
Header ("index.php");
}else{
Header ("login.php");
}
?>
This code looks fine, doesn't it? This code is used by hundreds (even thousands) of php/mysql sites around the world. Where is it wrong? Well, remember "cannot trust user input." There is no escaping any information from the user, so the application is vulnerable to attack. Specifically, any type of SQL injection attack may occur. For example, if the user enters Foo as the user name and enters ' or ' 1′= ' 1 as the password, the following string is actually passed to PHP and the query is passed to MySQL:
Copy Code code as follows:
<?php
$sql = "SELECT count (*) as Ctr from users where username=
' foo ' and password= ' or ' 1′= ' 1′limit 1″;
?>
This query always returns the count value of 1, so PHP will allow access. By injecting some malicious SQL into the end of the password string, the hacker can dress up as a legitimate user. The solution to this problem is to use PHP's built-in mysql_real_escape_string () function as a wrapper for any user input. This function escapes characters in the string, making it impossible for strings to pass special characters such as apostrophes and let MySQL operate on special characters. Listing 7 shows the code with escape processing.
Listing 7 shows the code with escape processing
Copy Code code as follows:
<?php
$okay = 0;
$username = $_post[' user '];
$PW = $_post[' pw '];
$sql = "SELECT count (*) as Ctr from users where Username= '". Mysql_real_
_string ($username). "' and password= '. Mysql_real_escape_string ($PW). "'
Limit 1 ";
$result = mysql_query ($sql);
while ($data = Mysql_fetch_object ($result)) {
if ($data->ctr = = 1) {//they ' re okay to enter the
application!
$okay = 1;
}
}
if ($okay) {
$_session[' Loginokay '] = true;
Header ("index.php");
}
else{
Header ("login.php");
}
?>
By using mysql_real_escape_string () as a wrapper for user input, you can avoid any malicious SQL injection in user input. If a user attempts to pass a malformed password through SQL injection, the following query is passed to the database:
Copy Code code as follows:
Select COUNT (*) as Ctr from users where Username= ' foo ' and password=
' \ ' or \ ' 1\ ' =\ ' 1′limit 1″