views:

141

answers:

5
+2  Q: 

File Exists Safe?

if (file_exists("pages/$page.php")) {
  include($page.'.php');
}

Is this safe?

With Safe i mean that you cant include remote scripts etc

+2  A: 

The code you posted has a typo i believe. It should be:

if (file_exists("pages/$page.php")) {
  include("pages/$page.php");
}

It however leads to code injection, if PHP settings allow it, remote file inclusion.

You need to make sure the page that you include can not be any arbitrary page.

Usually you'll see this type of code in a "Loader" class employing the Factory Method, however, in good implementations it restricts the files and classes it will load to a certain directory, or to a certain predefined set of files.

bucabay
I am interested in what values of `$page` would lead to remote file inclusion. If you didn't have `'pages/'` at the beginning then you could maybe inject '../' but otherwise I don't see how it's dangerous.
DisgruntledGoat
`../` can still be injected with `pages/` at the beginning: `pages/../../../../path/to/important/file`.
ceejayoz
You can include any file on the file system readable by the PHP process and thus pretty much have all access the PHP process has, including it's ability to make a HTTP request to a remote site for some worm or worse.
bucabay
Everything the web server writes to becomes a target since you now have the ability to read it from PHP. Log files, uploads, caches, database files, all take user input, directly and indirectly.
bucabay
+6  A: 

Certainly not, especially if $page = "./configuration"

I would recommend replacing it with something like this:

$pages = array("blog", "home", "login");
if (in_array(strtolower($page), $pages))
  include("pages/$page.php");

EDIT: You can generate that list of acceptable pages with this code.

$pages = array();
if ($dh = opendir("pages")) {
  while (($file = readdir($dh)) !== false) {
    if (strstr($file, ".php") !== false) // make sure it is a .php file
      $pages[] = substr($file, -4); // remove the .php
  }
  closedir($dh);
}
St. John Johnson
is there a way not to have to add all pages to an array?
The point is, you want to list your pages in the array. So you can limit what you can access. Let me give you some alternate code.
St. John Johnson
if you want to be safe, then **no**
knittl
+1  A: 

If $page is never set, PHP will then try to find what it could be following the variables_order directive inside your php.ini. This directive tells PHP the order in which to find variables. Since the default for this is EGPCS, a cunning hacker then then call your script and tell it to include any file that PHP has access too.

Ex:

www.example.com/?page=dbConfig.ini

MANCHUCK
+1  A: 

Storing all possible page names in an array is the safest approach, but you can also be reasonably safe by simply validating the supplied page name and ensuring that you don't have any "dangerous" files in your pages directory.

$page = basename($_GET['page']);
if (file_exists("pages/$page")) {
  include("pages/$page");
} else {
  include("pages/default.php");
}
pix0r
+1  A: 

Use basename($_REQUEST['page']) to prevent potential access to other directories then check if it exists.

http://php.mirror.facebook.net/manual/en/function.basename.php

netrox