gpt4 book ai didi

java - checkmarx - 如何解决存储绝对路径遍历问题?

转载 作者:行者123 更新时间:2023-12-03 11:19:41 28 4
gpt4 key购买 nike

Checkmarx - v 9.3.0 HF11
我将 env 值作为数据目录路径传递到 dev/uat 服务器中使用的 docker 文件中

ENV DATA /app/data/
在本地,使用以下环境变量
数据=C:\projects\app\data\
getDataDirectory("MyDirectoryName");//MyDirectoryName 存在于数据文件夹中
public String getDataDirectory(String dirName)
{
String path = System.getenv("DATA");
if (path != null) {
path = sanitizePathValue(path);
path = encodePath(path);

dirName = sanitizePathValue(dirName);
if (!path.endsWith(File.separator)) {
path = path + File.separator;
} else if (!path.contains("data")) {
throw new MyRuntimeException("Data Directory path is incorrect");
}
} else {
return null;
}

File file = new File(dirName); // NOSONAR

if (!file.isAbsolute()) {
File tmp = new File(SecurityUtil.decodePath(path)); // NOSONAR

if (!tmp.getAbsolutePath().endsWith(Character.toString(File.separatorChar))) {
dirName = tmp.getAbsolutePath() + File.separatorChar + dirName;
} else {
dirName = tmp.getAbsolutePath() + dirName;
}

}

return dirName;
}

public static String encodePath(String path) {
try {
return URLEncoder.encode(path, "UTF-8");
} catch (UnsupportedEncodingException e) {
logger.error("Exception while encoding path", e);
}
return "";
}

public static String validateAndNormalizePath(String path) {
path = path.replaceAll("/../", "/");
path = path.replaceAll("/%46%46/", "/");
path = SecurityUtil.cleanIt(path);
path = FilenameUtils.normalize(path); // normalize path
return path;

}

public static String sanitizePathValue(String filename){
filename = validateAndNormalizePath(filename);
String regEx = "..|\\|/";
// compile the regex to create pattern
// using compile() method
Pattern pattern = Pattern.compile(regEx);
// get a matcher object from pattern
Matcher matcher = pattern.matcher(filename);

// check whether Regex string is
// found in actualString or not
boolean matches = matcher.matches();
if(matches){
throw new MyAppRuntimeException("filename:'"+filename+"' is bad.");
}
return filename;
}

public static String validateAndNormalizePath(String path) {
path = path.replaceAll("/../", "/");
path = path.replaceAll("/%46%46/", "/");
path = SecurityUtil.cleanIt(path);
path = FilenameUtils.normalize(path); // normalize path
return path;

}
[尝试] - 更新我在少数成员的帮助下尝试防止路径遍历问题的代码。
试图清理字符串和规范化字符串,但没有运气并遇到同样的问题。
如何解决存储绝对路径遍历问题?

最佳答案

您的第一次尝试不会成功,因为单独逃逸并不会阻止路径遍历。用双引号替换单引号不会这样做,因为您需要确保有人使用 ../../etc/resolv.conf 设置属性/环境变量无法成功欺骗您的代码覆盖/读取敏感文件。我相信 Checkmarx 不会寻找 StringUtils作为将其识别为已清理的一部分,因此下面的简单工作示例与不使用 StringUtils 类似.
您的第二次尝试将不起作用,因为它是一个 validator ,它在抛出异常时使用控制流来防止错误输入。 Checkmarx 分析数据流。当filename作为参数传递给 sanitizePathValue并在最后按原样返回,数据流分析认为这不会对原始值进行更改。
您的系统中似乎还有一些自定义项可以识别 System.getPropertySystem.getenv作为不受信任的输入。默认情况下,这些不会以这种方式识别,因此任何试图扫描您的代码的人可能都不会获得绝对路径遍历的任何结果。您的应用程序的风险状况可能要求您将属性和环境变量称为不受信任的输入,因此您不能真正删除这些并恢复到 OOTB 设置。
正如 Roman 所提到的,查询中的逻辑确实会查找附加到这个不受信任的输入的值,以将这些数据流作为结果删除。下面的代码显示了如何使用 Roman 的方法来欺骗扫描仪。 (我强烈建议你不要选择欺骗扫描仪的路线......非常糟糕的主意。)可能还有其他字符串文字值可以使用这种方法工作,但它需要一些控制运行时方式的操作执行(如使用 chroot)以确保它确实解决了问题。
如果您扫描下面的代码,您应该只会看到一个易受攻击的数据路径。最后一个示例可能与您可以用来修复问题的内容类似。这实际上取决于您要对正在创建的文件做什么。
(我在 9.2 上对此进行了测试;它应该适用于以前的版本。如果它不起作用,请发布您的版本,我可以查看该版本的查询。)

// Vulnerable
String fn1 = System.getProperty ("test");
File f1 = new File(fn1);


// Path prepend - still vulnerable, tricks the scanner, DO NOT USE
String fn2 = System.getProperty ("test");
File f2 = new File(Paths.get ("", fn2).toString () );

// Path prepend - still vulnerable, tricks the scanner, DO NOT USE
String fn3 = System.getProperty ("test");
File f3 = new File("" + fn3);

// Path prepend - still vulnerable, tricks the scanner, DO NOT USE
String fn4 = System.getProperty ("test");
File f4 = new File("", fn4);

// Sanitized by stripping path separator as defined in the JDK
// This would be the safest method
String fn5 = System.getProperty ("test");
File f5 = new File(fn5.replaceAll (File.separator, ""));


因此,总而言之 (TL;DR),替换不受信任的输入值中的文件分隔符:
String fn5 = System.getProperty ("test");
File f5 = new File(fn5.replaceAll (File.separator, ""));
编辑
为其他可能遇到此问题的 Checkmarx 用户更新以寻找答案。
在我回答之后,OP 更新了问题以表明发现的问题是由于为代码在不同环境中运行而编写的机制。 Pre-docker,这将是使用的方法。该漏洞仍会被检测到,但大多数行动方案都是说“我们的部署环境有围绕它的安全措施,以防止不良行为者将不需要的路径注入(inject)我们存储基本路径的环境变量中。”
但是现在,有了 Docker,这已经成为过去。通常 Docker 的目的是创建运行 the way same everywhere they are deployed 的应用程序.在环境中使用基本路径可能意味着 OP 正在容器外部执行代码以进行开发(基于显示 Windows 路径的更新)和容器内部进行部署。为什么不直接在容器中运行代码以进行 Docker 的开发和部署?
大多数答案倾向于解释 OP 应该使用静态路径。这是因为他们意识到没有办法避免这个问题,因为获取不受信任的输入(来自环境)并将其添加到路径的前缀是绝对路径遍历的确切问题。
OP 可以在这里遵循许多海报的好建议,并在代码中放置一个静态基本路径,然后使用 Docker volumesDocker bind mounts .
它困难吗?不。如果我是 OP,我会将代码中的基本路径前缀修复为静态值 /app/data并在开发过程中进行简单的卷绑定(bind)。 (仔细想想,如果在部署期间容器中存储了数据,那么部署环境必须为 /app/data 做这件事,除非数据在容器的生命周期后不再保留。)
基本路径固定在 /app/data , OP 运行其开发版本的一种选择是:
docker run -it -v"C:\\projects\\app\\data":/app/data {container name goes here}
应用程序写入的所有数据都将出现在 C:\projects\app\data 中。与使用环境变量时的方式相同。主要区别在于没有环境变量前缀路径,因此静态分析扫描器没有绝对路径遍历结果。

关于java - checkmarx - 如何解决存储绝对路径遍历问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65106898/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com