Search code examples
phprealpathdirectory-traversal

PHP realpath not working to prevent directory traversal


I have received someone else's code for a system that shows folders with photos in them in your browser.

For example, this is a possible url on the site:

gallery.php?action=view&folder=Cars

At the moment, you can replace "Cars" with ../../../../../, which will happily show the Linux root folder. Luckily, the website is offline at the moment.

I tried using realpath to fix this. Here's what I have so far:

case 'view' :
$name = realpath(dirname(__FILE__) . "/Content/Gallery/" . $_GET['folder']);

echo $name;

$data = $file->getPictures($name);
require 'Views/Gallery.view.php';
break;

I have added echo on the third line to see what the URL would be. In the url above, everything is fine, and echo outputs this:

/var/www/Content/Gallery/Cars 

So far, so good. However, if I enter /../../../../../../../../ instead of "Cars", $name becomes / and the page still shows the root folder. English isn't my first language, so I could be misunderstanding how realpath works or what it does. From what I understood, it removes any instance of ../ from a given URL.

Can someone please tell me what I'm doing wrong?


Solution

  • From what I understood, it removes any instance of ../ from a given URL.

    No, that's not what it does. It's not for URLs, it's for paths. It simply converts a path and expands ../ into the right folder. It doesn't remove them, it resolves them - meaning it calculates what the ../ stands for and alters the path to have that.

    It also changes / to \ on Windows.

    realpath

    realpath() expands all symbolic links and resolves references to '/./', '/../' and extra '/' characters in the input path and returns the canonicalized absolute pathname.