Jul 23, 2026·6 min read·5 visits
c3p0 versions prior to 0.14.0 contain a deserialization gadget where JavaBean introspectors trigger getConnection() or getPooledConnection() on deserialized DataSources, leading to RCE via malicious JDBC URLs or JNDI lookups.
An untrusted deserialization vulnerability exists in the c3p0 JDBC connection pooling library before version 0.14.0. Standard JDBC getter methods conform to the JavaBean property getter pattern, allowing introspection libraries like Apache Commons BeanUtils to evaluate connection properties dynamically during deserialization, leading to arbitrary code execution when chained with a vulnerable database driver or JNDI sink.
The open-source library c3p0 serves as a JDBC connection pooling manager in enterprise Java applications. By automating the creation, reuse, and disposal of database connections, it optimizes application performance and database interaction. The library exposes public classes that implement the standard JDBC javax.sql.DataSource and javax.sql.ConnectionPoolDataSource interfaces to allow seamless integration into enterprise frameworks.\n\nBecause c3p0 functions within complex enterprise application containers, its classes are frequently instantiated, configured, and serialized. To facilitate runtime properties management, modern frameworks heavily depend on dynamic serialization and JavaBean introspection. This architecture relies on the implicit trust of underlying property names and getter methods, exposing a wide attack surface if untrusted inputs influence object configuration.\n\nIn environments where c3p0 is present on the application classpath alongside an introspection-driven deserialization library, this architectural design introduces a critical weakness. An attacker who is able to submit crafted serialized Java objects can exploit the trust relationship between dynamic reflection and connection configuration. This vulnerability allows an attacker to control the target database URI and trigger connection attempts, leading to remote code execution under specific circumstances.
The root cause of this vulnerability lies in the conflict between the standard JavaBean design conventions and the JDBC specification. Under standard JavaBean rules, any public parameterless method starting with get followed by an uppercase letter is interpreted as a getter for a readable property. When JavaBean helper libraries like Apache Commons BeanUtils scan a class, they translate these getter methods into readable and writable properties.\n\nIn the JDBC specification, the javax.sql.DataSource interface defines the getConnection() method to obtain a database connection, while the javax.sql.ConnectionPoolDataSource interface defines getPooledConnection(). Because these methods match the standard getter signature, standard JDK java.beans.Introspector registers connection and pooledConnection as readable properties. Consequently, utility methods that dynamically query properties will implicitly execute the database connection process.\n\nDuring standard deserialization of dynamic objects, libraries like Apache Commons BeanUtils utilize a BeanComparator to evaluate and compare properties across objects. When a deserialized payload triggers a comparison, the comparator invokes the configured property getter via reflection. If the compared target is a c3p0 DataSource, resolving the connection property forces a call to getConnection(), triggering an active TCP connection to an attacker-controlled endpoint.
The developer addressed the vulnerability in version 0.14.0 by introducing a custom BeanInfo code generation mechanism to modify the exposed metadata of c3p0 classes. In Java, providing an explicit BeanInfo implementation in the same package as the target bean class overrides the automatic reflective discovery performed by the JDK Introspector. The class C3P0BeanInfoGen generates these descriptor files during the project's build phase.\n\njava\npackage com.mchange.v2.c3p0.beaninfo;\n\nimport java.io.*;\nimport java.util.Collections;\nimport java.util.HashSet;\nimport java.util.Set;\nimport com.mchange.v2.codegen.bean.BeanInfoGen;\n\nimport static java.nio.charset.StandardCharsets.UTF_8;\n\npublic final class C3P0BeanInfoGen\n{\n final static Set excludedPropertyNames;\n final static Set excludedPropertyTypes;\n\n static\n { \n // Explicitly blacklists the dangerous property names to hide them\n Set tmp0 = new HashSet();\n tmp0.add(\"connection\");\n tmp0.add(\"pooledConnection\");\n excludedPropertyNames = Collections.unmodifiableSet(tmp0);\n\n // Explicitly blacklists return types that trigger database interactions\n Set tmp1 = new HashSet();\n tmp1.add( java.sql.Connection.class );\n tmp1.add( javax.sql.PooledConnection.class );\n excludedPropertyTypes = Collections.unmodifiableSet(tmp1);\n }\n // ... (rest of code generation logic follows)\n}\n\n\nBy generating explicit BeanInfo descriptors that exclude the connection and pooledConnection properties, standard JavaBean reflection libraries can no longer find these properties. Consequently, attempts to dynamically resolve the \"connection\" property result in a standard property-not-found exception rather than executing the underlying database connection method. This mechanism cleanly severs the link between JavaBean introspection and JDBC execution, neutralizing the deserialization gadget path.
Exploitation of this vulnerability requires the presence of specific dependencies on the target application's classpath. The primary prerequisite is an active deserialization vector that parses attacker-supplied object streams. Additionally, an introspection-based deserialization carrier such as Apache Commons BeanUtils must be present to bridge the gap between deserialization and getter invocation.\n\nmermaid\ngraph LR\n A[\"Serialized Payload\"] --> B[\"PriorityQueue.readObject()\"]\n B --> C[\"BeanComparator.compare()\"]\n C --> D[\"PropertyUtils.getProperty()\"]\n D --> E[\"ComboPooledDataSource.getConnection()\"]\n E --> F[\"Remote Exploit Execution\"]\n\n\nThe attack sequence begins when the target system deserializes a crafted payload containing a PriorityQueue configured with a BeanComparator. During queue rebuilding, the comparator executes dynamic property resolution on the elements. This action triggers getConnection() on the deserialized c3p0 DataSource, forcing the library to establish a connection to the configured JDBC URL. The attacker controls this URL, pointing it to a rogue database (e.g., an H2 instance executing custom SQL command scripts) or an external JNDI service to load malicious byte code.\n\nBecause the exploit relies on third-party drivers or JNDI sinks to execute commands, the payload composition varies based on the classpath of the target. For instance, if the H2 database driver is present, the connection URL triggers SQL script evaluation, executing commands via a user-defined alias. Alternatively, a JNDI-backed DataSource configuration allows loading arbitrary class files via LDAP or RMI lookups.
The immediate impact of successful exploitation is remote code execution in the context of the running Java Virtual Machine. An attacker who successfully delivers a weaponized payload can run arbitrary system commands, potentially leading to a complete compromise of the underlying application server and hosting infrastructure.\n\nWhile the CVSS Base Score is calculated at 6.3, this reflects the moderate rating of c3p0 itself since the connection pooling library functions as an intermediate gadget rather than the final execution context. However, in practice, the technical severity depends on the classpath environment. If a vulnerable database driver or unmitigated JNDI sink is available, the impact escalates directly to a critical system compromise.\n\nFurthermore, the confidentiality, integrity, and availability of database assets connected to the application are severely threatened. Once code execution is achieved, the attacker can extract application database credentials, modify operational data, or disrupt business services by executing denial-of-service commands on host systems.
To resolve the vulnerability, developers must upgrade the c3p0 connection pooling library to version 0.14.0 or newer. Upgrading ensures that the built-in BeanInfo files are present on the classpath, blocking reflective utilities from locating the connection-triggering properties.\n\nIf upgrading is not immediately possible, temporary workarounds should be applied to restrict the deserialization attack surface. The application should be configured to reject Java serialized objects from untrusted sources, transitioning to secure serialization alternatives like JSON or Protocol Buffers. Additionally, deploying look-ahead deserialization firewalls or custom ObjectInputStream filters can prevent the instantiation of dangerous classes like BeanComparator or c3p0 DataSources.\n\nEgress filtering must also be implemented on target servers to block unexpected outbound TCP connections. Restricting outbound connections to authorized database ports prevents the target from connecting to rogue external servers or fetching remote payloads via JNDI or HTTP channels.
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:L/VI:L/VA:L/SC:N/SI:N/SA:N| Product | Affected Versions | Fixed Version |
|---|---|---|
c3p0 Steve Waldman | < 0.14.0 | 0.14.0 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-502 / CWE-915 |
| Attack Vector | Network |
| CVSS v4.0 Score | 6.3 |
| EPSS Score | 0.00284 |
| Exploit Status | Proof-of-Concept |
| KEV Status | Not Listed |
The application deserializes untrusted serialization streams without validating that the incoming objects are safe.
CVE-2026-53467 is a heap information disclosure vulnerability in the Multiple-image Network Graphics (MNG) decoder of ImageMagick. The vulnerability arises from a failure to zero-initialize newly allocated pixel cache memory buffers. A remote attacker can exploit this by submitting a crafted sparse MNG image file to trigger uninitialized memory preservation. The resulting output contains residual heap bytes, potentially leaking sensitive process memory or assisting in ASLR bypass.
A heap-based buffer overflow vulnerability exists in the native C extension of the Ruby json gem (versions 2.9.0 through 2.19.8) during IO-based streaming serialization. An incorrect buffer size calculation can lead to memory corruption and process termination when processing large strings.
An uncontrolled memory allocation vulnerability (CWE-789) exists in pypdf prior to version 6.14.0. The library blindly trusted user-controlled image dimensions (/Width and /Height) from PDF metadata, allowing attackers to trigger physical memory exhaustion and an Out-of-Memory crash via tiny, malformed files.
An infinite loop vulnerability exists in the pure-python PDF library pypdf prior to version 6.14.1. This vulnerability occurs during the processing of malformed or truncated page content streams containing inline images. Specifically, the parser fails to validate the End-of-Stream condition during inline image dictionary parsing. This results in continuous backward stream-seeking and an infinite loop that consumes 100% CPU on the processing thread.
An infinite loop vulnerability exists in the pypdf library prior to version 6.14.2 when processing malformed PDF inline images that utilize ASCII85 or ASCIIHex decoders. Attackers can exploit this vulnerability by submitting crafted PDF files containing incomplete streams, causing the parsing thread to consume 100% CPU resource indefinitely and leading to Denial of Service.
A critical CPU exhaustion vulnerability exists in the pypdf library before version 6.14.0. When parsing PDF files with malformed or corrupt standard cross-reference (xref) table entries, the library falls back to sequentially scanning the entire file buffer via regular expression search. An attacker can exploit this algorithmic bottleneck by supplying a crafted PDF with numerous malformed xref entries, leading to denial of service.