In the previous 2 articles describing how to create a simple CMS using the PHP include() function, I've discussed how using included files can save a webmaster a lot of time. The downside to using included files is that it is possible for sensitive data to be public accessable. For example, if a hacker was to access and read one of your included files, he may be able to find a security hole in your script. The best way to prevent these kinds of security leaks is to ensure that the contents of any included file can not be viewed direclty.
Generally speaking, if your included files have a file extention of .php, then they should be treated like a normal PHP file and plain text will not be displayed if the file is access directly. This is only true if you make sure that you use opening (<?php) and closing (?>) PHP tags in your included files. Otherwise, everything will be treated like plain text when accessed directly. This is how we can have PHP in one part of our file and HTML in another part of the same file.
The real issue comes up when a file extention other than .php is used like the .inc or include file extention. Usually, most servers don't automatically parse .inc files as PHP. This can be remedied using your .htaccess file.
Editing or creating the .htaccess file in the directory where you have saved all of your included files can tell the server to parse .inc files as PHP.
In .htaccess add:
AddType application/x-httpd-php .inc AddType application/x-httpd-php .include
Basically, this tells the server to send all files with the extention .inc or .include to the PHP engine.
Now that the server thinks these are PHP files, anything inside of the PHP tags will not be sent to the browser without being parsed.
Already, we have made a great improvement in the security of our included files but more can and should be done.
ALWAYS BE SURE TO LEAVE A BLANK LINE AT THE END OF YOUR .htaccess FILE SO cPanel CAN ACCESS IT IF NEEDED!
Checking to be sure that an included file is being accessed by it's parent script before sending it's contents will make it very difficult to be viewed directly and/or in raw form.
In order to do this quickly and easily, we'll used 2 related PHP functions, define() and defined().
The define() function should be used in the parent script, usually index.php.
The defined() function should be used in each of the included files.
Assuming that you understood the code in the first 2 articles listed above, here is how the code looks.
Modified code from http://www.astahost....sign-t7778.html
<?php define( "MY_ACCESS_CODE", true );?><html><head><title>My CMS</title></head><body bgcolor="#FFFFFF" text="#000000" link="#0000FF" vlink="#800080" style="font-family: verdana;"><table width="100%"><tr><td colspan="2" bgcolor=silver><?php include("header.php"); ?> <!-- Used for Banner Advertising etc... --></td></tr><tr><td width="150" bgcolor=red valign="top"><?php include("menu.php"); ?> <!-- Used for The Main Menu... --></td><td bgcolor=navy><?php include("main.php"); ?> <!-- Could be left out and actual content inserted instead. --></td></tr><tr><td colspan="2" bgcolor=purple><?php include("footer.php"); ?> <!-- Banner Ads, Copyright Info., etc... --></td></tr></table></body></html>
<?php defined( 'MY_ACCESS_CODE' ) or die( 'Direct Access to this location is not allowed.' ); ?> <center> <a href="http://www.AstaHost.com" style="border-width: 2px; border-color: teal; font-size: 18pt; font-color: #FF0000;">Advertise Here!</a> </center>
menu.php - Here is the real time saver!
<?php defined( 'MY_ACCESS_CODE' ) or die( 'Direct Access to this location is not allowed.' ); ?> <span style="font-color: lime;">Search Engines</span><br> <a href="http://www.altavista.com" style="font-size: 8pt;"> ♦ Alta Vista</a><br> <a href="http://www.excite.com" style="font-size: 8pt;"> ♦ Excite</a><br> <a href="http://www.google.com" style="font-size: 8pt;"> ♦ Google</a><br> <a href="http://www.lycos.com" style="font-size: 8pt;"> ♦ Lycos</a><br> <a href="http://www.yahoo.com" style="font-size: 8pt;"> ♦ Yahoo</a><br>
<?php defined( 'MY_ACCESS_CODE' ) or die( 'Direct Access to this location is not allowed.' ); ?> <p> Enter your main content here. You can simple leave the include statement out of the template and enter the content for the page directly into the index.php. Hope this proves usefull to everyone.
<?php defined( 'MY_ACCESS_CODE' ) or die( 'Direct Access to this location is not allowed.' ); ?> <center> © 2005 Acme Web Design Inc. - All Right Reserved.<br> </center>
Now here is how it works:
define() defines a constant in PHP. This is like a variable in PHP but it will never vary.
define("HAPPINESS", "Hot apple pie."); echo HAPPINESS;Prints: Hot apple pie.
In our case, we only need to define that the constant named 'MY_ACCESS_CODE' is defined so we put true in the definition field of the function like so.
define( "MY_ACCESS_CODE", true );We don't care if the constant has a value or not just that is has been defined. We define the constant in the file that calls all of the included files. This is the parent script. It is usually the one that is presented to the public like index.php.
Next we check to see if the constant named 'MY_ACCESS_CODE' is defined. We do this in our included files. Since the constant is only defined in the file that is supposed to request it, the requesting file is the only one that has direct access to the included file.
When we use the defined() function, we are not actually doing anything as a result of a true answer to the question. The question is of course is "Is 'MY_ACCESS_CODE' defined as a constant?". What we are actually doing is performing an action if the answer to the question is false. If the answer is false, then we kill the script with the die() function. This acts as the custom error message handle for all PHP functions.
So we check to see if the constant is defined. If it is then there is no error in the code and the code continues to the next line. If the constant is NOT defined then there is an error and the die() function takes over. The script will do whatever the die() function says and will then terminate. Nothing past the die() function will be used. This includes any HTML that resides below the die() function! So only the
defined( 'MY_ACCESS_CODE' ) or die( 'Direct Access to this location is not allowed.' );need to be inside of the PHP tags (<?php and ?>).
I usually place the defined() function at the very begining of the file since it is the first thing I want to check but theoretically, it can be placed anywhere inside of the file and still work as long as it is not inside of a conditional statement which could cause it to be bypassed.
So by ensuring that all of your included files are parsable by the PHP engine and only allowing direct access to included files by parent scripts, you will greatly reduce the risk of security holes in your website. These methods as well as ensuring that your file permissions are set properly will make for a more secure site.
Additional security can be added to your website that range outside of this topic but include .htaccess settings which controls how the server will handle any file or file type you define.
I hope this information proves to be useful to everyone.