可以使用filesystem :: canonical来防止传递给fstream的文件路径注入文件路径

eze*_*ing 7 c++ std-filesystem

我有一个pub包含子文件夹和文件的公用文件夹。现在,用户给了我一个相对的文件路径,执行了一些映射,然后读取了文件fstream并将其返回给用户。

现在的问题是,如果用户../fileXY.txt考虑路径遍历或其他类型的文件路径注入,给我一个路径,例如或其他一些奇特的东西。fstream只会接受它并读取我的pub公用文件夹之外的潜在文件,甚至更糟的是给它们列出我系统中所有文件的列表,等等。

在重新发明轮子之前,我在文件系统库中进行了搜索,我发现这里有std :: filesystem :: canonical函数,并且已经有很多关于正常形式的讨论。我在这里有一个一般性的问题,可以使用此功能和变体std :: filesystem :: weakly_canonical来防止此类漏洞吗?那么基本上就足够了吗?

此外,我系统的文件系统库仍处于实验模式,并且std::filesystem::weakly_canonical缺少该文件系统。但是我不能使用,canonical因为文件必须存在于中canonical。就我而言,我具有某些映射,并且文件在这种意义上不存在。因此,我需要模仿该weakly_canonical功能,但是如何?

我已经在realpath上看到了有关不存在的路径的一个stackoverflow问题,建议他在路径存在的情况下重复规范,然后向其中添加不存在的部分,但这又容易受到这类注入的影响。那么我必须自己滚动weakly_canonical还是可以通过组合某些std::experimental::filesystem功能以某种方式模仿它?

A. *_* H. 1

简短的回答:不。

长答案这是根据 posix realpath建模的

我明白混乱的根源。来自真实路径

realpath() 函数应从 file_name 指向的路径名派生一个解析为同一目录条目的绝对路径名,其解析不涉及“.”、“..”

cppref 路径中您还可以看到双点已被删除。但是该路径仍然指向同一个文件。只是去掉了多余的元素。

如果您正在处理来自 db/webapp/无论您的程序与提供路径的用户具有不同权限的值,您需要首先通过转义双点来清理文件名。点子就好了

也许您可以使用正则表达式用反斜杠转义双点,从而使它们无效。

#include <iostream> 
#include <filesystem>
#include <string>
#include <regex>




int main() 
{ 
    
     std::string bad = "../bad/../other";
    std::filesystem::path p(bad);
    
    
    std::cout << std::filesystem::weakly_canonical(p) << std::endl;
    
   
    std::regex r(R"(\.\.)");
    p = std::regex_replace(bad, r, "\\.\\.");
    std::cout << std::filesystem::weakly_canonical(p) << std::endl;
    
}
Run Code Online (Sandbox Code Playgroud)

输出

“/tmp/其他”

“/tmp/1554895428.8689194/\.\./坏/\.\./其他”

运行样本