tags:

views:

201

answers:

4

Is there any way to safely include pages without putting them all in an array?

if (preg_match('/^[a-z0-9]+/', $_GET['page'])) {

$page = $_GET['page'].".php";
$tpl = $_GET['page'].".html";
if (file_exists($page)) include($page);
if (file_exists($tpl)) include($tpl);

}

What should I add to make this pretty safe?

I'm doing it this way bacause I don't like having to include stuff that has to be included on all pages. The "include header > content > include footer"-way. I don't wanna use any template engines/frameworks neither.

Thanks.

+5  A: 

The weakness in your current implementation is that …

  1. the regular expression just tests the beginning of the string, so “images/../../secret” would pass, and
  2. without further validation, “index” would also be a valid value and would cause a recursion.


To make your implementation safe, it’s a good practice to put everything, that’s intended to be included, in its own directory (e.g. “includes” and “templates”). Based on this, you just have to ensure that there is no way out of this directory.

if (preg_match('/^[a-z0-9]+$/', $_GET['page'])) {
    $page = realpath('includes/'.$_GET['page'].'.php');
    $tpl = realpath('templates/'.$_GET['page'].'.html');
    if ($page && $tpl) {
        include $page;
        include $tpl;
    } else {
        // log error!
    }
} else {
    // log error!
}

Note: realpath returns the absolute path to the given relative path if file exists and false otherwise. So file_exists is not necessary.

Gumbo
+4  A: 

Despite what you stated about not wanting to store a list of available pages in an array it is likely going to be the best, non-db, solution.

$availFiles = array('index.php', 'forum.php');
if(in_array($_GET['page'].".php", $availFiles))
 {
   //Good
 }
else
 {
   //Not Good
 }

You could easily build the array dynamicly with either DB queries or by reading a file, or even reading the contents of a directory and filtering out the things you don't want available.

Unkwntech
WOW I posted this answer and refreshed and you had posted a comment already.. that was quick.
Unkwntech
+1; reading directory contents and filtering out things is a good happy-medium
Rob
Reading directory contents and filtering out things would be a reason I would return your app to you to fix the implementation. If you have 100,000 users are you going to continually read the file permissions? Cache it if your going to be this lazy and generate glue code or something to handle it.
Syntax
I never said it was a good solution
Unkwntech
A: 

I agree with Unkwntech. This is such an insecure way to include files into your website, I wish PHP programmers would do away with it altogether. Even so, an array with all possible matches is certainly safer. However, You'll find that the MVC pattern works better and it is more secure. I'd download code igniter and take a tutorial or two, you'll love it for the same reason you wanna use dynamic includes.

Bretticus
+1  A: 

You should never use user supplied information for includes. You should always have some sort of request handler that does this for you. While a regular expression may filter somethings it will not filter everything.

If you do not want your site to get hacked you do not allow your users to control the flow of the application by designating an include.

Syntax