GCVE Workshop - 22 September 2026 (14:00-18:00), Luxembourg Before The Vulnopticon Conference - Registration

GCVE-1988-2026-0006

Vulnerability from gna-1988 – Published: 2026-09-07 06:42 – Updated: 2026-09-09 13:03
VLAI
Title
Payara 7.2026.1.RC1 Arbitrary EJB Method Invocation via Insecure Reflection in Payara Server
Summary
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> _______________________________________________ Sent through the Full Disclosure mailing list https://nmap.org/mailman/listinfo/fulldisclosure Web Archives & RSS: https://seclists.org/fulldisclosure/
Severity
No CVSS data available.
Impacted products
Vendor Product Version CPE status
Payara Payara Affected: unknown
guessed Create a notification for this product.
Credits

{
  "containers": {
    "cna": {
      "affected": [
        {
          "product": "Payara",
          "vendor": "Payara",
          "versions": [
            {
              "status": "affected",
              "version": "unknown"
            }
          ]
        }
      ],
      "credits": [
        {
          "lang": "en",
          "type": "finder",
          "value": "Ron E"
        }
      ],
      "descriptions": [
        {
          "lang": "en",
          "value": "Payara Server exposes multiple HTTP-accessible EJB invocation mechanisms\nthat rely on attacker-controlled reflection, dynamic class loading, and\nunsafe deserialization. These endpoints allow remote clients to perform\narbitrary JNDI lookups, resolve attacker-supplied class names, and invoke\nEJB business methods via reflection without sufficient authorization\nenforcement or input restriction.\n\nBoth the deprecated InvokeEJBServlet and the EjbOverHttpResource\n(EJB-over-HTTP JAX-RS endpoint) implement the same insecure design pattern:\nuser-controlled inputs are used to select classes, methods, parameter\ntypes, and argument values, which are then executed reflectively inside the\napplication context. Deprecation does not disable or mitigate the exposure,\nleaving a powerful remote invocation surface reachable in production\ndeployments.\n\nAffected Components\n\n   -\n\n   *EJB-over-HTTP JAX-RS Resource*\n   -\n\n      Class: fish.payara.ejb.http.endpoint.EjbOverHttpResource\n      -\n\n      Paths:\n      -\n\n         /jndi/lookup\n         -\n\n         /jndi/invoke\n         -\n\n      Media Types: JSON / Java Serialization\n      -\n\n      Technology: JAX-RS / EJB / JNDI / Reflection / JSON-B\n      -\n\n   *Deprecated HTTP Servlet*\n   -\n\n      Component: fish.payara.ejb.invoke.InvokeEJBServlet\n      -\n\n      Servlet Mapping: /ejb/*\n      -\n\n      Status: Deprecated but registered, reachable, and functional\n\n\nAffected Versions\n\n   -\n\n   Payara Server versions that include and expose either:\n   -\n\n      InvokeEJBServlet, or\n      -\n\n      EjbOverHttpResource\n\n*Vulnerability Details:*\nThe affected endpoints perform a series of insecure operations that\ncollectively expose a powerful reflection-based invocation surface.\nUser-supplied jndiName values are passed directly to InitialContext.lookup,\nand the application context is dynamically switched based on parsed JNDI\ninput, enabling access to arbitrary EJBs within the target application and,\nin some cases, across application boundaries. Once a target EJB is\nresolved, attacker-controlled method names and parameter type names are\nprocessed using Java reflection, and Method.invoke() is executed on EJB\nproxies without any allowlisting, capability checks, or restriction to\nintended business methods. In parallel, parameter and return types are\nresolved using Class.forName() with the application\u2019s class loader,\nallowing resolution of any class visible within the application context.\nUser-supplied JSON payloads are then deserialized via JSON-B into\nattacker-chosen target types, creating a generic deserialization sink that\nfeeds directly into the reflective invocation flow. Authentication is\noptional and controlled by the client, while authorization failures do not\nconsistently terminate execution, allowing invocation logic to continue\nafter partial or failed security checks. Finally, detailed reflection and\ninvocation errors, such as NoSuchMethodException, are returned verbatim to\nthe client, disclosing internal EJB proxy class names, interface\nstructures, and method resolution behavior, which enables method and\ninterface enumeration and facilitates further exploitation.\n\n*Impact:*\nA remote attacker may be able to:\n\n   - Invoke arbitrary EJB business methods\n   - Access EJBs outside the intended application scope\n   - Bypass or weaken authorization controls\n   - Abuse JSON-B deserialization with attacker-chosen target types\n   - Enumerate internal classes, interfaces, and method signatures\n   - Trigger sensitive or administrative application functionality\n   - Potentially achieve remote code execution, depending on reachable\n   methods and classes\n   - The exposure of a generic reflection-based invocation primitive\n   significantly increases the attack surface of affected Payara deployments.\n\n\n\n*Vulnerable Code \u2014 EjbOverHttpResource:*\n*Attacker-Controlled JNDI Lookup*\nObject bean = service.getBean(jndiName);\n\n*Application Context Switching Based on User Input*\nString applicationName = jndiName.substring(12, jndiName.indexOf(\u0027/\u0027, 12));\nClassLoader appClassLoader = service.getAppClassLoader(applicationName);\nThread.currentThread().setContextClassLoader(appClassLoader);\n\n*Externally Controlled Class Resolution*\nClass.forName(name, true, Thread.currentThread().getContextClassLoader());\n\n*Reflection-Based Method Resolution*\nMethod method = findBusinessMethodDeclaration(\n    ejb,\n    request.method,\n    argTypes\n);\n\n*Reflection-Based Method Invocation*\nObject result = method.invoke(\n    ejb,\n    request.argDeserializer.deserialise(\n        request.argValues,\n        method,\n        argActualTypes,\n        Thread.currentThread().getContextClassLoader()\n    )\n);\n\n*Unsafe JSON-B Serialization / Type Handling*\nJsonbBuilder.create().toJson(result.result, returnType, output);\n\n*Information Disclosure via Reflection Errors*\nthrow new NoSuchMethodException(\n    \"No method matching \" + methodName + \"(\" +\n    Arrays.toString(argTypeClasses) + \") found\"\n);\n\n*Vulnerable Code \u2014 InvokeEJBServlet (Deprecated but Active):*\n\n*Attacker-Controlled JNDI Lookup (Direct \u0026 Cross-Application)*\nObject bean = new InitialContext().lookup(beanName);\n*And the cross-application fallback:*\nfor (String applicationName : registry.getAllApplicationNames()) {\n\ncurrentThread.setContextClassLoader(registry.get(applicationName).getAppClassLoader());\n    Object bean = new InitialContext().lookup(beanName);\n    return operation.execute(bean);\n}\n\n*Application Context Switching Based on User Input*\nString applicationName = beanName.substring(12, beanName.indexOf(\u0027/\u0027, 12));\ncurrentThread.setContextClassLoader(\n    registry.get(applicationName).getAppClassLoader()\n);\n\n*Externally Controlled Class Resolution*\nClass.forName(className, true,\nThread.currentThread().getContextClassLoader());\n(from toClass())\nprivate static Class\u003c?\u003e toClass(JsonValue classNameValue) {\n    String className = ((JsonString) classNameValue).getString();\n    return Class.forName(className, true,\n        Thread.currentThread().getContextClassLoader());\n}\n\n*Reflection-Based Method Resolution Using Attacker Input*\nthis.method = findBusinessMethodDeclaration(methodName, argTypeClasses);\nreturn intf.getMethod(methodName, argTypeClasses);\n\n*Reflection-Based Method Invocation*\nthis.result = method.invoke(bean, argValues);\n(from Invocation.invoke())\n\n*Unsafe JSON-B Deserialization into Attacker-Chosen Types*\nreturn jsonb.fromJson(objectValue.toString(), type);\n(from toObject())\nargValues[i] = toObject(jsonArgValues.get(i), argTypes[i]);\n(from toObjects())\n\n*Broken Authorization Enforcement (Execution Continues)*\nif (!request.isUserInRole(role)) {\n    response.setStatus(HttpServletResponse.SC_FORBIDDEN);\n}\n\n*Information Disclosure via Reflection Errors*\nthrow new NoSuchMethodException(\n    \"No method matching \" + methodName + \"(\" +\n    Arrays.toString(argTypeClasses) + \") found in business interface\"\n);\nAnd error propagation:\nresponse.sendError(\n    SC_INTERNAL_SERVER_ERROR,\n    \"Error while invoking invoking method \" + methodName +\n    \" on EJB with name \" + beanName + \": \" + ex.getMessage()\n);\n\n\n*Proof of Concept:*POST /ejb-invoke-1.0/ejb/ HTTP/1.1\nHost: localhost:8080\nContent-Type: application/json\n\n{\n  \"lookup\": \"java:global/ejb-invoke-1.0/TestBean\",\n  \"method\": \"exec\",\n  \"argTypes\": [\"java.lang.String\"],\n  \"argValues\": [\"test\"]\n}\n\n*Output:*\n\nHTTP/1.1 500 java.lang.NoSuchMethodException:\ntest.__EJB31_Generated__TestBean__Intf____Bean__.exec(java.lang.String)\nServer: Payara Server 6.2024.6 #badassfish\n\nRon Edgerson\nVulnerability Researcher \u0026 Exploit Developer\n\nCVE Research | Binary Exploitation | Application \u0026 Systems Security\nResponsible Disclosure \u2022 Proof-of-Concept Development\n\n\ud83c\udf10 https://github.com/ob1sec\n\ud83d\udd17 https://www.linkedin.com/in/ronedgerson1\n\u003chttps://linkedin.com/in/yourhandle\u003e\n_______________________________________________\nSent through the Full Disclosure mailing list\nhttps://nmap.org/mailman/listinfo/fulldisclosure\nWeb Archives \u0026 RSS: https://seclists.org/fulldisclosure/"
        }
      ],
      "providerMetadata": {
        "dateUpdated": "2026-09-09T13:03:50Z",
        "orgId": "4e2abfbf-4a2a-4b76-a4e0-d77c18ba156c",
        "shortName": "VULNARCHIVE"
      },
      "references": [
        {
          "tags": [
            "technical-description"
          ],
          "url": "https://vuln.freearchive.org/archive/full-disclosure/2026/Sep/18"
        },
        {
          "tags": [
            "technical-description"
          ],
          "url": "https://seclists.org/fulldisclosure/2026/Sep/18"
        },
        {
          "url": "https://github.com/ob1sec"
        },
        {
          "url": "https://linkedin.com/in/yourhandle"
        },
        {
          "url": "https://nmap.org/mailman/listinfo/fulldisclosure"
        },
        {
          "url": "https://seclists.org/fulldisclosure/"
        },
        {
          "url": "https://www.linkedin.com/in/ronedgerson1"
        }
      ],
      "source": {
        "defect": [
          "https://seclists.org/fulldisclosure/2026/Sep/18"
        ],
        "discovery": "EXTERNAL"
      },
      "title": "Payara 7.2026.1.RC1 Arbitrary EJB Method Invocation via Insecure Reflection in Payara Server",
      "x_gcve": [
        {
          "recordType": "advisory",
          "relationships": [],
          "vulnId": "GCVE-1988-2026-0006",
          "x_vulnarchive": {
            "archiveUrl": "https://vuln.freearchive.org/archive/full-disclosure/2026/Sep/18",
            "automated": true,
            "contentSha256": "182a7e08978a96dd01492ec11a69b1388632cbfd5842c19681d53697ec1d14f6",
            "evidenceScore": 7,
            "messageId": "",
            "originalUrl": "https://seclists.org/fulldisclosure/2026/Sep/18",
            "policy": "vulnarchive-1",
            "sourceFormat": "text/html",
            "sourcePublishedAt": "2026-08-30T23:50:19Z"
          }
        }
      ]
    }
  },
  "cveMetadata": {
    "assignerOrgId": "4e2abfbf-4a2a-4b76-a4e0-d77c18ba156c",
    "assignerShortName": "VULNARCHIVE",
    "datePublished": "2026-09-07T06:42:13Z",
    "dateUpdated": "2026-09-09T13:03:50Z",
    "state": "PUBLISHED",
    "vulnId": "GCVE-1988-2026-0006"
  },
  "dataType": "CVE_RECORD",
  "dataVersion": "5.2"
}



Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

Forecast uses a logistic model when the trend is rising, or an exponential decay model when the trend is falling. Fitted via linearized least squares.

Sightings

Author Source Type Date Other

Nomenclature

  • Seen: The vulnerability was mentioned, discussed, or observed by the user.
  • Confirmed: The vulnerability has been validated from an analyst's perspective.
  • Published Proof of Concept: A public proof of concept is available for this vulnerability.
  • Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
  • Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
  • Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
  • Not confirmed: The user expressed doubt about the validity of the vulnerability.
  • Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.

Loading…

Detection rules are retrieved from Rulezet.

Loading…

Loading…

Loading…