The vulnerability exists due to an unsafe logging practice within the Apache CXF framework. When the DelayedCachedOutputStreamCleaner thread detects a leaked stream (an unclosed CachedOutputStream), it attempts to log a warning message. The vulnerable code concatenates the CachedOutputStream object directly into the log string: LOG.warning("Unclosed (leaked?) stream detected: " + next.closeable);. This action triggers the toString() method on the CachedOutputStream object.
The CachedOutputStream.toString() method is implemented to provide a string representation of the stream's content for debugging purposes. It does this by reading the entire stream—which for large payloads is spooled to a temporary file on disk—into memory. This behavior has two critical security implications:
- Denial of Service (DoS): An attacker can send a large payload, which gets written to a temporary file. By intentionally leaking this stream, they trigger the cleaner thread. The subsequent call to
toString() attempts to load the entire large file into memory, which can exhaust the heap space and cause an OutOfMemoryError, crashing the application.
- Information Disclosure: CXF allows for the encryption of these temporary files to protect sensitive data at rest. However, the
toString() method reads the decrypted content of the stream. This means that if an encrypted temporary file is logged via this vulnerability, its sensitive contents will be written to the logs in plaintext.
The fix applied in the patch replaces the logging of the object itself with its hash code (next.closeable.hashCode()). This avoids calling the expensive and unsafe toString() method, thus mitigating both the DoS and the information disclosure risks. The key functions in the execution of this vulnerability are DelayedCachedOutputStreamCleaner.clean(), which initiates the logging, and CachedOutputStream.toString(), which performs the unsafe operation of reading the entire file into memory.