Path.GetRandomFileName()仅生成8.3格式临时文件名,不能用于模糊测试;真 fuzz 需手动构造含 、超长路径、目录遍历等变异payload,并绕过.NET路径校验。

用 Path.GetRandomFileName() 生成文件名不等于模糊测试
很多人以为调用 Path.GetRandomFileName() 就算在做模糊测试,其实它只生成 8.3 格式短名(如 "w4567890.tmp"),长度固定、字符集受限、无路径遍历或空字节能力——根本碰不到解析器的边界逻辑。
真正需要的是可控的变异策略:比如插入 " "、超长路径、嵌套 "....etcpasswd"、UTF-16 surrogate 对、重复的 "//" 或 "///"。这些必须自己构造,不能依赖系统工具函数。
-
Path.GetRandomFileName()仅用于临时文件名,别拿它当 fuzz payload - 文件名模糊需覆盖:
" "、".."、"."、"*"、"?"、Unicode 归一化等变体 - 路径拼接务必用
Path.Combine(),但注意它会“规范化”掉部分非法片段(如自动删".."),反而掩盖漏洞
直接写入 " " 字节到文件名会导致 ArgumentException
C# 的 File.WriteAllText()、Directory.CreateDirectory() 等 API 在内部调用 Win32 CreateFile() 前,会先校验文件路径是否含 " " 或控制字符,直接抛 ArgumentException: Illegal characters in path。你根本没机会把恶意路径传到底层。
要绕过这层校验,得用更底层的方式:通过 FileStream 手动指定 FileOptions.None,或用 P/Invoke 调用 CreateFileW 并传入原始字符串指针——但这意味着放弃 .NET 的路径安全防护,风险自担。
- 所有高阶 IO 方法(
File.*、Directory.*)都会提前拦截" " - 若目标是测试解析器对 NUL 截断的处理,必须用
FileStream+Marshal.StringToHGlobalUni()构造原始缓冲区 - Linux/macOS 下还需注意:.NET 6+ 默认启用
System.IO.EnableUnsafeIO才允许传递含" "的路径给 syscall
用 Microsoft.CodeAnalysis.Fuzzing 不解决文件系统问题
这个 NuGet 包名字带 “Fuzzing”,但实际只针对 Roslyn AST 解析器,和文件路径、目录遍历、编码转换完全无关。它生成的是随机 C# 源码字符串,喂给 CSharpSyntaxTree.ParseText(),不是用来测 Path.GetDirectoryName() 或 ZipArchive 解压逻辑的。
如果你的解析器是自己写的 ZIP 解包器、INI 文件读取器或 YAML 路径解析模块,得另起炉灶:用 csfuzz 或 AFL++ 配 .NET 适配器,或者手写一个基于 Span 的变异循环,每次改写文件内容的某几个字节再触发解析。
-
Microsoft.CodeAnalysis.Fuzzing是领域专用,别被名字误导 - 文件系统级 fuzz 必须控制输入字节流,而非语法树节点
- 推荐从简单变异开始:单字节翻转 → 随机插入
" "→ UTF-8 编码异常序列(如0xC0 0xC1)
Windows 上 MAX_PATH 限制让长路径 fuzz 失效
默认情况下,Windows API 拒绝处理超过 260 字符的路径(MAX_PATH),哪怕你的代码用了 @"\?" 前缀,.NET 运行时仍可能在内部截断或抛 PathTooLongException。结果就是:你生成了 3000 字节的嵌套 "......" 路径,却连 File.Exists() 都没走到就挂了。
必须同时满足三个条件才能让长路径生效:启用应用清单中的 longPathAware=true、在 app.config 中设置 (.NET Core 3.1+ 不需要)、且所有中间 API(包括你自己写的路径拼接逻辑)都避免调用 Path.GetFullPath() ——因为它会主动截断。
-
Path.GetFullPath()是长路径 fuzz 的隐形杀手,它会在你不知情时把超长路径缩成合法值 - 检测是否真正生效:用
Kernel32.CreateFile()直接传@"\?C:..."+ 超长后缀,看返回是否为INVALID_HANDLE_VALUE - Linux/macOS 无此限制,但要注意 ext4 对单文件名长度限制是 255 字节,别盲目堆叠
事情说清了就结束。文件系统模糊测试真正的难点不在生成随机数据,而在绕过 .NET 层层封装,把原始、非法、边缘的字节准确送进目标解析器的入口点——中间任何一层“好心”的校验,都在帮你掩盖漏洞。











