Tuesday, May 22, 2018

Code Execution with JDK Scripting Tools & Nashorn Javascript Engine

The Java Development Kit (JDK) provides command-line scripting tools that allow for in-memory execution of code that is interpreted by the Nashorn Javascript Engine, which can be utilized on Windows, macOS and Linux when the JDK is installed. This blog post will cover the usage of these JDK command-line scripting tools and the Nashorn Javascript Engine to perform several actions, such as downloading files, executing scripts locally and remotely, and gaining an interactive shell to a computer system. Detective and preventative controls will also be covered for the usage of these JDK scripting tools.

Why is this useful for Offense?


There are several advantages from an offensive perspective in using these JDK scripting tools. Obviously, this completely relies on the JDK being installed in order to take advantage of these tools.
  • No native logging for usage of JDK scripting tools or Nashorn Javascript Engine
  • Can assist in evasion of host-based security controls that rely on or factor in parent process id relationships for detections
  • No need to drop anything to disk
  • JDK Scripting Tools are signed binaries by Oracle
  • Supported on multiple platforms (Windows, Linux, macOS)

Background


First, let's cover a couple basics when it comes to the Java Development Kit and the Java Runtime Environment (JRE).

Java Runtime Environment


T
he JRE is the Java Virtual Machine (JVM) where Java programs run on, along with browser plugins for applet execution


Java Development Kit


T
he JDK is a full feature software development kit for Java, which includes the JRE. The JDK is comparable to what the .NET Framework SDK is for developing .NET applications.


Usage of JDK vs. JRE


Below are the differences between the JDK and JRE in relation to their usage.
  • JDK is used if you need to do Java programming or if applications running on host depend on it in order to function. An example of an application running on a host that could depend on the JDK being installed could be a Java Web Application.
  • JRE is used if you only need to be able to run Java programs in browser or on computer. This is all that is needed for typical users.


JDK Version History


The below table shows the version history between JDK versions.
JDK Version Historyhttps://en.wikipedia.org/wiki/Java_version_history


JDK Scripting Tools


JDK Scripting Tools are command-line tools that can run scripts which interact with the JRE. These tools are located in the below file locations for Windows, Linux and macOS.

  • Windows (default install)
    • C:\Program Files\Java\jdk<version>\bin
    • C:\Program Files (x86)\Java\jdk<version>\bin
    • C:\Program Files\Java\jre<version>\bin
    • C:\Program Files (x86)\Java\jre<version>\bin
  • Linux & macOS (default install)
    • /usr/bin

JRunscript


JRunscript is a command-line scripting shell installed with the JDK on operating systems such as Windows, Linux and macOS that can be used to execute code interpreted by supported Javascript Engines. This tool is installed starting with Java SE 6.

Showing JRunscript Signed by Oracle


JRunscript has the ability to perform several actions with built-in global functions that can be passed to the "-e" switch.
JRunscript Evaluate Switch (-e)

The below functions can be called by "jrunscript -e functionName(arguments)". These definitions were found at http://apprize.info/javascript/scripting/10.html.
  • cat(path, pattern) -  Shows the content of a file, URL, or InputStream specified by path. Optionally, you can specify pattern to show only the matching contents. 
  • cp(from, to)Copies a file, URL, or stream to another file or stream.
  • exec(cmd)Starts a child process, executes the specified command, waits for completion, and returns the exit code.
  • load(path) - Loads and evaluates JavaScript code from a stream, file, or URL.


JJS


JJS (Java Javascript) is another command-line scripting shell installed with the JDK on operating systems such as Windows, Linux and macOS that can be used to execute code interpreted by the Nashorn Javascript Engine. This tool is installed starting with Java SE 8.

Showing JJS Signed by Oracle

Nashorn Javascript Engine


The Nashorn Javascript Engine is a code engine that can interpret and execute ECMA-compliant Javascript. This engine can also interpret and execute Java code starting with Java SE 8. The previous engine utilized was the Mozilla Rhino Javascript engine.


Scripting Syntax


It utilizes a traditional Javascript-like syntax. A great resource can be found at https://www.n-k.de/riding-the-nashorn/.


Extending the Java Programming Language


You can extend the Java programming language as seen in the example below by getting direct access to a Java object. The below example uses the "Runtime" Java object to execute an operating system command with the "getRuntime().exec()" method, which in this case is just "calc.exe". More great examples can be found at https://github.com/shekhargulati/java8-the-missing-tutorial/blob/master/10-nashorn.md.


Usage/Examples

Below you will see several practical uses of the JDK Scripting tools to download files, execute system commands, run local and remote scripts, and get a reverse shell on a computer system.


Downloading Files


The below commands show how to download files with JRunscript either from a web server or file share using the "cat" and "cp" global functions.

Execute System Commands


The below commands show how to execute system commands with JRunscript using the "exec" global function.


Loading & Running Local Scripts


The below commands show how to execute local scripts with JRunscript and JJS.


Loading & Running Remote Scripts


The below commands show how to execute remote scripts with JRunscript using the "load" global function. This will load and execute a script without dropping it to disk.


One-Liner Reverse Shell


The below commands show how to execute a one-liner to give a reverse shell with JRunscript. For the Windows command, it will send the "cmd.exe" process to the IP address and port that you specify. In the Linux & macOS command, it will send "/bin/bash -i" to the IP address and port that you specify. Credit for the original finding of the one-liner reverse CMD shell goes to Chris Frohoff.


Base64 Encoded One-Liner Reverse Shell


The below commands show how to execute a base64 encoded one-liner to give a reverse shell with JRunscript. An example script that can be base64 encoded for a reverse CMD shell can be found here. Credit for the original finding of this base64 encoded one-liner and example reverse CMD shell goes to Chris Frohoff.


Defensive Considerations


There are multiple detective and preventative controls that can be implemented in regards to the usage of the JDK scripting tools. For host-based controls, I will be focusing on Windows.


Full Command-Line Logging


Utilize free tools such as Sysmon to perform full command-line logging. I setup a default install of Sysmon, and it caught the running of JRunscript in my home lab as seen in the screenshot below. These logs will need to be sent to a Security Information & Event Management (SIEM) system where they can be processed and appropriate alerts can be created.

Sysmon Output on My Home Lab Machine

Process Monitoring


Monitor for process creation events containing "jrunscript.exe" or "jjs.exe" However, keep in mind that these files can be renamed and executed as well with appropriate file system permissions.

Filtering on JRunscript Process

User Agent String Monitoring


When utilizing the file download (cat & cp) and remote script loading (load) global functions in JRunscript, the user agent used is "Java/<jdk version>". Rules for detection of this user agent can be implemented.

Apache Logs Showing User Agent String

Application Whitelisting


Implement a robust application whitelisting policy that includes the blocking of JRunscript and JJS. For example, with AppLocker you will need to tweak beyond the default executable rules shown below, as the default rule to allow executable files located in the "Program Files" and "Program Files (x86)" directories would still permit the JDK Scripting Tools to execute.

AppLocker Default Executable Rules
 (https://docs.microsoft.com/en-us/windows/security/threat-protection/windows-defender-application-control/applocker/executable-rules-in-applocker)

Uninstall JDK


Survey the inventory of hosts in your enterprise and uninstall the JDK where not needed to reduce your risk exposure.


References

1 comment:

  1. Love this so much.That I posted my own stuff over here:

    https://cornerpirate.com/2018/08/17/java-gives-a-shell-for-everything/

    While you have mentioned JJS you focused on JRunScripter which is JDK only while JJS is JRE. I think this makes it slightly worse :D

    ReplyDelete