arbme
arbme

Reputation: 4941

RegEx find "../" or "./"

I am trying to get regex to tell me if a path contains ./ or ../. This is to check a user doesn't look beyond their area. If the input contains a period before a forward slash it wont be accepted.

E.g.

/user/selected/path/ - Ok 
./user/selected/path/ - Failed 
../user/selected/path/ - Failed 

The forward slash will be replaced with DIRECTORY_SEPERATOR so works for unix and windows paths.

Upvotes: 0

Views: 134

Answers (4)

joseph.hainline
joseph.hainline

Reputation: 26658

$myString = "some/path";
if (preg_match('/(\.\.\/|\.\/)/', $myString)) { 
    echo "found ../ or ./ in path"; 
}

Upvotes: 0

Pekka
Pekka

Reputation: 449623

Checking for the existence of ".." is an imperfect solution to the problem.

If you want to prevent the user from breaking out of a base directory, check whether the realpath() result of the path (which will take into account relative paths) is still underneath the root path.

Example:

$root = "/my/user/basepath";
$requested_path = $_GET["input"]; // or whatever

$real_path = realpath($root."/".$requested_path);

if (strpos($real_path, $root) !== 0)
 die ("Illegal path");

Upvotes: 6

fred2
fred2

Reputation: 1110

I'd

a) recommend strpos for something this simple, not regex functions.

$usrPath = '../some/path/';
if (strpos($usrPath, '.' . DIRECTORY_SEPARATOR) !== false){
    die('oh no you don\'t');
}

b) Recommend making sure your server setup and filesystem permissions are set to prevent any chance of a user getting 'beyond their area', rather then programmatic methods.

Upvotes: 0

botzko
botzko

Reputation: 630

Use this

if (preg_match('#\.(\.)?/#', $path, $match)) echo "Error";

If you need to check for ../ or ./ only in the beginning you must use this

if (preg_match('#^\.(\.)?/#', $path, $match)) echo "Error";

Upvotes: 0

Related Questions