我正在用C++编写一个小型HTTP Web服务器,这是我爱好项目的一部分,我需要提供静态文件。但是,我想避免的一个问题是用户键入,例如http://example.com/../passwd。为了确保用户不会输入恶意路径,我想检查输入的路径是否在当前父目录中。我目前的方法是使用std::filesystem::directory_iterator,检查提供的文件是否是一个文件,以及它是否与提供的文件相同。但是,这非常缓慢和笨重,我相信有一个更好的解决方案。
http://example.com/../passwd
std::filesystem::directory_iterator
hjqgdpho1#
一个更好的解决方案是将用户指定的路径附加到所需的根路径,规范化结果,然后检查结果是否仍在根路径中。例如,当用户请求http://example.com/../passwd时,您的服务器将看到如下请求:
GET /../passwd HTTP/1.1
因此,只需将"../passwd"附加到根文件夹并比较结果,例如:
"../passwd"
#include <string> #include <filesystem> namespace fs = std::filesystem; bool isSubDir(fs::path p, fs::path root) { static const fs::path emptyPath; while (p != emptyPath) { if (fs::equivalent(p, root)) { return true; } p = p.parent_path(); } return false; } ... fs::path requestedPath = fs::path("../passwd").make_preferred(); fs::path parentPath = fs::path("C:\\webroot\\"); fs::path actualPath = fs::canonical(parentPath / requestedPath); if (isSubDir(actualPath, parentPath)) { // serve file at actualPath as needed... } else { // send error reply... }
1条答案
按热度按时间hjqgdpho1#
一个更好的解决方案是将用户指定的路径附加到所需的根路径,规范化结果,然后检查结果是否仍在根路径中。
例如,当用户请求
http://example.com/../passwd
时,您的服务器将看到如下请求:因此,只需将
"../passwd"
附加到根文件夹并比较结果,例如: