|
|
CMS103 - Securing Your Website - Keeping your included files from being accessed directly. | ||
Discussion by vujsa with 9 Replies.
Last Update: January 20, 2008, 4:15 pm | |||
See Also:
- http://www.astahost.com/cms101-content-man...sign-t7778.html
- http://www.astahost.com/cms102-content-man...ign-t11367.html
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:
CODE
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.com/cms101-content-man...sign-t7778.html
index.php
CODE
<?phpdefine( "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>
header.php
CODE
<?phpdefined( '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!
CODE
<?phpdefined( '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>
main.php
CODE
<?phpdefined( '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.
footer.php
CODE
<?phpdefined( '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.
CODE
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.
CODE
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
CODE
defined( 'MY_ACCESS_CODE' ) or die( 'Direct Access to this location is not allowed.' );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.
vujsa
Sun Jun 11, 2006 Reply New Discussion
I have a concern about part of your code that is used in .htaccess.
The problem here is you're specifying .inc .include to be used by the PHP interpretter, it may not seem like a problem until you start wondering about what mime-type .inc or .include would originally use. Just because you specified that it should be handled by the PHP interpretter and said application/x-httpd-php what if this did not work?
In a situation where .htaccess could possibly fail (1:Million?), be overwritten (does happen), someone forgets to configure it, etc, these files are vulnerable to being viewed as plain/text (possibly?) and you don't want that. At least if you maintained the file extension of PHP, then it's a known mime-type by the server and it should not need to be told how it's handled, though older versions you had to still specify this.
I think it's better to call the file something like filename.inc.php rather than just filename.inc as you're not making it compatible across all servers doing this.
By allowing this other extension, although I know it was used prior (so was short hand coding and see how that went with compatibility), you now have to be aware of your doings, and that if you had to prevent someone creating a .php file from user input, you need to remember also using .inc .include as well and prevent that too.
To sum up what I'm saying, if it's PHP keep to PHP's extension, if it's PERL use PERL's extension, if it's HTML, etc, stick to that extension, same goes for those who like changing the PHP interpretter to handle .html files, it's not the best thing security wise or performance wise for that matter. Keep to what's known.
As a semi-related thing, also your code editors will display the right colour coding syntaxing if they knew the filetype correctly.
Apart from that your tutorial seems good, though you don't seem to handle situations where include fails. Include will commonly fail if the file does not exist or unreadable, so include('thisfile.php') or code_to(... handle it ...); or better an alternative to display in it's place or if no alternative, then obviously this might need to have been required using require(), where if this fails your script terminates at the point it failed with an allowable error to be displayed.
Another security bonus that you missed is that you can store your include files outside of the web root, meaning it's inaccessible from viewing it directly by it's link, which probably destroys the need for the defined() but better safe than sorry.
Cheers,
MC
Mon Jun 12, 2006 Reply New Discussion
QUOTE (mastercomputers)
I think it's better to call the file something like filename.inc.php rather than just filename.inc as you're not making it compatible across all servers doing this.
...
To sum up what I'm saying, if it's PHP keep to PHP's extension, if it's PERL use PERL's extension, if it's HTML, etc, stick to that extension, same goes for those who like changing the PHP interpretter to handle .html files, it's not the best thing security wise or performance wise for that matter. Keep to what's known.
Link: view Post: 80522
Hey thanks for the reply MC. I completely agree with you this time.
The only reason I wrote the article was because I knew so many people use the .inc extention. I figured if they were going to use this method of naming files, they should at least try to add some security. I guess I forgot to add my disclaimer to the tutorial.
Disclaimer:
PHP files should use a .php file extention. If you choose not to follow this very simple rule, then at least add a few security measures to try and protect yourself.
QUOTE (mastercomputers)
Apart from that your tutorial seems good, though you don't seem to handle situations where include fails. Include will commonly fail if the file does not exist or unreadable, so include('thisfile.php') or code_to(... handle it ...); or better an alternative to display in it's place or if no alternative, then obviously this might need to have been required using require(), where if this fails your script terminates at the point it failed with an allowable error to be displayed.
Another security bonus that you missed is that you can store your include files outside of the web root, meaning it's inaccessible from viewing it directly by it's link, which probably destroys the need for the defined() but better safe than sorry.
Link: view Post: 80522
I tend to not go into error handling in my tutorials. I usually add those functions after I nearly complete my scripts. I guess that I would have an easier time debugging scripts if I'd add the error handlers during the coding proccess.
I might look into doing a really detailed error handling tutorial sometime.
QUOTE (mastercomputers)
Another security bonus that you missed is that you can store your include files outside of the web root, meaning it's inaccessible from viewing it directly by it's link, which probably destroys the need for the defined() but better safe than sorry.
Link: view Post: 80522
Actually, I decided not to go into that option because I was afraid it could get confussing for some people. It is easy to forget about a file that is off the grid so to speak. But placing your sensitive files in non-web access directories is a great security measure. Most of use have been doing this exact thing with our .htpasswds files. I guess it is a rather simple concept but I consider it a more advanced security measure.
One additional note which MC touched on.
Setting your server to send HTML files through the PHP engine WILL have an effect on your website proformance. Even though the HTML files may not contain any PHP, the engine still has to read the entire file before it will release it to the browser. If your file doesn't have any PHP in it, it should be a HTML file. If your file has PHP in it, then it should be a PHP file.
vujsa
Mon Jun 12, 2006 Reply New Discussion
Sun Jul 9, 2006 Reply New Discussion
QUOTE (warallthetm)
I have seen it where html files have had php variables like index.html?id=test , was this done using htaccess to parse it as php, or is it some kind of client side scripting like javascript? I cant see why you would need to do this with an html? Can you explain?
Link: view Post: 82376
They were probably PHP files (or a similar technology, like ASP or JSP) using a .html extension for whatever reason. I know that a certain book on PHP recommends naming your PHP files with .html extensions to mask your use of PHP, thereby making your site just a little tougher for hackers. But I have to agree with vujsa and mastercomputers - it's better to name files as what they are.
If they were static HTML files, they must have had some sort of client-side script using the variable(s). Plain HTML can't do anything with variables - it's a markup language, not a programming or even scripting language. As far as I know (but my knowledge here is small - correct me if I'm wrong), Javascript doesn't have a native function for extracting variables from a URL. You could write a script to do it manually, though, if you really wanted to.
Incidentally, forcing an extension to parse as PHP doesn't necessarily have to be done in .htaccess. If you have access to your server configuration file, you can add the option there, which will change the setting for your whole website, not just the folder you put .htaccess in. Changing the server configuration globally isn't always desirable or feasible (as, for instance, when you are using a free web host!) but it's more efficient than using .htaccess.
Mon Jul 10, 2006 Reply New Discussion
good job there
this is bater than my way
i use Get and Post chackers and only by moving or including the file its useable
ill try this method later today
NoMore
Sat Nov 11, 2006 Reply New Discussion
Before i edited my .htaccess it looked like this:
CODE
# This folder does not require access over HTTP# (the following directive denies access by default)Order allow,denyShould it look like that =? (be empty)
Now this is how it looks:
CODE
# This folder does not require access over HTTP# (the following directive denies access by default)Order allow,denyAddType application/x-httpd-php .inc
AddType application/x-httpd-php .include
I am using Wamp
By the way: Very Very good tutorial =)
Fri Jan 18, 2008 Reply New Discussion
Feelay try this. Note, as Vujsa said there is a blank line at the end.
CODE
# This folder does not require access over HTTP (the following directive denies access by default)#Order allow,deny
AddType application/x-httpd-php .inc
AddType application/x-httpd-php .include
Sun Jan 20, 2008 Reply New Discussion
Sun Jan 20, 2008 Reply New Discussion
Sun Jan 20, 2008 Reply New Discussion
Creating And Using Includes With PHP A simple tutorial (6)
|
(2) Using Leading Zeros And Sorting Data Sort data correctly
|
Index




