如何检测文件是否在目录树之外?

时间:2018-10-01 12:00:02

标签: php

我创建了一个基本页面,人们可以在该页面“注册”以上传/删除他们自己隔离文件夹中的文件。 文件的上传/删除是安全的,但是我也想允许管理员“拒绝”文件。

仅代码有效,除非有人将URL更改为服务器上的其他位置,否则他们可以“拒绝”系统上的任何文件,从而使文件面临风险。我希望创建一个系统功能,该功能可以检测目标文件是否在目录树中的任何位置。

这是我正在使用的代码,我想创建一个返回true / false的函数。

<?php
if(isset($_GET['deny'])) {
    $tree_start = "Uploads";
    $targeted_file = $_GET['deny'];
    $safe_to_delete = in_directory_tree($tree_start, $targeted_file); <-- Looking for this
    if( $safe_to_delete == false ) {die("This file does not exist in the directory tree");}
    rename($_GET['deny'], "./Uploads/@Denied/". basename($_GET['deny']) );
}
?>


我的目录树:

.htaccess <-- Prevent downloading of the database
admin.php <-- Problematic file browser script
index.php <-- User File management script
Users.db  <-- Names and hashed passwords

Uploads: 
  [FILE] htaccess <-- Prevent script execution (layer 2).
  [DIR] @Accepted: Notes.png, Video.mp4, etc...
  [DIR] @Denied: Project.png, new_timetable.txt, etc...
  [DIR] Admin: Proj1.txt, Proj1.png, etc...
  [DIR] User1: Task1.txt, Task2.txt, etc...
  [DIR] User2: Video1.txt, date.txt, etc...

2 个答案:

答案 0 :(得分:1)

尝试一下此代码:

    function in_directory_tree($dir,$file_to_search){

    $filesList = new RecursiveDirectoryIterator("uploads");
    $targetFile = "contact.php" ;
    foreach(new RecursiveIteratorIterator($filesList) as $file)
    {
        $contents = explode("\\",$file);
        if (in_array($targetFile, $contents))
            return true;
    }
    return false;
}

此代码将加载目录并开始递归搜索,如果到达末尾但没有找到文件,它将返回false,否则将返回true。 我使用了RecursiveDirectoryIterator,因为它可以帮助我们进入目录以列出它们

答案 1 :(得分:0)

我通过防止遍历路径而不是检查文件是否在此文件夹中来解决了此问题。该代码对我有用(仅当/ uploads中的文件存在时才返回true(并且使用C:/、../等返回块),并且仅当该文件存在时才返回true。这是完成的代码:< / p>

<?php

// Code used for the deny button:
// <button onclick="location.href='?deny=SmilerRyan/Project.png';">Deny</button>

if(isset($_GET['deny'])) {

$userpath = $_GET['deny'];
$basepath = 'Uploads/';
$realBase = realpath($basepath);
$userpath = $basepath . $userpath;
$realUserPath = realpath($userpath);
if ($realUserPath === false || strpos($realUserPath, $realBase) !== 0) {
    die("Invalid path - Possible Attack Blocked");
} else {
    rename($userpath, "./Uploads/@Denied/" . basename($userpath) );
}

}
?>