• Aucun résultat trouvé

With security there are many factors to account for in every project. Many of these factors are the same for every project. Simple organization is a basic tool in the fight against invasion. Any elimination of disorganization is beneficial, as it eases the code review process, finding and fixing problems, refactoring code, and any number of other jobs a developer does. Consistency in repetition is a habit that is actually a valu-able tool that can be leveraged very effectively in secure development. With these two ideas in mind, a reusable layout template of basic project files is the subject of this chapter. The premise is that many files and base configurations are consistent and do not change from project to project.

Every App Has Some Basic Similarities

Every PHP/MySQL/HTML/jQuery/JavaScript application has many identical parts.

This chapter looks at many of these and proposes a base starting point. The structure here is not advocated as the best, or as the only one. It is a starting point to iden-tify common, reusable parts of an application structure. The reader is encouraged to modify this to suit his or her own style and project needs.

Project Layout Should Be Handled Consistently

A basic, reusable project structure is presented here.

/include secrets,php constants.php database.php sessions.php account.php error.log

|

__/WEBROOT/

index.php.php login.php public.php |

/HTML/

header.html footer.html

about.html contact.html |

/images/

logo.jpg

loginButton.jpg logOut.jpg |

/css/

layout.css form.css |

/javascript/

scripts.js

jqueryscripts.js

This basic layout achieves several goals.

• It separates the files according to type.

• It reduces the number of PHP files with direct access.

• It locates the secret and important files outside of the web root, preventing direct access.

• It isolates the static CSS, Image, and JS files which enables relocation to another server.

Application Secrets Include Files Outside of Web Root First, application secrets must be located up and out of the web root directory so that they are not directly accessible via HTTP request. The files should be located anywhere that is accessible by URL.

Second, the files should have the .php extension, not an .inc extension. .inc files are directly viewable in a browser, .php files are not. It is simply an extra protection. PHP files located in the web root directory need to access files located outside of the web directory by specifying at least one level of parent directory traversal like so,

<?php

include "../include/secrets.php";

?>

This provides file level protection for the secrets file as only the PHP engine can access files outside the web root directory. Incoming URL requests cannot access files outside of the web directory. This file has double protection. The .php extension, because it is parsed by the PHP engine, prevents direct viewing via web request, and since the file is located outside the web root, it is inaccessible via direct URL request.

Global constants in a file outside the web root is another good practice. Global constants can reveal a great deal about an application. Treating this like a secrets file helps prevent information leakage.

Core PHP Files Outside of Web Root Main PHP files, like the database file which contains the application’s SQL statements, and the login file are also good files to place outside of the main web root.

Keep the number of files that are publicly accessible to a minimum. Keep the core of your processing logic outside of the web root. Use the index file as a gateway to accessing support files. This always then gives the developer direct control over file access. By using gateway files, users are prevented from accessing core files directly. For example, the database.php located in the include directory cannot be called directly.

This prevents accidental misuse simply because a user has database.php as a URL in their browser history. The file database.php should never be a URL. Gateway files, such as index.php and login.php prevent this from happening. The only files that users should ever see as URLs are files like index.php, main.php, and public.php.

A PDO DB Access Class Template A PDO template class is included in the project layout files. It contains the base code to correctly make UTF-8 connections, query wrappers, and the application SQL.

This book heavily advocates locating all SQL statements in a single file, as a data-base repository pattern. Doing so greatly improves consolidating SQL statements and ensuring SQL security. Obviously, every single SQL statement will change for every project, but the process of calling them can remain the same. In this database class there are two parts to the class. Section one contains reusable connections and PDO query wrappers to help separate database calls from HTML output. Section two contains all the application SQL.

The following code uses connection data from the secrets.php file to make a connec-tion. To open different databases in different projects, simply change the connection information in the secrets file.

Include "secrets.php"

class mobileSecData {

public $conn = null;

public function_construct($host, $db, $user, $pass) {

try {

$t his->conn = new PDO("mysql:host = {$host};dbname = {$db};charset = utf8", $user, $pass);

$this->conn->setAttribute(PDO::ATTR_ERRMODE,

PDO::ERRMODE_EXCEPTION);

$this->conn->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);

}

catch(PDOException $e) {

$this->logErr($e->getMessage()); //log detailed errors

header('Location: sitedown.html'); //mo ve user to useful support page

exit(); //se rious problem, do not

continue page }

}

$db = new mobileSecData($host, $dbname, $username, $password);

The last statement of the file instantiates the database class, mobileSecData, with the connection info from secrets.php which automatically makes a global database object for the application to use whenever a file includes mobieSecData.php.

In practice, this connection call almost never changes, therefore it is wrapped in a class and accessed application wide as a single database object. Two sections of this function that might be altered on a per-project basis are the setting of different or additional attributes, and changing the catch handler.

The catch handler here first logs the error, which is essential, and then redirects to a generic site down page. This is important if your application cannot function without database support. The user genuinely does need to know that the site is down, but does not need to know details.

Finally, the exit() function is called. It is a best practice to call this after a redi-rect to discontinue processing of the page, which might leak information, or open a security hole. If the database is down, there is no reason to continue this page, or the calling page. Move the user to a support page and exit.

Select Query Wrapper

The following class function is a façade that enables DRY programming and helps separate HTML from PHP.

private function selectQuery($query, Array $qArray) {

try{

$stmt = $this->conn->prepare($query);

$stmt->execute($qArray);

$result = $stmt->fetch();

}

catch(PDOException $e) {

$this->logErr($e->getMessage());

}

return $result;

}

This function is a façade for the steps needed to make a PDO Select query. It takes the query string as the first parameter, and a parameter array as the second. The query string is prepared, and the parameter array is passed directly to the execute()  function.

Notice that the function is private and cannot be called externally. This forces SQL to be kept inside the class. SQL outside cannot be used.

It is called like this, from inside a public member function, which is what the appli-cation uses:

public function getUserName($userName) {

$query = "SELECT 1 FROM users WHERE username = :username";

$params = array(':username' = > $userName);

$result = $this->selectQuery($query, $params);

return $result;

}

This function contains the SQL and builds the necessary parameters. The function has a very descriptive name so the client of this function can know what it is.

The function takes a single parameter, the user name, which fits with the function name. All the client needs to know is the name of the user it wants. getUserName() handles the details of SQL and parameter construction in a single location.

The application calls this function in the following manner:

<?php

Include "../include/database.php";

$record = $db-> getUserName("Gus");

?>

This structure is repeatable for every project, and use of it or one similar is highly encouraged as a general practice.

HTML Template Files Very good reasons for separating static HTML files are so that designers can easily manipulate the HTML and so that HTML has a chance of being cached by the web server. PHP applications usually create most HTML dynami-cally, but HTML parts, like headers, footers, navigation panels, and possibly pure static contact like About pages can be separated out, which makes maintenance easier.

Whenever HTML can be pulled out of PHP, is it usually worth doing it.

Separation of HTML Static Resources

For static resources like CSS, images, and JavaScript files, there is one very good reason for the users of the application to separate them out from HTML. It makes the actual HTML smaller and allows for browser caching. Caching improves the speed of repeated page views and the number of HTTP requests by preventing the downloading of unchanged content for every page view. On every page load of your application, these resources are loaded. It is a big performance gain to make sure the files are downloaded only once and then cached by the browser. The browser cannot do this if CSS and JavaScript are inline with the HTML. For example, if there are

three pages in your application with CSS used by all of them, putting the CSS in its own file, and linking it via the HTML header meta-tag, allows the browser to down-load it and cache it for the first page of your application. The remaining two pages are now smaller, and the CSS is now already present on the browser, so fewer bytes are transferred.

Another possibility is that the CSS, images, and JavaScript can be relocated easily to a completely different web server for serving static content faster. This relieves the PHP server from serving static content and makes it freer for processing PHP.

Caching of files can be set with the following time limits in seconds:

Cache-Control: max-age = 31536000 will cache it for 1 year, which is the max recommended.

Cache-Control: max-age = 15768000 will cache it for 6 months.

CSS Files Setting CSS cache expiration for 3 months in seconds.

header('Content-Type: text/css');

header('Cache-Control: max-age = 7884000');

Javascript Files Setting Javascript cache expiration for 3 months in seconds.

header('Content-Type: text/javascript');

header('Cache-Control: max-age = 7884000');

Image Files Setting JPEG cache expiration for 3 months in seconds.

header('Content-Type: image/jpeg');

header('Cache-Control: max-age = 7884000');

The Completely Commented Files

All the files in the project layout are completely commented with explanations to make their intent and usefulness clear. Feel free to modify at will. It is just a starting point.

PHP PDO/UTF-8 Security Checklist

A checklist and base php.ini file are included for review with every project.

121

8