公开命令java.lang.Runtime.exec(String command)有哪些安全风险

问题描述 投票:0回答:1

我正在尝试对我的自定义应用程序进行碎片化,同时保持总体设计标准。
我最近学习了使用 graalvm 在 Windows 上将 java 应用程序编译为本机 exe 文件。

我正在考虑将设计从使用许多复杂的网络应用程序改为

  • 仅制作一个简单的 Web 应用程序作为 https 站点,
  • 并且只有一个 servlet 只有一项任务“将链接推送到相对的本机 exe 文件”,如下所示
     /**
     * for example url = "https://www.webpage.com/app-one/someNativeApplicationName?param1=value1&param2=value2...";
     * url params is ascii or base64
     */
    public String callNativeApplication(String url) {//
        //CONSTRUCT nativeApplicationFile
        String someNativeApplicationName = parseNativeApplicationNameFromUrl(url);
        Path nativeApplicationsFolder = Path.of("C:\\nativeApplicationsFolder");
        Path nativeApplicationFile = nativeApplicationsFolder.resolve(someNativeApplicationName);

        //CHECK FOR DIR HACK
        nativeApplicationFile = nativeApplicationFile.toAbsolutePath();
        if(!nativeApplicationFile.startsWith(nativeApplicationsFolder)) {
            throw new RuntimeException("ERROR: DIR HACK");
        }

        //CHECK HIDDEN COMMAND HACK
        if (url.chars().filter(ch -> ch == ' ').count() != 0) {
            throw new RuntimeException("ERROR: HIDDEN COMMAND HACK");
        }

        //CONSTRUCT command
        String command = nativeApplicationFile + " " + url;

        //CHECK HIDDEN CHAR HACK
        if (!Charset.forName("US-ASCII").newEncoder().canEncode(command)){
            throw new RuntimeException("ERROR: HIDDEN CHAR HACK");            
        }

        //EXECUTE
        Process p = java.lang.Runtime.getRuntime().exec(command); 
        String reply = fetchReply(p);
        return reply;
    }

并返回结果作为回复。

是否存在我应该额外考虑的安全风险。尝试一下安全吗?

java web servlets native graalvm
1个回答
0
投票

评论中有一些关于为什么让用户执行任意 shell 代码是一个坏主意的精彩评论。然而,有一些方法可以让它至少更安全一些。例如,您可以使用枚举将端点限制为硬编码的命令集:

public enum Command {
    ONE("C:/nativeApplicationsFolder/one.exe"),
    TWO("C:/nativeApplicationsFolder/two.exe"),
    ;

    private final String path;

    Command(String path) {
        this.path = path;
    }

    public String getPath() {
        return path;
    }
}

这样,您可以轻松检查该命令是否安全。但还是要小心:如果您需要用户传递命令行参数,您现在需要再次小心,确保用户不会访问您不希望他们访问的文件或其他应用程序。

© www.soinside.com 2019 - 2024. All rights reserved.