You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Snyk检测到路径遍历问题:已做输入清理仍未解决

路径遍历问题排查与代码修复

我用Snyk检测代码时触发了路径遍历告警,涉事代码行是:
FileUtils.CopyFile(this.txtEnFileName.Text, fullEnPath, true, true);

我已经在该行上方添加了输入清理逻辑:移除无效路径/文件名字符、用Path.Combine安全组合路径、校验路径合法性,但重新扫描后问题仍存在,怀疑需要修改涉事代码块。完整代码如下:

// Sanitize inputs
string sanitizedSubDirName = Path.GetInvalidPathChars().Aggregate(subDirName, (current, c) => current.Replace(c.ToString(), string.Empty));
string sanitizedProduct = Path.GetInvalidFileNameChars().Aggregate(productList[count], (current, c) => current.Replace(c.ToString(), string.Empty));
string sanitizedRootFileName = Path.GetInvalidFileNameChars().Aggregate(rootFileName, (current, c) => current.Replace(c.ToString(), string.Empty));

// Combine paths safely
dstEnFileName = Path.Combine(sanitizedSubDirName, sanitizedProduct, sanitizedRootFileName + "EN.rtf");
dstFrFileName = Path.Combine(sanitizedSubDirName, sanitizedProduct, sanitizedRootFileName + "FR.rtf");

string fullEnPath = Path.GetFullPath(dstEnFileName);
string fullFrPath = Path.GetFullPath(dstFrFileName);

if (!fullEnPath.StartsWith(subDirName, StringComparison.OrdinalIgnoreCase) || !fullFrPath.StartsWith(subDirName, StringComparison.OrdinalIgnoreCase))
{
    throw new UnauthorizedAccessException("Path traversal detected");
}

// Perform the file copy
FileUtils.CopyFile(this.txtEnFileName.Text, fullEnPath, true, true);
FileUtils.CopyFile(this.txtFrFileName.Text, fullFrPath, true, true);

问题根源

  1. 目标路径校验逻辑不严谨:直接用fullEnPath.StartsWith(subDirName)存在漏洞——如果subDirName是C:\safe,构造出的fullEnPath是C:\safeFake\file.txt,字符串前缀匹配会误判为合法;另外如果subDirName是相对路径,转成绝对路径后和原字符串比对会完全失效。
  2. 源路径完全未校验:Snyk的告警大概率是针对this.txtEnFileName.Text和this.txtFrFileName.Text这两个用户可控的源路径——攻击者可以输入../../malware.exe这类路径,让程序复制恶意文件,你之前的逻辑完全没覆盖这块风险。

修复方案

核心修改点

  • 把所有路径转成绝对路径后再做校验
  • 校验时在基准路径后追加目录分隔符,避免部分匹配的误判
  • 新增源路径的合法性校验,限定在指定的安全目录内

修改后的代码

// 定义允许的源根目录和目标基准目录(根据实际业务场景调整)
string allowedSourceRoot = Path.GetFullPath(@"C:\YourAllowedSourceDirectory");
string targetBaseDir = Path.GetFullPath(subDirName);

// Sanitize inputs
string sanitizedSubDirName = Path.GetInvalidPathChars().Aggregate(subDirName, (current, c) => current.Replace(c.ToString(), string.Empty));
string sanitizedProduct = Path.GetInvalidFileNameChars().Aggregate(productList[count], (current, c) => current.Replace(c.ToString(), string.Empty));
string sanitizedRootFileName = Path.GetInvalidFileNameChars().Aggregate(rootFileName, (current, c) => current.Replace(c.ToString(), string.Empty));

// Combine paths safely
dstEnFileName = Path.Combine(sanitizedSubDirName, sanitizedProduct, sanitizedRootFileName + "EN.rtf");
dstFrFileName = Path.Combine(sanitizedSubDirName, sanitizedProduct, sanitizedRootFileName + "FR.rtf");

string fullEnPath = Path.GetFullPath(dstEnFileName);
string fullFrPath = Path.GetFullPath(dstFrFileName);

// 修复目标路径校验:用绝对路径+目录分隔符做精确匹配
string targetBaseWithSeparator = targetBaseDir + Path.DirectorySeparatorChar;
if (!fullEnPath.StartsWith(targetBaseWithSeparator, StringComparison.OrdinalIgnoreCase) || 
    !fullFrPath.StartsWith(targetBaseWithSeparator, StringComparison.OrdinalIgnoreCase))
{
    throw new UnauthorizedAccessException("Path traversal detected");
}

// 新增源路径合法性校验
string sourceEnPath = Path.GetFullPath(this.txtEnFileName.Text);
string sourceFrPath = Path.GetFullPath(this.txtFrFileName.Text);
string sourceRootWithSeparator = allowedSourceRoot + Path.DirectorySeparatorChar;

if (!sourceEnPath.StartsWith(sourceRootWithSeparator, StringComparison.OrdinalIgnoreCase) ||
    !sourceFrPath.StartsWith(sourceRootWithSeparator, StringComparison.OrdinalIgnoreCase))
{
    throw new UnauthorizedAccessException("Invalid source path detected");
}

// 执行文件复制(使用校验后的源路径)
FileUtils.CopyFile(sourceEnPath, fullEnPath, true, true);
FileUtils.CopyFile(sourceFrPath, fullFrPath, true, true);

额外说明

  • 必须根据实际业务场景明确allowedSourceRoot的取值,不能开放任意源目录权限
  • 用绝对路径+目录分隔符的前缀匹配,能彻底避免部分字符串匹配带来的误判
  • 静态扫描工具会检查所有用户可控的输入路径,包括源和目标,两个方向的校验都不能少

内容的提问来源于stack exchange,提问作者ohayoouuuu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 23:52:05