views:

164

answers:

4

How do I clean this so users can't pull pages outside of the local domain?

<?php
 if(!empty($_GET['page']))
 {
  include($_GET['page']);
 }
 else
 {
  include('home.php');
 }
?>
+12  A: 

The safest way is to whitelist your pages:

$page = 'home.php';

$allowedPages = array('one.php', 'two.php', ...);

if (!empty($_GET['page']) && in_array($_GET['page'], $allowedPages))
    $page = $_GET['page'];

include $page;
Greg
Thanks Greg. This workes great!!
Mike
+1  A: 

// get the absolute file name of the page we want to see
$page = realpath($_GET['page']);

// get the directory in which pages are
$mydir = dirname(__FILE__);

// see if the included page is inside this allowed dir
if ($page === false || substr($page, 0, strlen($mydir) != $mydir) {
 die('go away hacker');
} else {
 include $page;
}
Bart van Heukelom
Assuming there was no sensitive information in the "$mydir", this is how I'd probably do it too.
David Wolever
The best option is to parse the URI (<code>/some/page.html</code>) and use that to determine which file needs to be included (or function called, or class created, or whatever). However, that's not really an answer to this particular question.
Bart van Heukelom
A: 

This isn't tested. I just wrote it up real quick, but it should work (I hope) and it'll definitely provide you a base for where to get started.

define('DEFAULT_PAGE', 'home.php');
define('ALLOWED_PAGES_EXPRESSION', '^[\/]+\.php$|^[\/]+\.html$');

function ValidateRequestedPage($p)
{
    $errors_found = False;

        // Make sure this isn't someone trying to reference directories absolutely.
    if (preg_match('^\/.+$', $p))
    {
        $errors_found = True;
    }

        // Disable access to hidden files (IE, .htaccess), and parent directory.
    if (preg_match('^\..+$', $p))
    {
        $errors_found = True;
    }


        // This shouldn't be needed for secure servers, but test for remote includes just in case...
    if (preg_match('.+\:\/\/.+', $p))
    {
        $errors_found = True;
    }

    if (!preg_match(ALLOWED_PAGES_EXPRESSION, $p))
    {
        $errors_found = True;
    }

    return !$errors_found;
}

if (!isset($_GET['page'])) { $page = DEFAULT_PAGE; }
else { $page = $_GET['page']; }

if ( !ValidateRequestedPage($page) )
{
    /* This is called when an error has occured on the page check. You probably
       want to show a 404 here instead of returning False. */
    return False;
}

// This suggests that a valid page is being used.
require_once($page);
monokrome
A: 

Just use a switch statement.

Check if the $_GET var is set and then run it through the cases and have the default go to home.php

AntonioCS