Search code examples
javawebservletsnativegraalvm

What are the security risks on making public the command java.lang.Runtime.exec(String command)


I am trying to fragment my custom applications, while keeping the total design standard.
I have recently learned compiling java applications to native exe files on windows with graalvm.

I am thinking of chaging the design from using many complex web-applications to

  • make only one simple web application to serve as a https site,
  • and having only one servlet having only one task "to push the link to relative native exe files", as sth like below
     /**
     * 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;
    }

and return the outcome as reply.

Will there be any security risk that i should additionally consider. Is it safe to give a go?


Solution

  • I am convinced that executing shell code with url is a bad idea.
    There is so many things that can go wrong. Please see here.

    Rather than dealing with all security checks for terminal execution, It is probably a better solution:

    • to input the url string to a database row,
    • then call the native exe with row id accordingly.
    String command = nativeApplicationFile + " " + 1234;
    
     /**
         * 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 IF FILE EXISTS
            if(!isFileExists(nativeApplicationFile)) {
                throw new RuntimeException("ERROR: FILE NOT FOUND");
            }
    
            //CONSTRUCT command
            var rowId = pushUrlToDB(url);
            String command = nativeApplicationFile + " " + rowId;
    
            //EXECUTE
            Process p = java.lang.Runtime.getRuntime().exec(command); 
            String reply = fetchReply(p);
            return reply;
        }
    

    ---------------- UPDATE -----------------
    I tried to implement the project using JDK (com.sun.net.httpserver) on graalvm21 so that it runs even as native, here