c++怎么防止恶意用户输入包含../的路径遍历攻击_lexically_normal【避坑】

风杰姑娘_1564

风杰姑娘_1564

2026-04-04

345人浏览

原创

std::filesystem::lexically_normal() 不能防止路径遍历攻击,它仅做词法归一化、不访问文件系统、不验证存在性或权限,无法阻止如 ../../../etc/passwd 的恶意路径。

c++怎么防止恶意用户输入包含../的路径遍历攻击_lexically_normal【避坑】

用 std::filesystem::path::lexically_normal() 不能防路径遍历

直接说结论:std::filesystem::lexically_normal() 只做词法归一化,不验证路径是否存在、也不检查权限,完全无法阻止 ../ 攻击。它只是把 a/../b 变成 b,但前提是输入是合法路径字符串——而恶意用户传 ../../../etc/passwd,它照样给你归一成 /etc/passwd,毫无防护作用。

常见错误现象:代码里写了 p.lexically_normal() 就以为安全了,结果 Web 服务或配置加载器仍能被读取任意文件。

  • lexically_normal() 不访问文件系统,纯字符串处理
  • 它不区分相对路径和绝对路径,../../secret.txt 归一后仍是相对路径(除非你提前 resolve)
  • 它不校验路径是否在允许根目录之下——这才是防护核心

真正有效的做法:白名单根目录 + std::filesystem::canonical() 或 std::filesystem::weakly_canonical()

必须先限定允许访问的根目录(如 /var/www/uploads),再将用户输入路径与之拼接,最后用 canonical() 解析真实路径并检查是否仍在根内。

关键点在于:canonical() 会实际访问文件系统,解析符号链接、处理 ..,返回绝对且唯一的路径;如果目标不存在,会抛 std::filesystem::filesystem_error,这反而是好事——可直接拒绝。

  • 用 std::filesystem::path base_dir = "/var/www/uploads"; 明确声明可信根
  • 拼接后立即调用 std::filesystem::canonical(user_path)(不是 lexically_normal)
  • 检查结果路径是否以 base_dir 开头:real_path.string().starts_with(base_dir.string())
  • 若用户路径指向不存在的位置,canonical() 抛异常,捕获后拒绝即可

示例片段:

C++14
C++14

C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。

下载
std::filesystem::path base_dir{"/var/www/uploads"};
std::filesystem::path user_input{"../../etc/shadow"}; // 恶意输入
auto full_path = base_dir / user_input;

try {
    auto real_path = std::filesystem::canonical(full_path);
    if (real_path.string().starts_with(base_dir.string())) {
        // 安全,可打开
    } else {
        throw std::runtime_error("Path escape detected");
    }
} catch (const std::filesystem::filesystem_error&) {
    throw std::runtime_error("Invalid or inaccessible path");
}

注意 weakly_canonical() 的适用场景和风险

当你要处理的路径可能最终不存在(比如创建新文件前校验父目录),canonical() 会失败,这时可用 weakly_canonical() ——它只解析存在的部分,对末尾不存在的组件保留原样。

但它有坑:如果恶意路径中存在一个**真实存在的中间目录**(如 ../../tmp/existing_dir/../../../etc),weakly_canonical() 可能只归一到 /tmp/existing_dir/../../../etc,后面仍含 ..,导致后续判断失效。

  • 仅在明确需要支持“路径末尾不存在”时才用 weakly_canonical()
  • 用它之后,仍需手动展开剩余的 ..(比如再套一层 lexically_normal()),但必须配合严格前缀检查
  • 更稳妥的做法是:先 weakly_canonical(),再对结果调用 lexically_normal(),最后比对是否在根下——但依然要确保根是绝对路径且无符号链接绕过

容易被忽略的底层细节:符号链接与挂载点

即使做了 canonical() + 前缀检查,如果根目录本身是符号链接(如 /var/www/uploads → /mnt/nfs/uploads),攻击者可能利用跨文件系统符号链接逃逸。Linux 下 canonical() 默认不跟随挂载点外的符号链接,但行为依赖 OS 和挂载选项。

  • 生产环境应确保 base_dir 是真实物理路径,用 std::filesystem::canonical(base_dir) 预先解析一次
  • 避免在根目录上使用符号链接;若必须,考虑用 openat() + AT_SYMLINK_NOFOLLOW 等系统调用级防护(C++ 标准库不覆盖此层)
  • 容器或沙箱环境里,还要配合 chroot 或命名空间限制,canonical() 无法替代这些机制

归一化函数不是防火墙,路径校验本质是「信任边界」问题——你得亲手划清那条线,并确保所有路径都落到线内。

C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!

相关文章

c++速学教程(入门到精通)
c++速学教程(入门到精通)

c++怎么学习?c++怎么入门?c++在哪学?c++怎么学才快?不用担心,这里为大家提供了c++速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

c++

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.02

7519

3

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.03

1938

5

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

2023.09.04

3184

5

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

2023.10.24

6384

49

字符串介绍
字符串介绍

字符串是一种数据类型,它可以是任何文本,包括字母、数字、符号等。字符串可以由不同的字符组成,例如空格、标点符号、数字等。在编程中,字符串通常用引号括起来,如单引号、双引号或反引号。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

2023.11.24

6549

6

java读取文件转成字符串的方法
java读取文件转成字符串的方法

Java8引入了新的文件I/O API,使用java.nio.file.Files类读取文件内容更加方便。对于较旧版本的Java,可以使用java.io.FileReader和java.io.BufferedReader来读取文件。在这些方法中,你需要将文件路径替换为你的实际文件路径,并且可能需要处理可能的IOException异常。想了解更多java的相关内容,可以阅读本专题下面的文章。

2024.03.22

8074

16

php中定义字符串的方式
php中定义字符串的方式

php中定义字符串的方式:单引号;双引号;heredoc语法等等。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

2024.04.29

12534

11

go语言字符串相关教程
go语言字符串相关教程

本专题整合了go语言字符串相关教程,阅读专题下面的文章了解更多详细内容。

2025.07.29

6499

17

c++字符串相关教程
c++字符串相关教程

本专题整合了c++字符串相关教程,阅读专题下面的文章了解更多详细内容。

2025.08.07

7307

13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C++ Core Guidelines
C++ Core Guidelines

共0课时 | 0人学习

C++ Reference
C++ Reference

共0课时 | 0人学习

C++ 官方标准说明
C++ 官方标准说明

共0课时 | 0人学习