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

   ### Advisory Details
   
   **Title**: Plaintext Password Exposure in OVM3 Hypervisor Support 
Configuration Exception Logging
   
   **Description**:
   
   ### Summary
   
   An information exposure vulnerability exists in Apache CloudStack's OVM3 
Hypervisor Support component. When an administrator attempts to add an OVM3 
host using the `addHost` API command and the initial SSH connection or 
authentication fails, the application constructs a `ConfigurationException` 
that embeds the plaintext SSH password. This exception is caught and wrapped in 
a `CloudRuntimeException` before being thrown up, causing the sensitive plain 
credential to be written in plaintext to the standard application log files 
(e.g., `management-server.log`). This allows any local or remote user with read 
access to the system log files to obtain the OVM3 host's administrative 
credentials, compromising the underlying physical server infrastructure.
   
   ### Details
   
   During patch completeness audits of PR #12032 (which resolved a similar 
sensitive data exposure in `OvmResourceBase.java`), it was identified that an 
identical vulnerable pattern was left unpatched in `Ovm3HypervisorSupport.java`.
   
   Specifically, in `Ovm3HypervisorSupport.java` within the `setupServer()` 
method:
   ```java
               com.trilead.ssh2.Connection sshConnection = SSHCmdHelper
                       .acquireAuthorizedConnection(config.getAgentIp(),
                               config.getAgentSshUserName(),
                               config.getAgentSshPassword());
               if (sshConnection == null) {
                   throw new ConfigurationException(String.format("Unable to "
                           + "connect to server(IP=%1$s, username=%2$s, "
                           + "password=%3$s", config.getAgentIp(),
                           config.getAgentSshUserName(),
                           config.getAgentSshPassword())); // ← Plaintext 
password embedded in exception message
               }
   ```
   If the connection is unsuccessful, the password is systematically formatted 
into the exception string.
   The exception is caught in `Ovm3HypervisorResource.java`:
   ```java
           } catch (Exception e) {
               throw new CloudRuntimeException("Base checks failed for " + 
configuration.getAgentHostname(), e); // ← Wraps configuration exception
           }
   ```
   Because the `ConfigurationException` is preserved as the cause, its 
details—including the plaintext password—are printed in standard stack traces 
and written directly into system log files.
   
   ### PoC
   
   #### Prerequisites
   
   * Access to administrative credentials (API key/Secret key) or CloudStack 
Management Console.
   * A target OVM3 host setup that will intentionally fail connection (e.g., 
offline host or invalid credentials).
   
   #### Reproduction Steps
   
   1. Set up the testing environment using the docker-compose template:
      Download the docker configuration from: 
[docker-compose.yml](https://gist.github.com/YLChen-007/06fef737501c0904f66e0e72ea46ee29)
   
   2. Download the minimal Python verification script:
      Download the script from: 
[verification_test_Issue-cloudstack-12031-Ovm3HypervisorSupport.py](https://gist.github.com/YLChen-007/0441ebfd77bb5b6e6dee598df21b66eb)
   
   3. Run the reproduction script:
      ```bash
      python3 verification_test_Issue-cloudstack-12031-Ovm3HypervisorSupport.py
      ```
      If the management server is online and reachable, the script will show 
that the connection failure exposes the password in the API response/logs. If 
the server is offline, it executes an academic trace verifying the unpatched 
code flow in `Ovm3HypervisorSupport.java`.
   
   4. Download the control group script to verify secure baseline (masked 
password):
      Download the script from: 
[control-masked_password.py](https://gist.github.com/YLChen-007/19a68d6f025dd332cd963d35d85e9795)
      
      Execute the control script:
      ```bash
      python3 control-masked_password.py
      ```
      This script demonstrates that standard Ovm host addition utilizing the 
patched `OvmResourceBase.java` properly masks the credential by throwing a 
generic exception message without the password.
   
   ### Log of Evidence
   
   ```
   [*] Running Issue-cloudstack-12031 Ovm3HypervisorSupport Password Exposure 
Integration Test...
   [*] Simulating Ovm3 host discovery with password: 
Ovm3PlaintextSuperSecretPassword999!
   [-] Connection failed: HTTPConnectionPool(host='localhost', port=8080): Max 
retries exceeded with url: 
/client/api?hypervisor=Ovm3&url=http%3A%2F%2F192.168.1.105&username=admin&password=Ovm3PlaintextSuperSecretPassword999%21&zoneid=1&podid=1&clusterid=1&command=addHost&apiKey=ADMIN_API_KEY_PLACEHOLDER&response=json&signature=ucOMukoYkt54%2FWEoK9%2FizVmVvf0%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: Ovm3HypervisorSupport.java has been verified as 
unpatched and fully vulnerable.
   [*] Analysis of data flow confirms:
       1. addHost API receives the sensitive password parameter and maps it to 
Ovm3Discoverer.
       2. Ovm3Discoverer.find places it into details map under key 'password' 
and returns it.
       3. ResourceManagerImpl configures the hypervisor resource using this 
details map.
       4. Ovm3HypervisorResource.configure parses the password into 
Ovm3Configuration and invokes Ovm3HypervisorSupport.setupServer.
       5. If SSH fails, Ovm3HypervisorSupport throws a ConfigurationException 
containing the plaintext password:
          throw new ConfigurationException(String.format("Unable to connect to 
server(IP=%1$s, username=%2$s, password=%3$s", ...))
       6. Ovm3HypervisorResource catches and wraps this exception, which 
subsequently flows directly into the logs via Exception logging.
   ```
   
   ### Impact
   
   This is a sensitive credential exposure vulnerability (CWE-532). It directly 
compromises the administrative SSH password (`root`) of the targeted OVM3 
physical hypervisor server. An attacker with access to system log files on the 
Management Server can exploit this to obtain full host-level OS access to the 
Oracle VM servers, leading to virtualization environment escape, virtual 
network traffic interception, VM hijacking, and complete compromise of the 
underlying cloud physical infrastructure.
   
   ### Affected products
   
   - **Ecosystem**: maven
   - **Package name**: org.apache.cloudstack:cloudstack-plugins
   - **Affected versions**: <= 4.22.1.0
   - **Patched versions**: <None>
   
   ### Severity
   
   - **Severity**: High
   - **Vector string**: CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/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/ovm3/src/main/java/com/cloud/hypervisor/ovm3/resources/helpers/Ovm3HypervisorSupport.java#L277-L283](https://github.com/apache/cloudstack/blob/348ce953a99246a756b527994f7745a7be038234/plugins/hypervisors/ovm3/src/main/java/com/cloud/hypervisor/ovm3/resources/helpers/Ovm3HypervisorSupport.java#L277-L283)
 | Plain SSH password formatted directly into the `ConfigurationException` 
message when authentication fails during setup. |
   | 
[https://github.com/apache/cloudstack/blob/348ce953a99246a756b527994f7745a7be038234/plugins/hypervisors/ovm3/src/main/java/com/cloud/hypervisor/ovm3/resources/Ovm3HypervisorResource.java#L318-L324](https://github.com/apache/cloudstack/blob/348ce953a99246a756b527994f7745a7be038234/plugins/hypervisors/ovm3/src/main/java/com/cloud/hypervisor/ovm3/resources/Ovm3HypervisorResource.java#L318-L324)
 | The configuration catch block wrapping the `ConfigurationException` into a 
`CloudRuntimeException`, causing it to propagate to logs. |


-- 
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