如何修复某些Java代码中的“路径操作漏洞”?

时间:2012-10-02 12:53:29

标签: security fortify path-manipulation

以下简单的java代码获取Fortify Path Manipulation错误。请帮我解决这个问题。我很长时间都在挣扎。

public class Test {
    public static void main(String[] args) {
        File file=new File(args[0]);
    }

}

7 个答案:

答案 0 :(得分:8)

查看Path Manipulation的OWASP页面,它说

  

攻击者可以指定文件系统上的操作中使用的路径

您正在打开由用户指定的输入定义的文件。您的代码几乎就是漏洞的完美示例!

  1. 不要使用上面的代码(不要让用户指定输入文件作为参数)
  2. 让用户从您提供的文件列表中选择(具有整数选择的文件数组)
  3. 不要让用户提供文件名,删除可配置性
  4. 接受漏洞但通过检查文件名来防止它(尽管这是最糟糕的事情 - 有人可能会绕过它。)
  5. 或重新考虑您的应用程序的设计。

答案 1 :(得分:5)

在使用之前尝试规范化网址

https://docs.oracle.com/javase/7/docs/api/java/net/URI.html#normalize()

Path path = Paths.get("/foo/../bar/../baz").normalize();

或使用 org.apache.commons.io.FilenameUtils

中的规范化

https://commons.apache.org/proper/commons-io/javadocs/api-1.4/org/apache/commons/io/FilenameUtils.html#normalize(java.lang.String)

Stirng path = FilenameUtils.normalize("/foo/../bar/../baz");

两者的结果都是\baz

答案 2 :(得分:2)

仅允许alnum和输入中的句号。这意味着你过滤掉控制字符“..”,“/”,“\”,这会使你的文件容易受到攻击。例如,一个人不应该输入/path/password.txt。

完成后,重新扫描然后运行Fortify AWB。

答案 3 :(得分:2)

我有Fortify Path Manipulation问题的解决方案。

它抱怨的是,如果您从外部源获取数据,则攻击者可以使用该源来操纵您的路径。因此,使攻击者能够删除文件或以其他方式破坏您的系统。

对此问题的建议补救措施是使用受信任目录的白名单作为有效输入;而且,拒绝其他一切。

此解决方案在生产环境中并不总是可行的。所以,我建议一个替代解决方案。解析可接受字符的白名单的输入。从输入中拒绝路径中不需要的任何字符。它可以被删除或替换。

以下是一个例子。这确实通过了Fortify审核。重要的是要记住这里返回文字,而不是被检查的字符。 Fortify会跟踪原始输入的部件。如果您使用任何原始输入,您仍可能会收到错误。

public class CleanPath {

    public static String cleanString(String aString) {
        if (aString == null) return null;
        String cleanString = "";
        for (int i = 0; i < aString.length(); ++i) {
            cleanString += cleanChar(aString.charAt(i));
        }
        return cleanString;
    }

    private static char cleanChar(char aChar) {

        // 0 - 9
        for (int i = 48; i < 58; ++i) {
            if (aChar == i) return (char) i;
        }

        // 'A' - 'Z'
        for (int i = 65; i < 91; ++i) {
            if (aChar == i) return (char) i;
        }

        // 'a' - 'z'
        for (int i = 97; i < 123; ++i) {
            if (aChar == i) return (char) i;
        }

        // other valid characters
        switch (aChar) {
            case '/':
                return '/';
            case '.':
                return '.';
            case '-':
                return '-';
            case '_':
                return '_';
            case ' ':
                return ' ';
        }
        return '%';
    }
}

答案 4 :(得分:1)

即使路径/文件不像属性文件那样来自用户输入,Fortify也会标记代码。处理这些问题的最佳方法是首先规范路径,然后根据允许路径的白名单对其进行验证。

<强>为:

public class Test {
    public static void main(String[] args) {
        File file=new File(args[0]);
    }

}

不可

public class Test {
    public static void main(String[] args) {
        File file=new File(args[0]);
        if (!isInSecureDir(file)) {
              throw new IllegalArgumentException();
            }
            String canonicalPath = file.getCanonicalPath();
        if (!canonicalPath.equals("/img/java/file1.txt") &&
            !canonicalPath.equals("/img/java/file2.txt")) {
           // Invalid file; handle error
        }

        FileInputStream fis = new FileInputStream(f);
    }

来源:https://www.securecoding.cert.org/confluence/display/java/FIO16-J.+Canonicalize+path+names+before+validating+them

答案 5 :(得分:0)

假设您正在针对Web应用程序运行Fortify,在您对Fortify漏洞进行分类时可能会标记为“不是问题”。推理A)显然这是测试代码和B)除非你有多重人格障碍,否则当你运行测试应用程序时,你不会对自己进行路径操纵攻击。

如果很少见到很少的测试实用程序提交到存储库,这会产生这种误报风格。

至于编译错误,通常归结为类路径问题。

答案 6 :(得分:-2)

使用正则表达式验证文件路径和文件名

fileName = args[0];
final String regularExpression = "([\\w\\:\\\\w ./-]+\\w+(\\.)?\\w+)";
Pattern pattern = Pattern.compile(regularExpression);
boolean isMatched = pattern.matcher(fileName).matches();