• Aucun résultat trouvé

Every PHP/MySQL/HTML/JavaScript application has several parts that are the same for every application. Security issues likewise require that certain procedures be followed every time. It stands to reason that it is worthwhile to identify these parts and examine how we can organize them into a reusable template. This is not a template in the same category as a framework, such as the Zend Framework, but a template for laying out and recognizing reusable parts from a project perspective. Chapter 7, “Project Layout Template,” describes the specific files and code patterns common to many applications.

A Consistent UTF-8 Character Set

The first element that is the basis for a secure application is a consistent character set encoding. Not having a consistent character set across the application is the cause of both data misinterpretation, which is the root of security holes, and data destruction when user-entered data gets parsed or saved incorrectly. It is quite common for charac-ter set mismatches to occur in an application. Two reasons for this are lack of awareness of the issue, and the fact that there are so many places where the mismatch can occur.

This book chooses to use UTF-8 as the specific character set. The reason is that UTF-8 is Unicode, can accommodate all languages, and works to send multi-byte characters to a browser without mangling them. Also, because of the way UTF-8 characters are encoded, it cannot be tricked into parsing multi-byte characters in dif-ferent ways, so its security is increased.

To make this happen in PHP and MySQL, the character set has to be set in several places and in several different ways. A complete UTF-8 project setup is outlined in Chapter 6, but here is a review of the basics.

While this book uses UTF-8, the character set used doesn’t matter as long as it is the same throughout the book. The foundational basis of secure programming rests on properly parsing and examining data. This can only be done when the charac-ter set/encoding of the supplied data matches the characcharac-ter set of the filcharac-ters used.

Mismatched data is the root of much evil.

Remember: Take action and explicitly configure the character sets used by the appli-cation processes.

1. Decide what character encoding should be used.

2. Ensure all internal functions, filters, and structures, are configured for the chosen character encoding.

3. Ensure user-supplied data is comprised of the chosen encoding.

4. Convert or drop data that does not conform.

UTF-8 in the Database

The database setup requires that the database itself be declared with the UTF-8 char-acter set. It also needs to have what is known as the collation set to UTF-8. Collation is how characters are compared during a search. If the collation is different than the character set of the search characters, mismatches can result.

Next, the actual columns in the table can each have their own character set, which could be different from UTF-8, and collation. There needs to be a check that these are UTF-8 and not something else.

The query client connection to the database must also be set to UTF-8 in order to ensure that no translation errors occur. If you ever save a multi-byte string to the database and get garbage characters back, it is usually because the table column, or the client connection, is not set to be the same.

UTF-8 in the PHP Application

First, PHP must be set to process UTF-8 internally. This can be done via the php.ini file, or via the mb_internal_encoding() function.

An example of ensuring conformance would be the following.

mb_substitute_character(0xFFFD);

mb_convert_encoding($userdata, 'UTF-8', 'UTF-8');

mb_substitute_character() configures the replacement character for detected invalid characters and is an important base function. This is so critically important that it is repeated several times in this book to reinforce its use and application.

If a  replacement character is not specified, invalid characters are silently dropped.

This creates a security risk because attack strings can be assembled by having characters dropped.

DEXLETE becomes DELETE

Note: See Mark Davis, Michel Suignard, Unicode.org deletion point security advisory.

Multi-byte functions need to be set to UTF-8 in php.ini, and strings must be processed with multi-byte string functions. Otherwise your string lengths and other calculations will not be correct. The PDO database connection must be opened with the charset UTF-8 parameter set in order to ensure that the client connection is correct.

UTF-8 in the Client Browser

The web browser is told to speak UTF-8 from either the HTML header, or a meta-tag embedded in the HTML page header section. The PHP server code needs to set the header to UTF-8 and send this ahead of the page content. A good practice is to include the meta-tag as well. This a double method of ensuring UTF-8 compliance on the browser, but it also makes it easy to view which character set is in use upon inspecting the page source.

The HTML form element can also be set to UTF-8 for specifying that form data be submitted as UTF-8.

Clean Secure Data

Now that all the parts are speaking the same language, UTF-8, the stage is set to clean the data. Every application needs to sanitize user-supplied data. Having a com-mon routine that performs this task is critical for the consistency aspect of security.

Creating a new input filter for routing every project is an anti-pattern to avoid.

One way to go about this is to create a filter routine that cleans all input variables equally. This is identified as an anti-pattern as well because not all data can or should be treated the same. Therefore a sanitization routine needs to implement a non-changing process, but handle different data sets based on the project requirements. Design patterns can help accomplish this.

Input Validation: Account for Size and Type

Input types, ranges, and sizes should be a part of every application so that proper filtering can occur consistently. While inputs will always be different for every application, the way integers are treated and the way strings are treated are the same.

There should be an object that helps you organize and classify the applications input so that it becomes very easy to know what to do with input variables, and more importantly, to easily keep track of whether variables have even been filtered.

The goal is to enforce correct data where necessary and to preserve data where possible. Achieving this goal depends on clearly delineating input filtering and output escaping. User data can only be safely preserved in the database if it is safely escaped upon output. If not, then the user input must be destructively filtered in anticipation of safe rendering later. Remember a general rule of thumb: filtering removes, escaping preserves for a specific context.

Escape Output: Account for Context

Output context is critical. The wrong text in the right context opens a security hole.

Tracking which data goes to which output context is at this point a critical part of secure development. An application needs a process for easily escaping to the proper

context each and every time. This process needs to ensure that output is encoded, and quoted correctly for each context. This includes HTML, URLs, URL parameters, JavaScript, JSON, and CSS.

Database Access Pattern

Since SQL injection is such a widespread problem, attention has to be paid to it.

A database access pattern is a tool for a developer to gain control over SQL. A simple form of this pattern is a global application object, a singleton pattern that contains all the SQL statements an application needs. The first goal this achieves is the consoli-dation of SQL statements into one location, making tracking and refactoring a great deal easier. The second goal this achieves is a clearer security perspective. It is much easier to find and correct problems “correctly” with all the statements in one place.

One is much less likely to miss something if one doesn’t have to hunt down all the places a SQL statement could be hiding.

Application Secrets Location Pattern

The basic measure is to include account names and passwords in a file located outside of the web root directory. Other files should load this file via a dot dot include pattern such as "..\inc\secrets.inc" pattern. It is wise for main classes to be outside the web root as well, and that the only files in the web root are main application entry points such as index.php and support files.

Error Processing Pattern

There should be a consistent pattern for handling errors that occur. Handling errors in the same fashion helps ensure good handling. Error messages, response logic, and logging are part of the system. The logic for local errors, and the logic for global errors need to be put in place. A good error system should handle errors in stride and keep the system going forward, and prevent it from falling down. If a fatal error does occur, the details of the event definitely need to be recorded, but this is an extra step that needs to be included in the code via the register_shutdown_function() function.

There is a choice in PHP between error functions and exception handling. This book employs exception handling. Part of that choice entails mapping errors into an exception handling mechanism.

The other decisions that need to be made regard what constitutes an error. There are errors that are recoverable, and those that are not recoverable. Deciding what stops the application from continuing is a very important architectural decision that affects the entire application, both from a security standpoint and a usability standpoint.

Error Logging Process Pattern

The logging system is very important. The location of the log file is important.

It  should be outside of the web root as well. The logging system should record the  kind of error in a meaningful manner, the file, and line number of where it occurs.

Authentication Pattern

Authentication is also a part of every application that maintains user accounts. This is a critical system as well and one that should not be completely reinvented for every application. Even if the HTML interface changes the look and location of the user-name and password form, the essential handling of logging in, authenticating the password, storing the password, handling the session cookie, logging out, and clear-ing the cookie should be consistent across your applications.

Authorization Pattern

Authorization is an additional security step that has to be specifically employed.

This step is a two-factor process that helps ensure that someone knows what he/she should know. It is not enough that a page request include an active, authenticated cookie. This cookie could be stolen. High-risk requests such as changing account information like a password, or making a purchase need an additional piece  of  information, for example, re-verifying the user’s password.

Asking that this step be completed each time a high-risk request is made helps ensure that automated methods of impersonation are greatly reduced. Therefore, logic needs  to  exist  that  helps  distinguish and direct high-risk requests to the authorization function.

White Listing Acceptable Input

Data that is needed will vary greatly between applications, but there should be logic that helps consolidate, identify, and look up the application’s “acceptable”

data. Examples of this would be acceptable colors a user could choose, or a list of table columns a user could search from. A white list of acceptable terms helps keep your internal data clean and free from injection. Using a white list is a powerful mechanism that lets users choose without being able to inject. Part of your design process should be identifying a list of ranges, choices to the extent possible, and presenting those choices to the user. The processing of a white list selection always occurs through a lookup table and never uses direct input. If direct input does not match the lookup, the input is discarded. Via this mechanism, injection of any kind is blocked.

PHP Security Design Best Practices Summary

Every web application needs to address the following issues in order to meet the requirements for current web application protection.

Architect application character set Architect HTTP request patterns Architect HTTP cookie usage Architect input validation Architect output escaping Architect session management

Protect secret files/protect included files Protect user passwords

Protect user session data Protect against CSRF attacks

Protect against SQL injection attacks Protect against XSS attacks

Protect against file system attacks Proper error handling

Architect Application Character Set

The foundation of a secure process is speaking the language. The character set needed to support the application requirements needs to be chosen and configured across the entire application. All data must conform to this requirement, as well as all filter, sanitization, and storage processes. Any time data characters are different from the processing expectation, the possibility to exploit the system exists. This then becomes a critical element of application planning and execution.

Architect HTTP Request Patterns

What kind of HTTP requests an application uses, and how those requests are used has an overall effect on the security of an application. The requests allowed determin-ing the attack vectors which will be inherent to the application, which determine what kind of attacks can be formed against the application, and what kind of attacks the application could be susceptible to.

Some HTTP request design considerations that can help eliminate or control attack vectors are:

• GET for public, read only requests

• GET for persistable, cachable URL requests

• GET for persistable, one-time NONCE URL requests

• POST over SSL for private, authenticated requests

• POST for public updates and state change requests

• POST over SSL for private update and state change requests

• POST for non-persistable, non-cachable URL requests

• POST-Redirect-GET pattern for POST results

Read only requests are static, or dynamically generated pages which are not changed, and can be read by anyone, anonymous or authenticated. Persistable URLs are URLs that can be safely saved, cached, or stored in emails and book-marks  because  they do not contain sensitive data embedded within the URL.

A NONCE URL contains a one-time code that is storable in an email, for example, and activates a process. The URL can only be used one time, after which it becomes useless. A POST for private, authenticated requests should be over SSL and prevent sensitive data from being persisted in the URL. POST should be used for altering and updating data. POST should be used when it is not desirable for data to be embedded in a URL. The PRG pattern, explained later, prevents double submission of form data.

Architect HTTP Cookie Usage

It is strongly advised to use HTTP cookies for a single purpose. Use a restricted authentication cookie, which is only transmitted over SSL to private URL path requests, for accessing private documents. Use a separate public cookie, which can be transmitted over HTTP for accessing read only, public URL documents. A public cookie should have no connection whatsoever to an authentication cookie, and each is used independently.

Architect Input Validation

The first rule of thumb in security is “Don’t trust any user input. Ever.” Always assume the worst; always assume incorrect data; always assume data is attacking your applica-tion. Always validate and filter incoming data. This is a key architecture component in building a secure application.

Data can only be validated by the server side PHP code. JavaScript is an assistant for legitimate users. It is a very important assistant for users, as it saves them time and hassle, and increases usability. It is not secure.

Architect Output Escaping

The new second rule of thumb is to not trust user output either. Output escap-ing needs to be thought out in order to be effective as well. Where is the data going, and how is the data being formatted? This affects how output escaping code is implemented.

Architect Session Management

This is a central aspect to the security of any system. Session management is what decides the encryption, and is what protects the session ID, the cookies, user veri-fication, and access level. It also determines user satisfaction with usability and confidence of protection.

The effectiveness of the login system, the registration system, and the page view system are dependent on this logic. Additionally, a critical part of protecting user ses-sion data and/or account data is to ensure that all required input forms are accessed over SSL. In addition to protecting the transmission of data, SSL certificates also afford higher levels of certainty that the user is legitimately connected to the real application. To protect the application and the users, session management needs a thorough and complete design that addresses all the issues.

Protect Secret Files/Protect Included Files

One of the first things an application does is to determine which file(s) to call. A first task then is to ensure only the correct files can be called. PHP scripts almost always include other PHP files for connecting to a database or accessing additional functions and classes. Simple white listing of files is one of the first defenses to ensure that the application is choosing the file, and not untrusted user input. Always use the .php extension for included code files so that the contents cannot be reflected back to a browser and read. .inc extensions are not parsed by PHP and serve plain text to the browser when called directly. If these files are not placed outside of the web root direc-tory, then an attacker is able to read all of the application’s key data. Always keep these configuration files outside of the web root directory so that they are not accessible via direct web requests.

Protect User Passwords

User passwords can be protected in several ways. First is to not keep/never store the actual password at all, only a hash of it. The second is to store these hashes with modern levels of encryption. This means using Blowfish, Rijndael256, or Serpent.

The third method is to ensure the secure transmission of user passwords via SSL so that passwords are never in the open, and that the likelihood of being intercepted is reduced.

Protecting User Session Data

There are several parts that must be addressed to protect session data. This includes where session data is stored, and how session data is handled as determined by the configuration of the php.ini file. Options available for better protection are moving