如何在std::experimental::filesystem中限制用户仅在指定目录操作
如何防止路径遍历攻击,限制用户仅在指定目录创建文件
这是个典型的路径遍历攻击风险问题——用户通过输入包含../的相对路径,就能轻松突破你设定的工作目录限制,访问系统其他敏感目录。别担心,我们可以通过路径规范化和范围校验来彻底解决这个问题。
核心思路
要确保最终生成的文件路径完全被限制在你指定的工作目录之下,不能跳出这个范围。具体分两步:
- 把用户输入的路径转换为规范化的绝对路径,消除所有
../、.和符号链接,得到真实的文件系统路径。 - 校验这个规范化路径是否以工作目录的绝对路径为前缀,以此判断是否越权。
代码实现示例
结合你使用的std::experimental::filesystem,可以这么写:
namespace fs = std::experimental::filesystem; // 先把工作目录转换为绝对路径,避免相对路径带来的校验问题 fs::path working_path = fs::absolute(fs::path(getenv("HOME")) / "work"); // 处理用户传入的文件名 fs::path user_input_path = working_path / file_name; // 使用weakly_canonical处理(适合创建新文件的场景,允许路径中存在未创建的子目录) fs::path normalized_path = fs::weakly_canonical(user_input_path); // 先确保工作目录存在,避免后续校验出错 if (!fs::is_directory(working_path)) { std::cerr << "Working directory does not exist!" << std::endl; return; } // 检查规范化后的路径是否以工作目录为前缀 if (normalized_path.string().compare(0, working_path.string().size(), working_path.string()) != 0) { // 路径越权,拒绝操作 std::cerr << "Error: Access to paths outside the working directory is forbidden." << std::endl; return; } // 验证通过,安全创建文件 std::ofstream target_file(normalized_path); if (target_file.is_open()) { // 写入内容逻辑 target_file << "Content to write..." << std::endl; target_file.close(); } else { std::cerr << "Failed to create file!" << std::endl; }
关键细节说明
fs::weakly_canonicalvsfs::canonical:如果是创建新文件,推荐用weakly_canonical——它能处理路径中不存在的目录;而fs::canonical要求路径上的所有目录都必须存在,更适合校验已有文件的场景。- 绝对路径校验:一定要先把工作目录转为绝对路径,否则用相对路径做前缀对比会出现逻辑错误。
- 永远不要信任用户输入:哪怕用户输入的看起来是普通文件名,也要经过规范化和校验,避免隐藏的路径遍历风险。
内容的提问来源于stack exchange,提问作者Reudi
相关产品推荐
相关产品推荐

