商城首页欢迎来到中国正版软件门户

您的位置: 首页 > 文章列表 > 编程开发 > C#如何防止目录遍历攻击_C# Path.GetFullPath安全校验文件路径【核心】

C#如何防止目录遍历攻击_C# Path.GetFullPath安全校验文件路径【核心】

  发布于2026-07-11 阅读(0)

扫一扫,手机访问

先列出几个核心判断:

在C#里防目录遍历攻击,最靠谱的路径就是拿Path.GetFullPath做归一化,然后用它来校验。别指望靠字符串里找..或者拿正则替换就能搞定,那些手段在真实攻击面前基本是纸糊的。

C#如何防止目录遍历攻击_C# Path.GetFullPath安全校验文件路径【核心】

规范做法就一条:归一化之后再做检查,光靠字符串过滤".."或者用正则替换,根本靠不住。

为什么 Path.Combine 加字符串检查靠不住

很多人习惯把用户输入和根目录拼一起,然后查有没有..,或者干脆用string.Replace("..", "")。这种做法遇到真实攻击路径时,漏洞百出:

  • Path.Combine("C:\\app", "..\\..\\windows\\system32\\cmd.exe") 出来的是C:\app\..\..\windows\system32\cmd.exe——Combine本身不做归一化,你再用StartsWith去判断,结果必然是“通过”
  • 攻击者可以用URL编码的%2e%2e/、Unicode点号(比如..)、甚至混合斜杠(..../混着来)轻松绕开字符串检查
  • 更狠的是绝对路径注入:Path.Combine("C:\\app", "C:\\evil\\web.config"),结果直接跳到另一个盘符,字符串检测在这种场景下毫无意义

正确的校验流程:三步,一步都不能少

归一化 → 比对前缀 → 注意分隔符边界

  • 先调用Path.GetFullPath(candidate),让操作系统帮你解析出最终的绝对路径(比如C:\app\..\config.json变成C:\config.json
  • 然后用StartsWith(safeRoot + Path.DirectorySeparatorChar, StringComparison.Ordinal)做检查——必须加上后缀分隔符,否则C:\safe会错误地匹配上C:\safeguard
  • 这个校验必须在所有路径操作完成后、文件I/O之前执行——比如在File.Open前、在Directory.EnumerateFiles前,一个不能少

写文件比读文件更需要严防死守

读操作越界,最多是泄露些配置信息;写操作一旦被突破,后果可能就是web.config被覆盖、WebShell被植入、日志被篡改。

  • 写操作要额外检查目标路径是否已经存在,并且不在白名单里(比如禁止覆盖appsettings.json这样的关键文件)
  • 不要依赖扩展名黑名单——比如只拦截.aspx——Windows允许长文件名,攻击者可以用shell.aspx:zone.id这种手法绕过
  • 如果业务允许用户指定文件名,最保险的做法是用间接映射,比如ID对应文件名字典,而不是直接把用户输入拼接到路径上

符号链接是隐藏的雷区

DirectoryInfoFile.Exists默认会跟随符号链接或junction点,Path.GetFullPath的校验在这种情况下是无效的。

  • 必须用File.GetAttributes(path) & FileAttributes.ReparsePoint检测重解析点
  • 然后调用File.GetLinkTarget(path)(.NET 6+)确认是不是符号链接(junction点会返回null)
  • 递归遍历时不要用SearchOption.AllDirectories,要手动做BFS/DFS,对每个FileSystemInfo逐一校验

最容易忽略的一点:校验逻辑必须跑在真实的文件系统路径上,而不是在URL解码后、没有归一化的字符串上。攻击者不会和你比谁的正则写得漂亮,他们只会盯着GetFullPath的行为去对齐——那就让它成为唯一权威的判断标准。

本文转载于:https://www.php.cn/faq/2382763.html 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。

热门关注