About the Author

Chris Shiflett

Hi, I’m Chris: entrepreneur, community leader, husband, and father. I live and work in Boulder, CO.


Secure Design

  • Published in PHP Architect on 23 Sep 2004
  • Last Updated 23 Sep 2004
  • 18 comments

Welcome to another edition of Security Corner. This month's topic is secure design, the application architecture that provides the foundation for secure development. The column on input filtering touched on this topic a bit, and it's something that is sure to appear in this column again.

Design has always been a controversial topic, but only because developers tend to be very loyal to their own discoveries, ideas, and approaches. Thus, discussing software design can spawn debates rivaled only by coding standards discussions, text editor opinions, and programming language choices. With this in mind, please feel free to suggest different approaches than the ones written here. Like any other developer, I'm always interested in learning new approaches, and I'd be happy to do a few case studies of any particularly sound designs.

In order to demonstrate some common approaches, I describe two different overall methods of organizing your applications that I refer to as the dispatch method and the include method.

Dispatch Method

A good software design should help developers to ensure that input filtering cannot be bypassed, ensure that tainted data cannot be mistaken for filtered data, and help identify the origin of data. Without these characteristics, a developer's task is more difficult and error-prone. Just as complexity in an application leads to more bugs, the lack of a sound design leads to more security vulnerabilities.

One popular design that embodies each of these characteristics is the dispatch method. The approach is to have a single PHP script available to the public (via URL). Everything else is a module included with include or require as needed. This method usually requires that a GET variable be passed along with every URL, identifying the task, although modern frameworks and techniques eliminate this need. This GET variable can be considered the replacement for the script name that would be used in a more simplistic design. For example:

http://example.org/dispatch.php?task=print_form

dispatch.php is the only file within document root. This allows a developer to do two important things:

  • Implement some global security measures at the top of dispatch.php and be assured that these measures cannot be bypassed
  • Easily see that input filtering takes place when necessary, by focusing on the control flow of a specific task

I have developed applications using this approach with great success. As a developer, I especially appreciate the simplicity. Over-architected applications tend to solve problems that don't exist, and the added complexity is rarely worth it.

To further illustrate this approach, consider the example dispatch.php script given in Listing 1.

Keeping in mind that dispatch.php is the only resource available to the public, it should be clear that the design of this application ensures that any global security measures taken at the top cannot be bypassed. It also lets a developer easily see the control flow for a specific task. For example, instead of glancing through a lot of code, it is easy to see that end.inc is only displayed to a user when $form_valid is TRUE, and because it is initialized as FALSE just before process.inc is included, it is clear that the logic within process.inc must set it to TRUE, otherwise the form is displayed again (presumably with appropriate error messages). It is also impossible to access end.inc otherwise, because it is not available via URL (it is not within document root).

In order to keep dispatch.php as simple as possible, I recommend only adding logic that is important to the control flow of the application and putting everything else in modules. It can also help your module organization to categorize them in three categories: presentation, logic, and database queries. These two guidelines make dispatch.php very readable.

If you use a directory index file such as index.php (instead of dispatch.php), you can use URLs such as http://example.org/?task=print_form.

You can also use the Apache ForceType directive or mod_rewrite to accommodate URLs such as http://example.org/app-name/print-form.

Include Method

An almost opposite approach is to have a single module that is included at the top of every public script (those within document root). This module is responsible for all global security measures, such as ensuring that input filtering cannot be missed.

Listing 2 gives a simplistic example of such a script, security.inc. This example demonstrates the handling of form submissions, although this is only one example of the types of tasks that can be performed here.

process.inc handles input filtering, and security.inc makes sure that it always executes when a form meets the minimum criteria for testing, which is that it only contains expected data. This is done by adding a hidden form variable to every form that identifies it (or using any approach that can be used to distinguish forms) and then comparing form fields with what is expected.

Listing 3 shows an example of a form that identifies itself as login and adheres to the checks from the example security.inc script shown in Listing 2.

Use the auto_prepend_file directive to ensure that security.inc is not accidentally left out.

Naming Conventions

A topic worth reiterating here is naming conventions. However you decide to name your variables, make sure that you choose a method that will not make it easy to mistakenly use tainted data. One approach is to rename any variable that is filtered to something that distinguishes it as being clean.

For example, Listing 4 demonstrates testing the format of an email address. The variable $clean['email'] will either not exist, or it will contain a valid email address. With this approach, you can safely use any variable within the $clean array in your programming logic, and the worst-case scenario is that you reference an undefined variable. You can catch these types of errors with your error reporting (a future topic for Security Corner), and the impact is much less severe anyway.

If you place your input filtering in a separate module (such as process.inc mentioned in Listing 2), it is important to initialize your $clean array in the parent script and to be sure that no path through your logic bypasses this initialization.

Until Next Time...

Of the two approaches discussed, I prefer the dispatch method. The main reason for my preference is that it levers existing mechanisms that have been proven reliable, such as the fact that only files within document root can be accessed via URL. Another benefit is that it relies less on the developer remembering to do something for security.

Again, if you have a particularly secure design that you wouldn't mind sharing with your fellow readers, please let me know. I'll be happy to have a look and provide a thorough analysis in the hopes that everyone benefits.

You should now have the tools you need to add security precautions to your next application design. Just be sure that your approach satisfies the three important characteristics I mentioned earlier. Help developers to ensure that data filtering cannot be bypassed, ensure that tainted data cannot be mistaken for clean data, and identify the origin of data.

Until next month, be safe.

About this article

Secure Design was last updated on 23 Sep 2004. Follow me on Twitter.

18 comments

1.Luis Garcia wrote:

I don't know if I'm missing something, but I can see no "listing 1", "listing 2"... in the article. Thx.

Mon, 14 Nov 2005 at 18:54:55 GMT Link


2.stan zita wrote:

THE USE OF THIS COMPUTER IS PUBLIC.

I WANT TO KEEP URL BUT I WANT TO

READ AND REPLY TO EMAIL UNDER SECURE

CONDITIONS USING MY PRIVATE PASSWORD.

HOW CAN I DO THIS?

WE HAVE WINDOWS 2000 WITH STOPZILLA.

PLEASE REPLY

Tue, 10 Jan 2006 at 16:34:05 GMT Link


3.Kyle Lougnot wrote:

Chris, I bought your book Essential PHP security, and I am finding it very helpful. I am interested in using the dispatch method for a project that I am currently working on, but am unsure of how to implement it. I am new to PHP and want to write secure code. Any help would be greatly appreciated.

My understanding of the dispatch method is as follows:

Main Dispatch URL, dispatch.php- All top tear request for services pass through dispatch. Display, logic, and database are handled by related modules.

Example

http://example.org/dispatch.php?task=search_products

if ($_Get['task'] = 'search_products')

{

/search/search_products.inc

}

search_products.php is the top tear service and is located in /search/search_products.php.

secuirty, database, logic, and display are handled by related modules.

ie.

product_security.php (filtering all $_GET data and other security concerns for product_search)

product_database.php (All database concerns for product_search)

product_logic.php (All logic for product_search ie. shopping cart logic, only 2 discounts per customer)

product_display.php (Display for product_search)

.htaccess then restricts access to /search to a specified IP address. Making dispatch.php the only php file visible to the Internet.

Is this the correct way to implement the dispatch method?

Sincely

Kyle Lougnot

klougnot@hotmail.com

Mon, 27 Feb 2006 at 17:06:25 GMT Link


4.Chris Shiflett wrote:

Hi Kyle,

Glad to hear the book is helpful. :-)

What I call the dispatch method is really a simplified version of a front controller in the popular MVC architecture.

Your basic summary sounds right (there's a missing = in your conditional, and $_GET is uppercase), but it's usually much easier to manage with a switch statement, since you'll be comparing $_GET['task'] to many different values.

I would also recommend that you place your search directory above document root. Remember that you include files based on their filesystem path, not URL. This is a bit safer than depending on .htaccess restrictions.

Hope that helps!

Mon, 27 Feb 2006 at 17:14:49 GMT Link


5.Chris Shiflett wrote:

Luis, you're right, there is some code that is missing. Thanks for pointing it out.

Mon, 27 Feb 2006 at 17:15:27 GMT Link


6.Kyle Lougnot wrote:

Thanks Chris,

I don't understand how placing php files in one directory up from root such as /search helps prevents direct access to the the php include files.

Can't anyone just type in the include address and access that file.

Does anything need to be configured in apache or php to prevent direct access to the include file.

Thanks

Kyle

Mon, 27 Feb 2006 at 18:19:42 GMT Link


7.Nate Klaiber wrote:

RE: Kyle

Placing files like this above root only allow YOU to include them in your scripts from running. This is relative to the filesystem, NOT the URL of the site.

The root of your site is:

http://my.site.com/

which can be translated on the backend as something like:

/user/path/to/document/root/

(or c:\Path\to\document\root if you are windows based)

So, anything up from the root folder can be accessed by the world on your site. Having your files stores in something like /document/ makes them unviewable (and unexecutable) to the world, but callable to you by your scripts.

I am pretty sure this is what Chris is referring to, if not - im sure he can correct me.

It helps in that your 'Models' can be hidden, and only used for processing in your 'controller' scripts or the like. This also prevents accidental leaking of important information if it is stored here. (same concept of the dispatch method discussed earlier...)

Hope this helps...

Peace,

Nate

Tue, 28 Feb 2006 at 17:32:25 GMT Link


8.Nate Klaiber wrote:

EDIT: I meant to say anything 'above' the root folder, like:

/root/includes/ would be accessible, whereas includes/root/ would not be....

Sorry about that...

Tue, 28 Feb 2006 at 17:34:31 GMT Link


9.Chris Davies wrote:

Out of curiosity, are there any security advantages/disadvantages to using the .php extension for included files rather than the .inc extension, as you use in your examples? For a site I'm currently developing, I'm using the dispatch pattern and I have the various "modules" located in /home/username/private_php/, while the dispatch core is located in the publically accessible: /home/username/public_html/admin/. Inside the private_php directory, I'm keeping the various modules as .php files rather than .inc files. Is this a bad idea?

My reasoning is that since the private_php directory isn't in the HTML root, people can't execute it anyway (unless they're on the same shared hosting as me and include() those private_php files... but I think that's unavoidable, judging by the comments left in another article). I suppose the only other additional security measure I could take is to chmod the private_php directory so that only the owner has +x permission, thus restricting other users on the shared hosting from being able to ls the files.

Thanks for writing these great articles, they've really inspired me to learn more PHP and they've given me a good idea of the coding habits to avoid.

Mon, 17 Apr 2006 at 17:07:18 GMT Link


10.Nate Klaiber wrote:

RE: Chris

I don't believe there to be any security advantage/disadvantage to using .php versus .inc. You have already covered the security in that they are not accessible to the public, but they are below the site root. Therefore, the only way which they could be run (aside from shared hosting) is if called directly in your scripts. Also, in most cases, for security, you will make sure .inc is parsed as PHP, making it the SAME as .php. It just seems to be a naming/convenience issue versus anything security related.

Chris can correct me if I am wrong though :)

Tue, 18 Apr 2006 at 12:57:46 GMT Link


11.thee wrote:

Re: Chris

On most of Apache/Php default install, .inc is not parsed as php. I would recommend using .inc.php as an extension since anyone could read your include files in plain text with their browser (or download the script if the filetype is not recognized by your browser).

Thu, 07 Sep 2006 at 18:51:09 GMT Link


12.Chris Shiflett wrote:

Your includes should not be stored within document root, because there's no need for them to have their own URL. You include them with a filesystem path.

If you must store your includes within document root, you should at least deny requests for them. I disagree with anyone who thinks executing them (e.g., using a .php file extension as a protective measure) is an acceptable alternative.

Fri, 08 Sep 2006 at 02:52:20 GMT Link


13.andrisp wrote:

Some hosting companies do not allow storing files above root directory. And some hosting companies do not allow using .htaccess files, so there is no way (AFAIK) to deny direct access with URL.

So I do something like this (my dispatch method):

Main script (index.php):

define('INCLUDED', true);

// code that parses URL and includes necessary module

All includes have:

if (@BLA !== true) {

die();

}

// code

Tue, 06 Mar 2007 at 15:44:46 GMT Link


14.andrisp wrote:

Oh, replace BLA with INCLUDED in my examples :)

Tue, 06 Mar 2007 at 15:45:59 GMT Link


15.Rico wrote:

I don't understand why anyone would use .inc as a PHP file extension. I have always found this crazy.

Use .php when it's a PHP file. Wether it's inside or outside your document root.

Mon, 06 Oct 2008 at 00:04:58 GMT Link


16.industriemusic11 wrote:

Wonderful article, thanks for putting this together! This is obviously one great post. Thanks for the valuable information and insights you have so provided here.

<a href='http://www.masalaart.com.sg'>new futura 4 bedroom</a>

Tue, 12 Sep 2017 at 09:05:32 GMT Link


17.industriemusic11 wrote:

Thanks for the valuable information and insights you have so provided here...

<a title="new futura 4 bedroom" href="http://www.masalaart.com.sg">new futura 4 bedroom</a>

Tue, 12 Sep 2017 at 09:06:20 GMT Link


18.industriemusic11 wrote:

<a href="" http://www.masalaart.com.sg"">new futura 4 bedroom</a>

Tue, 12 Sep 2017 at 09:07:00 GMT Link


Hello! What’s your name?

Want to comment? Please connect with Twitter to join the discussion.