TalkPHP
 
 
Account Login
Latest Articles
» The basic usage of PHPTAL, a XML/XHTML template library for PHP
» Vulnerable methods and the areas they are commonly trusted in.
» Simple way to protect a form from bot
» The Basics On: How Session Stealing Works
» How to keep your forms from double posting data
IRC Channel
IRC Speech Bubble Join the friendly bunch on IRC...
(#TalkPHP on Freenode)

...Also available via a web interface.

See this thread for information on the TalkPHP Free Hugs Initiative™. Subject to availability.
Associates
Associates
CSS Tutorials
Reply
 
LinkBack Thread Tools Search this Thread Display Modes
Old 03-13-2008, 08:27 PM   #1 (permalink)
The Wanderer
 
Join Date: Nov 2007
Posts: 9
Thanks: 1
solistus is on a distinguished road
Arrow Can an included file 'know' where it's been included?

Hey all,

I have a fairly straightforward problem. I work for a University's IT department. Long story short, we have a lot of PHP content providers who don't know what they're doing and have had several major security breaches due to bad file uploading code. We want to write a function as an include to handle all uses of move_uploaded_file with proper data sanitisation and security measures.

Due to the way we distribute authority/responsibility for content at the University, we need our code to know where it is being called from so we can look up directory permissions and match them to the target directory. We need a foolproof way of determining where the function is being included from.

I tried wrapping the function in an object with a constructor that remembers the value of PHP_SELF, but that returned an empty string.

So, to wrap it up: is there any way to get the path to the including page in the code on the included one? Sadly, we are stuck with PHP 4.4.0 for now, so PHP5-only solutions won't do the trick (if the only way to do it is with PHP5, that would still be quite valuable to know).

I apologise if this is not really an 'advanced' question, but a lot of time on PHP.net yielded nothing and I figure the readers of this board have the best chance of knowing some obscure trick.
solistus is offline  
Reply With Quote
Old 03-13-2008, 08:55 PM   #2 (permalink)
La Vida es Sueño
Advanced Programmer Top Contributor 
 
Wildhoney's Avatar
 
Join Date: Sep 2007
Location: Oldham
Posts: 2,280
Thanks: 90
Wildhoney is on a distinguished road
Default

So just to clarify, what you're asking of is to interrupt the call to the function move_uploaded_files, and to essentially call another function prior to calling move_uploaded_files -- and then passing that sanitised data to move_uploaded_files?

Edit: There is $_SERVER['REQUEST_URI'], but that merely gets the root file that's being accessed, it's not the magical item you're looking for that knows the included file's parent.
__________________
The man who comes back through the Door in the Wall will never be quite the same as the man who went out.
Send a message via AIM to Wildhoney Send a message via MSN to Wildhoney Send a message via Yahoo to Wildhoney
Wildhoney is offline  
Reply With Quote
Old 03-13-2008, 09:10 PM   #3 (permalink)
La Vida es Sueño
Advanced Programmer Top Contributor 
 
Wildhoney's Avatar
 
Join Date: Sep 2007
Location: Oldham
Posts: 2,280
Thanks: 90
Wildhoney is on a distinguished road
Default

I'll make this as a new post, but I think I've cracked it, if I understand your question correctly -- which I think I do now. It will also work when includes have been daisy-chained.

php Code:
function getIncludedParent()
{
    $aIncluded = get_included_files();
    $iKey = array_search(__FILE__, $aIncluded);
   
    if(!array_key_exists($iKey - 1, $aIncluded))
    {
        return __FILE__;
    }
   
    return $aIncluded[$iKey - 1];
}

echo 'Included parent: ' . getIncludedParent();
__________________
The man who comes back through the Door in the Wall will never be quite the same as the man who went out.
Send a message via AIM to Wildhoney Send a message via MSN to Wildhoney Send a message via Yahoo to Wildhoney
Wildhoney is offline  
Reply With Quote
The Following 2 Users Say Thank You to Wildhoney For This Useful Post:
ReSpawN (03-13-2008), solistus (03-13-2008)
Old 03-13-2008, 09:55 PM   #4 (permalink)
The Wanderer
 
Join Date: Nov 2007
Posts: 9
Thanks: 1
solistus is on a distinguished road
Arrow

I set up a test of your code: a main page with nothing but require()s, and a bunch of includes, one of which with your code verbatim and the others all empty. When I only had the include with your code required by the parent, the code worked, but when I threw a bunch of empty includes before and after the 'real' include, it started reporting paths to other includes and not the real parent.

Based on my limited understanding of what your code does, it looks like the problem is this line:

PHP Code:
return $aIncluded[$iKey 1]; 

My test setup right now looks like this (the common portion of the test files' path was replaced here with $path; it's a literal string in the actual code):

main page (the one being requested via http):

PHP Code:
<?php

require_once("$path/aa/b.php");

require_once(
"$path/aa/bb.php");

require_once(
"$path/aa/a.php");

require_once(
"$path/aa/bbb.php");


?>
b.php, bb.php and bbb.php are all identical:

PHP Code:
<?php

//nothing to see here...

?>
a.php is a copy-paste of your code.

The result: Included parent: $path/aa/bb.php




It seems like this should be a recursive call somehow, but I'm not sure how to make it work. I tried this on a whim, but it failed as well:

PHP Code:
function getIncludedParent($offset 0)
{
    
$aIncluded get_included_files();
    
$iKey array_search(__FILE__$aIncluded);
    
    if(!
array_key_exists($iKey - ($offset), $aIncluded))
    {
        return 
__FILE__;
    }
    
    return 
getIncludedParent($offset 1);
}

echo 
'Included parent: ' getIncludedParent(); 
If I move around the requires, your code consistently returns the require immediately before the one with the code in it, unless it's first in which case it returns the correct parent.

I did a little playing around, and it seems like the parent is always at index 0. Are there cases in which this would not be the case? I don't have time right now to try anything too complex, but adding/moving/removing things seemed to have no effect. The include running the code always sees itself as last. It looks like it stores the files in the order they are called, so first the parent, then the first include, then that include's first include, etc. If this is the case, can't I just do something like:

PHP Code:
$x get_included_files();
$parent $x[0]; 
I assume there's a reason this wouldn't always work, which is why you tried a more complex method, but might it be easier to check for those exceptions and use this method in all other cases? You can't get much more efficient than that (unless you can somehow eliminate the get_included_files call, of course, but that seems to be the function that makes any of this even possible...).

Oh, by the way, in case anyone is still unclear: we're not trying to interrupt calls to move_uploaded_file. We've blocked uploads of PHP containing that function using RATS and our own deployment software; instead, we plan to provide an include that our content providers can call instead. It will basically provide a secure wrapper for move_uploaded_file; it will perform all the security checks on the data that we feel are necessary, since we don't trust many of our content providers to write secure PHP. We also want to be able to monitor and control uploads more tightly as issues arise in the future, so routing them all through a piece of code we control would be quite handy.
solistus is offline  
Reply With Quote
Reply



Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On


All times are GMT. The time now is 12:25 PM.

 
     

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2013, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.1.0
Inactive Reminders By Icora Web Design