Lucene search
+L

Payara 7.2026.1.RC1 Arbitrary EJB Method Invocation

🗓️ 04 Sep 2026 00:00:00Reported by Ron EType 
packetstorm
 packetstorm
🔗 packetstorm.news👁 8 Views

Arbitrary EJB method invocation in Payara 7.2026.1.RC1 via reflective HTTP endpoints.

Code
Payara Server exposes multiple HTTP-accessible EJB invocation mechanisms
    that rely on attacker-controlled reflection, dynamic class loading, and
    unsafe deserialization. These endpoints allow remote clients to perform
    arbitrary JNDI lookups, resolve attacker-supplied class names, and invoke
    EJB business methods via reflection without sufficient authorization
    enforcement or input restriction.
    
    Both the deprecated InvokeEJBServlet and the EjbOverHttpResource
    (EJB-over-HTTP JAX-RS endpoint) implement the same insecure design pattern:
    user-controlled inputs are used to select classes, methods, parameter
    types, and argument values, which are then executed reflectively inside the
    application context. Deprecation does not disable or mitigate the exposure,
    leaving a powerful remote invocation surface reachable in production
    deployments.
    
    Affected Components
    
       -
    
       *EJB-over-HTTP JAX-RS Resource*
       -
    
          Class: fish.payara.ejb.http.endpoint.EjbOverHttpResource
          -
    
          Paths:
          -
    
             /jndi/lookup
             -
    
             /jndi/invoke
             -
    
          Media Types: JSON / Java Serialization
          -
    
          Technology: JAX-RS / EJB / JNDI / Reflection / JSON-B
          -
    
       *Deprecated HTTP Servlet*
       -
    
          Component: fish.payara.ejb.invoke.InvokeEJBServlet
          -
    
          Servlet Mapping: /ejb/*
          -
    
          Status: Deprecated but registered, reachable, and functional
    
    
    Affected Versions
    
       -
    
       Payara Server versions that include and expose either:
       -
    
          InvokeEJBServlet, or
          -
    
          EjbOverHttpResource
    
    *Vulnerability Details:*
    The affected endpoints perform a series of insecure operations that
    collectively expose a powerful reflection-based invocation surface.
    User-supplied jndiName values are passed directly to InitialContext.lookup,
    and the application context is dynamically switched based on parsed JNDI
    input, enabling access to arbitrary EJBs within the target application and,
    in some cases, across application boundaries. Once a target EJB is
    resolved, attacker-controlled method names and parameter type names are
    processed using Java reflection, and Method.invoke() is executed on EJB
    proxies without any allowlisting, capability checks, or restriction to
    intended business methods. In parallel, parameter and return types are
    resolved using Class.forName() with the application’s class loader,
    allowing resolution of any class visible within the application context.
    User-supplied JSON payloads are then deserialized via JSON-B into
    attacker-chosen target types, creating a generic deserialization sink that
    feeds directly into the reflective invocation flow. Authentication is
    optional and controlled by the client, while authorization failures do not
    consistently terminate execution, allowing invocation logic to continue
    after partial or failed security checks. Finally, detailed reflection and
    invocation errors, such as NoSuchMethodException, are returned verbatim to
    the client, disclosing internal EJB proxy class names, interface
    structures, and method resolution behavior, which enables method and
    interface enumeration and facilitates further exploitation.
    
    *Impact:*
    A remote attacker may be able to:
    
       - Invoke arbitrary EJB business methods
       - Access EJBs outside the intended application scope
       - Bypass or weaken authorization controls
       - Abuse JSON-B deserialization with attacker-chosen target types
       - Enumerate internal classes, interfaces, and method signatures
       - Trigger sensitive or administrative application functionality
       - Potentially achieve remote code execution, depending on reachable
       methods and classes
       - The exposure of a generic reflection-based invocation primitive
       significantly increases the attack surface of affected Payara deployments.
    
    
    
    *Vulnerable Code — EjbOverHttpResource:*
    *Attacker-Controlled JNDI Lookup*
    Object bean = service.getBean(jndiName);
    
    *Application Context Switching Based on User Input*
    String applicationName = jndiName.substring(12, jndiName.indexOf('/', 12));
    ClassLoader appClassLoader = service.getAppClassLoader(applicationName);
    Thread.currentThread().setContextClassLoader(appClassLoader);
    
    *Externally Controlled Class Resolution*
    Class.forName(name, true, Thread.currentThread().getContextClassLoader());
    
    *Reflection-Based Method Resolution*
    Method method = findBusinessMethodDeclaration(
        ejb,
        request.method,
        argTypes
    );
    
    *Reflection-Based Method Invocation*
    Object result = method.invoke(
        ejb,
        request.argDeserializer.deserialise(
            request.argValues,
            method,
            argActualTypes,
            Thread.currentThread().getContextClassLoader()
        )
    );
    
    *Unsafe JSON-B Serialization / Type Handling*
    JsonbBuilder.create().toJson(result.result, returnType, output);
    
    *Information Disclosure via Reflection Errors*
    throw new NoSuchMethodException(
        "No method matching " + methodName + "(" +
        Arrays.toString(argTypeClasses) + ") found"
    );
    
    *Vulnerable Code — InvokeEJBServlet (Deprecated but Active):*
    
    *Attacker-Controlled JNDI Lookup (Direct & Cross-Application)*
    Object bean = new InitialContext().lookup(beanName);
    *And the cross-application fallback:*
    for (String applicationName : registry.getAllApplicationNames()) {
    
    currentThread.setContextClassLoader(registry.get(applicationName).getAppClassLoader());
        Object bean = new InitialContext().lookup(beanName);
        return operation.execute(bean);
    }
    
    *Application Context Switching Based on User Input*
    String applicationName = beanName.substring(12, beanName.indexOf('/', 12));
    currentThread.setContextClassLoader(
        registry.get(applicationName).getAppClassLoader()
    );
    
    *Externally Controlled Class Resolution*
    Class.forName(className, true,
    Thread.currentThread().getContextClassLoader());
    (from toClass())
    private static Class<?> toClass(JsonValue classNameValue) {
        String className = ((JsonString) classNameValue).getString();
        return Class.forName(className, true,
            Thread.currentThread().getContextClassLoader());
    }
    
    *Reflection-Based Method Resolution Using Attacker Input*
    this.method = findBusinessMethodDeclaration(methodName, argTypeClasses);
    return intf.getMethod(methodName, argTypeClasses);
    
    *Reflection-Based Method Invocation*
    this.result = method.invoke(bean, argValues);
    (from Invocation.invoke())
    
    *Unsafe JSON-B Deserialization into Attacker-Chosen Types*
    return jsonb.fromJson(objectValue.toString(), type);
    (from toObject())
    argValues[i] = toObject(jsonArgValues.get(i), argTypes[i]);
    (from toObjects())
    
    *Broken Authorization Enforcement (Execution Continues)*
    if (!request.isUserInRole(role)) {
        response.setStatus(HttpServletResponse.SC_FORBIDDEN);
    }
    
    *Information Disclosure via Reflection Errors*
    throw new NoSuchMethodException(
        "No method matching " + methodName + "(" +
        Arrays.toString(argTypeClasses) + ") found in business interface"
    );
    And error propagation:
    response.sendError(
        SC_INTERNAL_SERVER_ERROR,
        "Error while invoking invoking method " + methodName +
        " on EJB with name " + beanName + ": " + ex.getMessage()
    );
    
    
    *Proof of Concept:*POST /ejb-invoke-1.0/ejb/ HTTP/1.1
    Host: localhost:8080
    Content-Type: application/json
    
    {
      "lookup": "java:global/ejb-invoke-1.0/TestBean",
      "method": "exec",
      "argTypes": ["java.lang.String"],
      "argValues": ["test"]
    }
    
    *Output:*
    
    HTTP/1.1 500 java.lang.NoSuchMethodException:
    test.__EJB31_Generated__TestBean__Intf____Bean__.exec(java.lang.String)
    Server: Payara Server 6.2024.6 #badassfish
    
    Ron Edgerson
    Vulnerability Researcher & Exploit Developer
    
    CVE Research | Binary Exploitation | Application & Systems Security
    Responsible Disclosure • Proof-of-Concept Development
    
    🌐 https://github.com/ob1sec
    🔗 https://www.linkedin.com/in/ronedgerson1
    <https://linkedin.com/in/yourhandle>

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

04 Sep 2026 00:00Current
5.8Medium risk
Vulners AI Score5.8
8