Home >Backend Development >PHP Tutorial >An in-depth analysis of the seven habits of writing secure PHP applications_PHP Tutorial

An in-depth analysis of the seven habits of writing secure PHP applications_PHP Tutorial

WBOY
WBOYOriginal
2016-07-21 15:08:09834browse

When it comes to security issues, it's important to note that in addition to actual platform and operating system security issues, you also need to ensure that you write secure applications. When writing PHP applications, apply the following seven habits to ensure your application has the best possible security:
• Validate input
• Protect the file system
• Protect the database
•Protect session data
•Protect cross-site scripting (XSS) vulnerabilities
•Verify form post
•Protect against Cross-Site Request Forgeries (CSRF) Protect

Validate input
When it comes to security issues, validating your data is the most important habit you can adopt. And when it comes to input, it's very simple: don't trust the user. Your users may be excellent, and most of them may use the application exactly as expected. But wherever there is an opportunity for input, there is also a high probability of very bad input. As an application developer, you must prevent your application from accepting incorrect input. Careful consideration of the location and correct value of user input will allow you to build a robust, secure application.
Although file system and database interaction will be covered later, Listed below are general validation tips that apply to various validations :
• Use white Values ​​in the list
• Always revalidate limited options
• Use built-in escaping functions
• Validate correct data types (like numbers)
Values ​​in the whitelist (White- listed value) is the correct value, as opposed to the invalid black-listed value (Black-listed value). The difference between the two is that typically when validating, the list or range of possible values ​​is smaller than the list or range of invalid values, many of which may be unknown or unexpected values.
When doing validation, remember that it is often easier to design and validate the values ​​your application allows than to protect against all unknown values. For example, to limit a field value to all numbers, you need to write a routine that ensures that the input is all numbers. Do not write routines that search for non-numeric values ​​and mark them as invalid when they are found.

Securing File Systems
In July 2000, a Web site exposed customer data stored in files on the Web server. A visitor to the Web site used the URL to view a file containing data. Although the file was misplaced, this example highlights the importance of protecting the file system from attackers.
If a PHP application manipulates a file and contains variable data that the user can enter, carefully check the user input to ensure that the user cannot perform any inappropriate actions on the file system. Listing 1 shows an example of a PHP site that downloads an image with a specified name.
List 1. Download file

Copy code The code is as follows:

if ($_POST['submit'] == 'Download') {
$file = $_POST['fileName'];
header("Content-Type: application/x-octet-stream ");
header("Content-Transfer-Encoding: binary");
header("Content-Disposition: attachment; filename="" . $file . "";" );
$fh = fopen($file, 'r');
while (! feof($fh))
{
echo(fread($fh, 1024));
}
fclose( $fh);
} else {
echo("<");
echo("title>Guard your filesystem" );
echo("
"" method="post">");
echo("
echo(isset($_REQUEST['fileName']) ? $_REQUEST['fileName'] : '');
echo("" />");
echo("
");
echo("
");
}

As you can see, the more dangerous script in Listing 1 will process all files that the web server has read access to, including files in the session directory (see "Securing session data") and even some system files ( For example /etc/passwd). For demonstration purposes, this example uses a text box where the user can type a filename, but the filename can easily be provided in the query string.
Simultaneous configuration of user input and file system access is dangerous, so it is best to design your application to use a database and hide generated filenames to avoid simultaneous configuration. However, this doesn't always work. Listing 2 provides a sample routine for validating file names. It will use regular expressions to ensure that only valid characters are used in file names, and specifically checks for dot characters: ..
Listing 2. Checking for valid filename characters
Copy code The code is as follows:

function isValidFileName($file) {
/* don't allow .. and allow any "word" character / */
return preg_match('/^(((?:.)(?!.)) |w)+$/', $file);
}

Protect database
In April 2008, the Bureau of Prisons of a certain state in the United States was querying SQL column names were used in the string, thus exposing confidential data. This breach allowed a malicious user to select which columns to display, submit the page, and obtain the data. This leak shows how users can perform input in ways that application developers could not have anticipated, and demonstrates the need to defend against SQL injection attacks.
Listing 3 shows a sample script that runs a SQL statement. In this case, the SQL statement is a dynamic statement that allows the same attack. The owner of this form may think the form is safe because they have restricted the column names to select lists. However, the code misses one last tip about form cheating — just because the code limits the options to a drop-down box doesn't mean that someone else can't post the form with the required content (including the asterisk [*]).
Listing 3. Execute SQL statement
Copy code The code is as follows:


SQL Injection Example


method="post">
value=" $_POST['account_number'] : ''); ?>" />



if ($_POST['submit'] == 'Save') {
/* do the form processing */
$link = mysql_connect ('hostname', 'user', 'password') or
die ('Could not connect' . mysql_error());
mysql_select_db('test', $link);

$ col = $_POST['col'];
$select = "SELECT " . $col . " FROM account_data WHERE account_number = "
. $_POST['account_number'] . ";" ;
echo '

' . $select . '

';
$result = mysql_query($select) or die('

' . mysql_error() . '

' );
echo '';
while ($row = mysql_fetch_assoc($result)) {
echo '';
echo '';
echo '';
}
echo '
' . $row[$col] . '
';
mysql_close($link );
}
?>



So, to get into the habit of protecting your database, avoid using dynamic SQL code whenever possible. If you cannot avoid dynamic SQL code, do not use input directly on a column. Listing 4 shows that in addition to using a static column, you can add a simple validation routine to the account number field to ensure that the input value is not a non-numeric value.
Listing 4. Protection via validation and mysql_real_escape_string()
Copy code The code is as follows:



SQL Injection Example


method="post">
value=" $_POST['account_number'] : ''); ?>" /> < input type="submit"
value="Save" name="submit" />


function isValidAccountNumber($number )
{
return is_numeric($number);
}
if ($_POST['submit'] == 'Save') {
/* Remember habit #1--validate your data! */
if (isset($_POST['account_number']) &&
isValidAccountNumber($_POST['account_number'])) {
/* do the form processing */
$link = mysql_connect('hostname', 'user', 'password') or
die ('Could not connect' . mysql_error());
mysql_select_db('test', $link);
$select = sprintf("SELECT account_number, name, address " .
" FROM account_data WHERE account_number = %s;",
mysql_real_escape_string($_POST['account_number']));
echo '< p>' . $select . '

';
; 🎜> echo '';
while ($row = mysql_fetch_assoc($result)) {
echo '';
echo '';
$ row ['address']. '& lt;/td & gt;';
echo '& lt;/tr & gt;';
}
echo '& lt;/table & gt;'; $ link); } else {
echo "& lt; span style =" font-color: red "& gt;".
"Please support a valid account number! & lt;/span & gt;" "; }
}
?>




This example also shows the usage of mysql_real_escape_string() function. This function will filter your input correctly so it does not include invalid characters. If you have been relying on magic_quotes_gpc, you need to note that it is deprecated and will be removed in PHP V6. From now on you should avoid using it and write secure PHP applications in this case. Also, if you are using an ISP, it is possible that your ISP does not have magic_quotes_gpc enabled.
Finally, in the improved example, you can see that the SQL statement and output do not include the dynamic column options. Using this approach, you can export columns if they are added to a table that later contains different information. If you are using a framework to work with a database, your framework may already perform SQL validation for you. Make sure to check the documentation to ensure the framework is secure; if you're still unsure, verify it to make sure. Even when using a framework for database interaction, there are still additional validations that need to be performed.

Protect Sessions
By default, session information in PHP will be written to a temporary directory. Consider the form in Listing 5, which shows how to store the user ID and account number within a session.
Listing 5. Storing data in session
Copy the code The code is as follows:

< ;?php
session_start();
?>


Storing session information


if ($_POST['submit'] == 'Save') {
$_SESSION['userName'] = $_POST[' userName'];
$_SESSION['accountNumber'] = $_POST['accountNumber'];
}
?>
method="post">

Value="" />


value= " $_POST['accountNumber'] : ''); ?>" />







Listing 6 shows the contents of the /tmp directory.
Listing 6. Session files in /tmp directory
Copy code The code is as follows:

-rw ------- 1 _www wheel 97 Aug 18 20:00 sess_9e4233f2cd7cae35866cd8b61d9fa42b

As you can see, when output (see Listing 7), the session file contains the information in a very readable format . Because the file must be readable and writable by the Web server user, session files can cause serious problems for all users on the shared server. Someone other than you could write a script to read these files and therefore try to get the values ​​out of the session.
Listing 7. Contents of session file
Copy code The code is as follows:

userName | s:5:"ngood";accountNumber|s:9:"123456789";

Storing Passwords
Passwords should never be stored as plain text, whether in a database, session, file system, or any other form. The best way to handle passwords is to store them encrypted and compare the encrypted passwords with each other. Despite this, in practice people still store passwords in plain text. Whenever you use a website that can send passwords instead of resetting them, that means the password is stored in plain text or you can get a code for decryption (if encrypted). Even with the latter, the decryption code can be found and used.
There are two actions you can take to protect your session data. The first is to encrypt everything you put into your session. But just because encrypting your data doesn't mean it's completely secure, use this approach with caution as the only way to protect your session. An alternative is to store session data elsewhere, such as a database. You will still have to make sure to lock the database, but this approach will solve two problems: first, it will put the data in a more secure location than a shared file system; second, it will allow your application to more easily span With multiple web servers, simultaneous shared sessions can span multiple hosts.

To implement your own session persistence, see the session_set_save_handler() function in PHP. Using it you can store session information in a database or implement a handler for encrypting and decrypting all data. Listing 8 provides implemented function usage and function skeleton examples. You can also see how to use the database in the Resources section.
Listing 8. session_set_save_handler() function example
Copy code The code is as follows:

function open($save_path, $session_name)
{
/* custom code */
return (true);
}
function close()
{
/* custom code */
return (true);
}
function read($id)
{
/* custom code */
return (true);
}
function write($id, $sess_data)
{
/* custom code */
return (true);
}
function destroy($id)
{
/* custom code */
return (true);
}
function gc($maxlifetime)
{
/* custom code */
return (true);
}
session_set_save_handler("open", "close", "read", "write", "destroy", "gc");

For XSS vulnerabilities Protecting
XSS vulnerabilities represented the majority of vulnerabilities in all archived Web sites in 2007 (see Resources). An XSS vulnerability occurs when a user is able to inject HTML code into your web page. HTML code can carry JavaScript code within script tags, allowing JavaScript to run whenever the page is fetched. The form in Listing 9 could represent a forum, wiki, social network, or any other site where text can be entered.
Listing 9. Form for inputting text
Copy code The code is as follows:

< html>

Your chance to input XSS










Listing 10 demonstrates how a form that allows XSS attacks can output results.
Listing 10. showResults.php
Copy code The code is as follows:



Results demonstrating XSS


echo("");
echo("

");
echo($_POST['myText']);
echo("?>



Listing 11 provides a basic example in which a popup Create a new window and open Google's homepage. If your web application is not protected against XSS attacks, serious damage can be caused. For example, someone could add links that mimic the site's style for the purpose of phishing (see Resources).
List 11. Sample of malicious input text
Copy code The code is as follows:



To prevent XSS attacks, as long as the value of the variable will be printed to the output , you need to filter the input through the htmlentities() function. Remember to follow Habit #1: Validate input data with values ​​from a whitelist in inputs to your web application for names, email addresses, phone numbers, and billing information.
A more secure page showing text input is shown below.
Listing 12. More secure form
Copy code The code is as follows:

< html>

Results demonstrating XSS


echo( "

You typed this:

");
echo("

");
echo(htmlentities($_POST['myText']));
echo("

");
?>



Protect against invalid posts
Form spoofing means someone sends a post to your form from an inappropriate location. The simplest way to spoof a form is to create a web page that passes all values ​​through submission to the form. Because web applications are stateless, there is no sure-fire way to ensure that the data being published comes from a specified location. Everything from IP addresses to hostnames can be spoofed. Listing 13 shows a typical form that allows entry of information.
Listing 13. Form for processing text
Copy code The code is as follows:

< html>

Form spoofing example


if ( $_POST['submit'] == 'Save') {
echo("

I am processing your text: ");
echo($_POST['myText']);
echo("

");
}
?>



Listing 14 shows Publish to the form shown in Listing 13. To try this, you can put the form into a Web site and save the code in Listing 14 as an HTML document on your desktop. After saving the form, open it in a browser. You can then fill in the data and submit the form to see how the data is processed.
Listing 14. Form for collecting data
Copy code The code is as follows:

< html>

Collecting your data









The potential impact of form spoofing is that if you have a form that contains drop-down boxes, radio buttons, check boxes, or other input-restricted These restrictions have no meaning when the form is spoofed. Consider the code in Listing 15, which contains a form with invalid data.
Listing 15. Form with invalid data
Copy code The code is as follows:



Collecting your data


method="post"> value="There is no way this is a valid response to a yes/no answer..." />


< ;/body>


Think about it: If you have a drop-down box or radio button that limits the amount of user input, you might think you don’t have to worry about validating input. After all, the input form will ensure that the user can only enter certain data, right? To limit form spoofing, validation is required to ensure that the publisher's identity is genuine. You can use a single-use tag, although this technique still doesn't make the form completely secure, but it makes form spoofing more difficult. Since the markup is changed each time the form is called, a would-be attacker would have to obtain an instance of the sent form, remove the markup, and put it into a fake form. Using this technology can prevent malicious users from constructing persistent web forms to issue inappropriate requests to applications. Listing 16 provides an example of form markup.
Listing 16. Using disposable form tags
Copy the code The code is as follows:

< ;?php
session_start();
?>


SQL Injection Test


echo 'Session token=' . $_SESSION['token'];
echo '
';
echo 'Token from form=' . $_POST['token'];
echo '
';
if ($_SESSION['token'] == $_POST['token'] ) {
/* cool, it's all good... create another one */
} else {
echo '

Go away!

';
}
$token = md5(uniqid(rand(), true));
$_SESSION['token'] = $token;
?>
method="post">

Value="" />
< /div>




Protect against CSRF
Cross Site request forgery (CSRF attack) is the result of an attack performed using user privileges. In a CSRF attack, your users can easily become unintended accomplices. Listing 17 provides an example of a page that performs a specific action. This page will look up user login information from cookies. As long as the cookie is valid, the web page will process the request.
Listing 17. CSRF example
Copy code The code is as follows:



CSRF attacks usually appear in the form of tags because the browser will The URL is called unknowingly to obtain the image. However, the image source can be a page URL in the same site that is processed based on the incoming parameters. When this tag is combined with an XSS attack - the most common among the documented attacks - users can easily perform some actions on their credentials without their knowledge - and are therefore forged.
To protect you from CSRF attacks, you need to use the one-time tag method used when validating form posts. Also, use the explicit $_POST variable instead of $_REQUEST. Listing 18 demonstrates a poor example of handling the same Web page—whether the page is called via a GET request or by posting a form to the page.
Listing 18. Obtain data from $_REQUEST
Copy the code The code is as follows:



Processes both posts AND gets


if ($_REQUEST['submit'] == 'Save') {
echo("

I am processing your text: ");
echo(htmlentities($_REQUEST['text' ]));
echo("

");
}
?>



Listing 19 shows a clean page using only form POST.
Listing 19. Get data from $_POST only
Copy code The code is as follows:



Processes both posts AND gets


if ($_POST['submit'] == 'Save') {
echo("

I am processing your text: ");
echo(htmlentities( $_POST['text']));
echo("

");
}
?>



Conclusion
Try writing more secure PHP web applications by starting with these seven habits that can help you avoid falling victim to malicious attacks who. Like many other habits, these may be difficult to get used to at first, but following them will become more and more natural over time.
Remember the first habit is key: validate input. After ensuring that the input does not include invalid values, you can continue to protect the file system, database, and session. Finally, make sure your PHP code is resistant to XSS attacks, form spoofing, and CSRF attacks. Developing these habits can help you defend yourself against some simple attacks.

www.bkjia.comtruehttp: //www.bkjia.com/PHPjc/327487.htmlTechArticleWhen mentioning security issues, it should be noted that in addition to actual platform and operating system security issues, You also need to make sure you write secure applications. When writing PHP applications,...
Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
' $ . row[ 'account_number']. '