Jump to content

[SOLVED] Directory traversal and path concatenation


Checksum

Recommended Posts

Hey guys! I'm working on a simple download script. The script has two files : index.php to list the files and traverse directories, download.php to download. I'm having problems traversing the directories and setting the pathnames.

 

1. For directories to be displayed, i send the path through index.php?path=./songs/sample.mp3.

 

2. For download links, i send the path through download.php?fname=./songs/sample.mp3.

 

Now i need a way to maintain the current path, starting from the root directory. For example if I have to download ./songs/pop/song1.mp3, I have to set the path as ./songs/pop/ and then append song1.mp3 to the filename. So basically the path of the file starting from the root of the script should be displayed. How can i do that?

 

Also, if i have to go back to the previous directory, how should i generate the link?

 

Thank you.

 

I have a suggestion.  You could be really cool and display the whole directory structure on one page, that way you could avoid passing directory paths through GET variables.

 

Here is an example of a nice function that will scan a full directory structure and store it in an array:

http://lixlpixel.org/recursive_function/php/recursive_directory_scan/

 

And then you could use something like this (untested!) to display the directory structure on one page:

<?php
function create_nested_list($items) {
$out = '<ul>';
foreach ($items as $item) {
	$out .= '<li>';
	if ($item['kind'] == 'directory') {
		$out .= $item['name'];
		if ($item['content']) {
			$out .= $this->__create_nested_list($item['content']);
		}
	} else {
		$out .= $item['name'];
	}
	$out .= "</li>";
}
$out .= "</ul>";
return $out;
}
?>

Thanks a lot :) That was real helpful! Displaying all the directories would be a good idea in the end. I also found a useful script http://www.alistapart.com/articles/complexdynamiclists to generate the lists like a osx finder list. Might be useful for others looking for a similar thing.

 

One thing though. Supposing i pass the path to the file directly like download.php?./songs/song1.mp3, how can i validate that users don't pass something like ../../index.php to access the root of the website?

 

 

Maybe you could feed the path name to something like realpath() (http://us2.php.net/realpath), and then check to make sure that it is within the allowed directory.  So say your allowed download path is this:

 

/allowed/download/path/files/

 

and you get passed a filepath like this:

 

../../../rofl.jpg

 

You could take the realpath() of '../../../rofl.jpg' and check to make sure that '/allowed/download/path/files/' is a substring of it.

 

This is completely untested, im just making this up, but maybe something like this:

 

<?php
$allowed_path = '/allowed/download/path/files/';
$file_to_download = '../../../rofl.jpg';
if (strpos(realpath($file_to_download)) !== false) {
    // then the file_to_download must be in the correct path.
} else {
    // tricksy haxing
}
?>

 

Does that make sense?

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.