Jump to content

Path traversal vulnerability


jdock1

Recommended Posts


When I first started the code on my application a few years ago, I was still starting out and didnt realize how dumb it was to use this.

 

I wanted my site to display pages dynamically through index.php (like index.php?page=help or index.php?page=contact)

 

So I used this code

 

if (isset($_GET['page']))
	{
		include_once($_GET['

.".php");
	}
	else
		include_once("home.php");
	include_once("footer.php");

 

So for any php file I have on my webserver, I can call it through index.php. For example, if I had uploaded news.php, I could view it through http://mysite/index.php?page=news

 

I realized this huge security flaw a while ago, but continued work anyway thinking it would be an easy fix, but nothing ive tried is working and I cant find any help online.

 

Anyway, I need to use this. I have over 100 pages coded up already. The index.php page has important functions & other code as well as all of the css. All the other php files that need to be viewed through index.php is not relative to any of the css and include files. In other words, I would have to edit every single file to include code from index.php to that file.

 

This is a very serious security flaw. I did alot of tests and its very vulnerable, I can access the admin side of the application and even secret server files using path traversal hacks (../../) etc.

 

How can I fix this? So if someone were to enter a non existent php page, (mysite.com/index.php?page=nonexistent) it would redirect them elsewhere so they don't see the php error messages , and most importantly, disallow them from viewing any other page such as secret admin files (mysite.com/index.php?page=/admin/includes/functions.php) ?

 

 

The best way to do this for me would probably be by setting up allowed pages, and if someone goes to a URL that is not on the allowed list, display a 404 or redirect them elsewhere. Is this possible?

 

 

Please help! I did my research, I can't find anything that helps me out. I am extremely upset idk what to do. I really want to cry because I cant fix it! I put so much time and work into this application.

 

If I cant fix this, years of hard coding went to waste. I would never release this application to the public with such security flaws. After I get this fixed, im going to consult with a security specialist to try anything they can to hack it & secure it. I do not have the money for it at this time though, otherwise I would just hire them to fix this for me.

 

Thank you!!!! I really appreciate & respect any replies!

Link to comment
Share on other sites

Off the top of my head I came up with this.

Not sure if you use uppercase for pages or not.

 

$page = preg_replace('/[^-a-zA-Z0-9_]/', '', $_GET['page']);//allow these characters
$allowed_pages = array("news", "about", "contact", "links");//add allowed pages
if (in_array($page, $allowed_pages) && isset($_GET['page']) && !empty($_GET['page'])) {
    include_once($page.".php");
} else {
   header("HTTP/1.0 404 Not Found");
   die('Page not found.');
}

Link to comment
Share on other sites

All external data that your script receives - post, get, cookie, files, and some server variables - can contain anything and cannot be trusted. The solution is to validate/filter the data so that your code only uses the data if it has an expected value.

 

You also have a possible problem with what you are doing if your server allows URL's to be using in include statements because a hacker can supply a URL to his site on the end of your URL that will cause his php code to be included into your script and executed on your server.

 

For what you are doing, you would validate that the supplied value is a page name that your script allows to be included and the current visitor has permission to access and only execute the include statement when the page exists and is permitted for the current visitor.

 

The simplest way to do this is if you have (an array statement) or get (using glob, which would be easiest if the files to be include were all in a specific folder - you would also prevent all http requests to the files to be included) an array with the permitted file names -

 

<?php
$includes = array('news.php','help.php','contact.php'); // a list of the permitted include files that this index.php file may include. You could also build this array from a glob() statement executed against a specific folder holding the include files
$page = isset($_GET['page']) ? strtolower($_GET['page']) . '.php' : '';
if(in_array($page,$includes)){
include_once('./' . $page); // the leading './' prevents php from searching the include path to find and include the file
} else {
include_once("home.php");
}
?>

 

By testing for specific file names, you prevent directory transversal since anything other than the file name won't match an entry in the array. Also, the main index.php file cannot include any of the admin include files because only files accessible through the path you build (currently no path in the code) can be accessed.

Link to comment
Share on other sites

Wow guys thank you so much. I havent tested it yet but it looks like it will work. See, I belive I would still be considered a "novice" php programmer to the PHP world, but I can do almost anything with php and build pretty complex dynamic applications, but im still at the point where I cant think of solutions to anything, but when I see an example I can build from it and make use of it. I can definitely make this work.

 

I really appreciate the replies!

 

Still definitely open to more suggestions, theres no such thing as being to secure

Link to comment
Share on other sites

Ok now I have another question. I have to require users to view pages through index.php.

 

Otherwise, if they figure it out & go to the default page (for example, index.php?page=news, they would go to mysite.com/news.php) it displays the page, a very messed up version of the page (filesare not literal & defined in index.php). I cannot allow users to go to the default php file.

 

How can I restirct this!? I cant believe I didint even think of this either, its just as important!

 

Thank you! Respect.

Link to comment
Share on other sites

The easiest way would be to put the included files into a folder that is either outside your document root folder (closer to the disk root) or if that option is not available to you, put a .htaccess file in the folder that prevents all http requests to the files in the folder.

Link to comment
Share on other sites

The easiest way would be to put the included files into a folder that is either outside your document root folder (closer to the disk root) or if that option is not available to you, put a .htaccess file in the folder that prevents all http requests to the files in the folder.

 

Oh yeah that would work lol see I cant believe I didn't think of that.

 

 

Thanks for the suggestion, will look into it definitely.

If you have 100 or so unique pages coded up, you should probably use a more robust system than a page controller.  Look into MVC frameworks and how their routing systems work

Link to comment
Share on other sites

 

 

 

The easiest way would be to put the included files into a folder that is either outside your document root folder (closer to the disk root) or if that option is not available to you, put a .htaccess file in the folder that prevents all http requests to the files in the folder.

 

 

Ok, now im trying to include files from another directory, but its not finding the files. Please see my code:

 

$includes = array('login.php','/controller/register.php','abc.php','admin/inc/links.php','admin/inc/gFunctions.php'); // a list of the permitted include files that this index.php file may include. You could also build this array from a glob() statement executed against a specific folder holding the include files

 

$page = isset($_GET['page']) ? strtolower($_GET['page']) . '.php' : '';

if(in_array($a,$includes)){

 

include_once('./' . $page); // the leading './' prevents php from searching the include path to find and include the file

 

}

else {

include_once("home.php");

 

}

In this test, I made a folder "controller" to put the include files in. I put register.php in the controller directory. When I went to the URL, it didnt do anything, acting like it couldnt find it.

 

How could I set it up so I can put the include files into another folder & put them in an array to view them from the index page? Sorry for my stupidity, I code alot and sometimes after so long I just get a block.

 

 

Also, I have includes in other pages, such as for example register.php. Once I started to use that code, I was getting errors when trying to register. It doesnt seem that it is including the files for register.php, or any page for that matter. Thats why in the code above you see "admin/inc/gFunctions.php", etc. I figured I just have to include them from the index file. Im sure thats all I have to do, but I just need to know how to include to another folder on my server.

 

 

Thank you so much for all your help! I really appreciate it. I hope you understand what Im trying to do. I am terrible at words and explaining my coding controversies!

 

Link to comment
Share on other sites

One of the points of putting the included/required files into a folder is that all of them (for any specific index.php page) would be put into the folder and you would have or build the path to the folder in your php code. The $_GET value would still be just the name portion of the file you you want to include. Your php code would take the name and build the complete -

./some_path/name.php to specify the file to be included.

 

To do this with a folder of files -

<?php
$path = './controller/'; // path to permitted include files (leading ./ prevents php from searching the include path to find and include the file)
$includes = glob($path . '*.*'); // get a list of permitted include files
$page = isset($_GET['page']) ? strtolower($_GET['page']) . '.php' : '';
$file = $path . $page;
if(in_array($file,$includes)){
include_once($file);
} else {
include_once($path . "home.php"); // assuming that your home.php file is in the folder as well
}
?>

Link to comment
Share on other sites

One of the points of putting the included/required files into a folder is that all of them (for any specific index.php page) would be put into the folder and you would have or build the path to the folder in your php code. The $_GET value would still be just the name portion of the file you you want to include. Your php code would take the name and build the complete -

./some_path/name.php to specify the file to be included.

 

To do this with a folder of files -

<?php
$path = './controller/'; // path to permitted include files (leading ./ prevents php from searching the include path to find and include the file)
$includes = glob($path . '*.*'); // get a list of permitted include files
$page = isset($_GET['page']) ? strtolower($_GET['page']) . '.php' : '';
$file = $path . $page;
if(in_array($file,$includes)){
include_once($file);
} else {
include_once($path . "home.php"); // assuming that your home.php file is in the folder as well
}
?>

 

Omg wow I am so dumb. Thank you so much for clearing that up for me! I swear if I would just stop and think a little longer my post count on this site would be cut in more than half!

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • 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.