Home > front end >  How to disable Path Traversal Attack on Laravel
How to disable Path Traversal Attack on Laravel

Time:03-05

I have a laravel web that serve some file for authenticated user only but somehow hacker can get my .env file by Path Traversal. Here is my route under middleware auth group

Route::get('storage/{filename?}/download/',function($filename){        
    $basepath = storage_path($filename);
    $path = realpath($basepath);
    try {
        if ($path !== false && substr($path, 0, strlen($basepath)) == $basepath){
            $response = response()->download($path);
            return $response;
        }
        
    } catch (\Throwable $err) {
        abort(404);
    }
})->where('filename','(.*)');
Route::get('storage/{filename?}',function($filename){  
    $basepath = storage_path($filename);
    $path = realpath($basepath);
    try {
        if ($path !== false && substr($path, 0, strlen($basepath)) == $basepath){
            $response = response()->file($path);
            return $response;
        }
        
    } catch (\Throwable $err) {
        abort(404);
    }
})->where('filename','(.*)');

I write this route after reading an article from here but I dont know how to test if my app is free from path traversal attack. Is it enough only configuring my route like this or any additional setting? the only accessible storage is storage/app/files

CodePudding user response:

This is still not safe. example:

Psy Shell v0.10.8 (PHP 7.4.27 — cli) by Justin Hileman
>>> $basepath = storage_path('../.env');
=> "/usr/local/var/www/site-example/storage/../.env"
>>> $path = realpath($basepath);
=> "/usr/local/var/www/site-example/.env"

Just follow the guide you mentioned. basename will strip the directories attached.

Psy Shell v0.10.8 (PHP 7.4.27 — cli) by Justin Hileman
>>> $fileName = basename('../.env');
=> ".env"
>>> $basepath = storage_path($fileName);
=> "/usr/local/var/www/site-example/storage/.env"
>>> $path = realpath($basepath);
=> false
>>>

false is returned if the file does not exist in the storage dir.

>> $fileName = basename('../.env');
=> ".env"
>>> $basepath = storage_path($fileName);
=> "/usr/local/var/www/example-site/storage/.env"
>>> $path = realpath($basepath);
=> false
>>> $fileName = basename('../test-file.pdf');
=> "test-file.pdf"
>>> $basepath = storage_path($fileName);
=> "/usr/local/var/www/example-site/storage/test-file.pdf"
>>> $path = realpath($basepath);
=> "/usr/local/var/www/example-site/storage/test-file.pdf"
>>>

CodePudding user response:

You can do a path check against storage path to avoid path traversal attacks after finding realpath of the requested file:

Like:

$fileName = "../.env";
$filePath = realpath(storage_path($fileName));
$storagePath = storage_path();

if (!$filePath) {
    abort(404, "Not Found");
}

if (strpos($filePath, $storagePath) !== 0) {
    abort(403, "Forbidden");
}
  • Related