0

I would like to know if there is a possible way to stop people create sub folders 4 deep

Question how to make it so that whe user wants to create a sub folder 4 deep it will not let that user. I only want it so can create 3 deep sub folder.

Example for $this->input->get('directory') catalog/home/view

public function folder()
{
    $json = array();

    if ($this->input->get('directory') != '') {

        $directory = FCPATH . 'images/'. $this->input->get('directory') . '/';

        @mkdir($directory . $this->input->post('folder'), 0777, true);

        $json['success'] = true;

    } else {

        $directory = FCPATH . 'images/catalog/';

        @mkdir($directory . $this->input->post('folder'), 0777, true);

        $json['success'] = true;
    }

    $this->output->set_content_type('Content-Type: application/json');
    $this->output->set_output(json_encode($json));
}
Mr. ED
  • 11,163
  • 10
  • 51
  • 114
  • 2
    Count the amount of slashes? Only allow two. You should also read about [Preventing Directory Traversal in PHP but allowing paths](https://stackoverflow.com/questions/4205141/preventing-directory-traversal-in-php-but-allowing-paths). You should also stop suppressing errors with @. Handle the errors correctly instead. – Magnus Eriksson Apr 01 '18 at 07:32
  • 1
    IMHO - Really don't like the idea of using `@mkdir()` and then just saying `$json['success'] = true;`. – Nigel Ren Apr 01 '18 at 07:36
  • @NigelRen Do you think a `if statment` for mkdir would be better? – Mr. ED Apr 01 '18 at 07:37
  • 2
    My primary concern would be security if you give control to the user. Imagine what happens when you enter `../../../../`. Maybe it would be better to only allow entering up to four directory names in the UI (without directory separators) and build the path yourself? At least filter all occurences of `./` and `../`. – Namoshek Apr 01 '18 at 07:38
  • If you can think better way then would be great for some examples. – Mr. ED Apr 01 '18 at 07:40
  • Did you read the most up voted answer in the link I posted? (regarding the security)? – Magnus Eriksson Apr 01 '18 at 07:42
  • How do they make the folders? eg. FTP, sFTP ? You can write a cron job, that runs every minute and deletes the folder if they make one that deep.... :). Soon they will learn not to. otherwise if it's a web interface in PHP that should be no issue. – ArtisticPhoenix Apr 01 '18 at 07:47
  • @ArtisticPhoenix that doesn't sound like a solution - rather a bandaid. And it looks like they are making the folders with a php script via web interface (as seen in the question code). – Alex Apr 01 '18 at 07:55
  • is it possible that the user just provides "an array" of sorts so that you can build the path yourself. e.g. user provides dir1,dir2,dir3. and you just build it via fcpath . DS . dir1 .DS .dir2 ... etc. – Alex Apr 01 '18 at 07:58
  • @Alex -personally I wouldn't let them create folders through an interface, if they want organization it can be emulated in the database, or in a zip file. I was thinking more the lines of FTP, we don't let even our FTP users create folders in there home directory, if they create subfolders (they have a few folders to put stuff in) they get deleted after 10 days with any files that are 10 days old. That was what I was thinking about. Because in that case, they must have write access to the folders or they cant save files. – ArtisticPhoenix Apr 01 '18 at 08:07
  • yea i guess it would helpful to know the purpose of this script – Alex Apr 01 '18 at 08:13

1 Answers1

2

The first thing which comes to mind is

Why do you even allow users to create folders ?
If anyone finds out what you are doing here and understands the procedure - its very possible that you can get flooded (suddenly you have thousands of folders here...)

But if this isn't your concern, imho you are facing here a very difficult problem which isn't trivial at all, because you've to do so many checks

i can give you a start - but be aware this isn't all... if you really set this to a productive state, the only debugging way is the result ;)

Check if the directory you get is a valid one. For this matter i took the function from here, removed the / and added a . (in this case it will prevented that anyone steps out of your root directory)

The code below is a snippet but it should be clear what i intend and can easily be extended...

try
{
    $strBaseDirectory = FCPATH . 'images/';
    $strUserDirectory = $this->input->get('directory');

    if (empty($strUserDirectory) || strpbrk($strUserDirectory, "\\.?%*:|\"<>"))    throw new InvalidArgumentException('Invalid directory');
    $strUserDirectory = trim($strUserDirectory, '/');
    $arrPathParts = explode('/', $strUserDirectory);

    if (count($arrPathParts) > 3)   throw new InvalidArgumentException('To much folders...');

    $arrPathParts = array_map(function($item)    {
        return trim($item);
    }, $arrPathParts);

    $key = array_search('', $arrPathParts);

    if ($key)   throw new InvalidArgumentException('One or more Foldername(s) contain only spaces...');

    echo '<pre>';
    print_r($arrPathParts);

    $strUserDirectory = implode('/', $arrPathParts);

    $blnDirectoryCreated = mkdir($strBaseDirectory.$strUserDirectory);

    $arrJson = [
        'success'   => $blnDirectoryCreated,
        'message'   => 'whatever...'
    ];

}
catch (Exception $e)
{
    $arrJson = [
        'success'   => false,
        'message'   => $e->getMessage()
    ];
}

$this->output->set_content_type('Content-Type: application/json');
$this->output->set_output(json_encode($arrJson));
sintakonte
  • 5,124
  • 5
  • 18
  • 34