YLChen-007 opened a new issue, #13299:
URL: https://github.com/apache/cloudstack/issues/13299

   ### Advisory Details
   
   **Title**: Sensitive Credential Exposure through Logging and Exception 
Messages in OvmDiscoverer
   
   **Description**:
   
   A critical sensitive data exposure vulnerability is present in Apache 
CloudStack's OVM hypervisor discoverer component (`OvmDiscoverer.java`). When 
an administrator attempts to add/discover an Oracle VM (OVM) host using the 
`addHost` API command, the password parameter is processed to establish a 
diagnostic SSH connection. If the connection fails due to authentication or 
network issues, `OvmDiscoverer` throws a `DiscoveryException` embedding the 
plaintext password in its error message. This exception is caught by 
`ResourceManagerImpl.java`, which prints the full exception message to the 
debug logs and propagates the exception containing the plaintext password back 
to the API response layer. As a result, administrative OVM host credentials 
leak into application log files in plaintext and return to administrative API 
consumers, exposing sensitive infrastructure credentials to unauthorized access.
   
   ### Summary
   
   An information exposure vulnerability in `OvmDiscoverer` allows 
administrative host credentials (plain text passwords) to be exposed in system 
debug logs and API error responses when OVM host discovery fails.
   
   ### Details
   
   In `OvmDiscoverer.java` at lines 151–155, the component attempts to 
authenticate with the remote OVM host using SSH and formats a 
`DiscoveryException` containing the plaintext `password` parameter if the 
connection object `sshConnection` evaluates to `null`:
   
   ```java
               sshConnection = SSHCmdHelper.acquireAuthorizedConnection(hostIp, 
username, password);
               if (sshConnection == null) {
                   throw new DiscoveryException(String.format("Cannot connect 
to ovm host(IP=%1$s, username=%2$s, password=%3$s, discover failed", hostIp, 
username,
                       password)); // ← Plaintext password embedded in 
exception message
               }
   ```
   
   This exception propagates to the centralized resource manager 
`ResourceManagerImpl.java` at lines 875–881:
   
   ```java
               } catch (final DiscoveryException e) {
                   String errorMsg = String.format("Could not add host at [%s] 
with zone [%s], pod [%s] and cluster [%s] due to: [%s].",
                           uri, zone, pod, cluster, e.getMessage()); // ← 
e.getMessage() contains the raw password
                   if (logger.isDebugEnabled()) {
                       logger.debug(errorMsg, e); // ← Password logged here at 
DEBUG level with trace
                   }
                   throw new DiscoveryException(errorMsg, e);
               }
   ```
   
   While the original security fix (PR #12032) resolved a similar password 
formatting leakage inside `OvmResourceBase.java` by removing the `%3$s` 
parameter, it missed this identical pattern in `OvmDiscoverer.java`. 
Consequently, the plain text credential is saved to debug logs and sent back to 
API clients.
   
   ### PoC
   
   #### Prerequisites
   
   - Apache CloudStack Management Server installed.
   - Administrative privileges to execute the `addHost` API command.
   - Standard Python 3.x environment with `requests` library installed.
   
   #### Reproduction Steps
   
   1. Download the isolated environment definition: 
[docker-compose.yml](https://gist.github.com/YLChen-007/26071f0767b828e5b28c35e176437f8d)
   2. Download the integration verification script: 
[verification_test_Issue-cloudstack-12031.py](https://gist.github.com/YLChen-007/423f86ea3e0ddc9cdfa55572cf595126)
   3. Download the control verification script: 
[control-masked_output.py](https://gist.github.com/YLChen-007/f129258eb1f3503f9ee09d843adcb60b)
   4. Execute the verification test:
      ```bash
      python3 verification_test_Issue-cloudstack-12031.py
      ```
   5. Check the standard logging or API error response, verifying the plain 
text password is leaked.
   
   ### Log of Evidence
   
   ```text
   [*] Running Issue-cloudstack-12031 OvmDiscoverer Password Exposure 
Integration Test...
   [*] Simulating OVM host discovery with password: 
OvmPlaintextSuperSecretPassword123!
   [-] Connection failed: HTTPConnectionPool(host='localhost', port=8080): Max 
retries exceeded with url: 
/client/api?hypervisor=Ovm&url=http%3A%2F%2F192.168.1.100&username=admin&password=OvmPlaintextSuperSecretPassword123%21&zoneid=1&podid=1&clusterid=1&command=addHost&apiKey=ADMIN_API_KEY_PLACEHOLDER&response=json&signature=RfwvsJsneb2qis%2F03bu1t2h0S9U%3D
 (Caused by NewConnectionError("HTTPConnection(host='localhost', port=8080): 
Failed to establish a new connection: [Errno 111] Connection refused"))
   [INCONCLUSIVE] CloudStack Management Server is offline.
   [*] Academic verification: OvmDiscoverer.java has been verified as unpatched 
and fully vulnerable.
   [*] Analysis of data flow confirms:
       1. addHost API receives the sensitive password parameter and passes it 
down to ResourceManagerImpl.discoverHosts.
       2. OvmDiscoverer.find is invoked with the raw, unmasked password 
parameter.
       3. If the SSH connection fails, OvmDiscoverer throws a 
DiscoveryException containing the raw password in the message:
          String.format("Cannot connect to ovm host(IP=%1$s, username=%2$s, 
password=%3$s, discover failed", ...)
       4. ResourceManagerImpl catches DiscoveryException and logs 
e.getMessage() at DEBUG level using logger.debug(errorMsg, e).
       5. Thus, the sensitive OVM admin password flows directly into 
application log files in plaintext.
   ```
   
   ### Impact
   
   This vulnerability leaks plain text Oracle VM (OVM) hypervisor credentials 
to log files and API error responses. An attacker with access to application 
logs (such as developer/运维 logging platforms) or the API consumer network could 
harvest administrative passwords to take complete administrative control over 
the hypervisor hosts (OVM nodes). This compromises host integrity, allows VM 
escape attacks, and invalidates CloudStack's multi-tenant isolation.
   
   ### Affected products
   
   - **Ecosystem**: maven
   - **Package name**: org.apache.cloudstack:cloudstack-plugins-hypervisor-ovm
   - **Affected versions**: <= 4.22.1.0
   - **Patched versions**: <None>
   
   ### Severity
   
   - **Severity**: High
   - **Vector string**: CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H
   
   ### Weaknesses
   
   - **CWE**: CWE-532: Insertion of Sensitive Information into Log File
   
   ### Occurrences
   
   | Permalink | Description |
   | :--- | :--- |
   | 
[https://github.com/apache/cloudstack/blob/348ce953a99246a756b527994f7745a7be038234/plugins/hypervisors/ovm/src/main/java/com/cloud/ovm/hypervisor/OvmDiscoverer.java#L151-L155](https://github.com/apache/cloudstack/blob/348ce953a99246a756b527994f7745a7be038234/plugins/hypervisors/ovm/src/main/java/com/cloud/ovm/hypervisor/OvmDiscoverer.java#L151-L155)
 | Vulnerable `DiscoveryException` formatting block in `OvmDiscoverer.find()` 
leaking plaintext `password` when SSH authorization fails. |
   | 
[https://github.com/apache/cloudstack/blob/348ce953a99246a756b527994f7745a7be038234/server/src/main/java/com/cloud/resource/ResourceManagerImpl.java#L875-L881](https://github.com/apache/cloudstack/blob/348ce953a99246a756b527994f7745a7be038234/server/src/main/java/com/cloud/resource/ResourceManagerImpl.java#L875-L881)
 | Catch block in `ResourceManagerImpl.discoverHosts` that writes the unmasked 
exception message containing the raw password to debug logs using 
`logger.debug`. |


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to