Nashorn is the high-performance JavaScript engine developed in Java. It allows the developer to execute JavaScript in Java and vice versa. After Java SE 7, Nashorn has become the official JavaScript engine and all JDKs are shipped with it. Nashorn supports and implements the ECMAScript 5.1 specification. The Nashorn script engine implements javax.script API. It converts JavaScript to Java bytecode at the runtime.

Why Nashorn?

When we say Nashorn helps to execute JavaScript code in Java and vice versa, the first question which comes to our mind is why in the first place something like this is required. Isn’t it a security concern to execute JavaScript code in Java? Well, there are a few reasons why this might be required:

  • Customization: Nashorn helps the developer to add scripting support to the application. The end-user can quickly modify the product without recompiling the whole Java application.
  • Code reuse: Developers can leverage Nashorn to JavaScript code on the server without rewriting the business logic. E.g. the code for input validation on the client-side can be reused on the server-side because the business logic remains the same.

To interact with Nashorn JavaScript Engine, JDK comes with 2 command-line tools

  1. Java Java Script (jjs)
  2. jrunscript

Java Java Script (jjs) is the recommended client for interacting with Nashorn. We can write a JavaScript code, embed the Java snippets in it and execute the javascript file using jjs.

Similarly, we can write a Java code and embed the JavaScript snippets. In this case, we use javax.script API which will allow us to execute the JavaScript from within Java code.

Now, let’s look in the code and see how we can execute Java code from JavaScript and vice versa.

Executing Java Code within JavaScript

First, we will create a Java file Testing.java within a package roguesecurity and compile the code.

Now, we will create a file with name JavaFromJs.js and try to call the above Java code.

To run the above JavaScript code, we will use the command-line tool jjs and pass the filename as the argument.

Executing JavaScript Code within Java

First, we will create a simple JavaScript file testing.js which contains a single function.

Now, let’s create a Java file with name JsFromJava.java. We will be using javax.script API for calling above JavaScript function from our Java code.

Now we know how nashorn works, it’s time to abuse this. Suppose in the web application, there is a customization feature where the application accepts the javascript code/file from the end-user and the server-side will process this javascript to perform certain operations. If you ever see any such functionality, it should raise the red flag. By providing the javascript code as an input, we can perform remote code execution on the server. This can be achieved by taking the help of the Java reflection API. If you are not aware of reflection API, in the next section we will quickly discuss this. If you are already aware, jump to Writing the payload section.

Reflection 101

TLDR; Given an instance of a class, it is possible to call ANY* java method with the help of the reflection API.

Quoting the line from Oracle’s official documentation

Reflection enables Java code to discover information about the fields, methods and constructors of loaded classes, and to use reflected fields, methods, and constructors to operate on their underlying counterparts, within security restrictions.

https://docs.oracle.com/javase/8/docs/technotes/guides/reflection/index.html

Reflection API comes under java.lang.reflect package. Let’s create a simple class “Testing.java” in the package roguesecurity and look into various operations performed using reflection API.

Now, let’s create a file ReflectionDemo.java and look into the various reflection methods and their output

The key observation is we can execute the code using the instance of any class with the help of reflection API. Here we created a simple class “Testing” and with the help of its object, we were able to call Runtime.exec() to perform code execution. Note that in the above code, we have hardcoded the indices (7 and 14). In the next section, while writing our payload and we will automate the process of finding the index.

Writing the payload

Now we will sum up all the learnings till now and write the full working exploit to perform remote code execution. Below is the javascript payload which when supplied to Nashorn Script engine, will execute the command on the remote system.

If this payload is supplied to the below Java class, it will lead to remote code execution.

Mitigations

We can mitigate this vulnerability by implementing ClassFilter interface. This interface contains a method exposeToScripts. By overriding this method, we can prevent dangerous methods from being called via reflection API. Below is the code snippet for implementing the ClassFilter interface

Executing the above code will return “javax.script.ScriptException: TypeError: Java reflection not supported when class filter is present” and we are no longer to use reflection for code execution.

Conclusion

The best way to find this vulnerability is through manual code review. Try grepping the source code for the keywords like nashorn, javax.script. In case the application is using Nashorn Script Engine, review the source code to confirm if the ClassFilter is implemented. If you are doing black box pentest, look for the functionality which takes javascript as an input. Modify the exploit payload mentioned earlier to perform remote code execution or get the reverse shell back from the victim.

I hope this article was useful. If you have any questions or suggestions please leave your comments down below.

Happy Learning 🙂

References

https://coderanch.com/t/634396/java/case-Javascript-engine-Java
https://docs.oracle.com/javase/8/docs/technotes/guides/scripting/prog_guide/javascript.html
https://www.oracle.com/technetwork/articles/java/javareflection-1536171.html
https://docs.oracle.com/javase/8/docs/technotes/guides/reflection/index.html
https://docs.oracle.com/javase/8/docs/technotes/guides/scripting/nashorn/api.html
https://docs.oracle.com/javase/8/docs/technotes/guides/scripting/nashorn/api.html https://www.n-k.de/riding-the-nashorn/
https://github.com/shekhargulati/java8-the-missing-tutorial/blob/master/10-nashorn.md

Author: Piyush Saurabh

Author is a cyber security enthusiast, application and network penetration tester. His area of interest includes reverse engineering, application, network and hardware security.
Author is a cyber security enthusiast, application and network penetration tester. His area of interest includes reverse engineering, application, network and hardware security.

One Thought on “Abusing Nashorn for Remote Code Execution”

Leave a Reply

Your email address will not be published.