Keystore Password and CIFS Credentials Plaintext Exposure via SSH Command Logging in KVM CA Provisioning and Baremetal PXE
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 4/5
- Tiempo estimado
- 3-5 días
- Aptitud para principiantes
- 48/100
- Tipo de issue
- Error
- Claridad
- Bastante claro
- Estado de actividad
- Tranquilo
- Área
- backend, infrastructure, security
Línea de trabajo
Comienza con SSHCmdHelper.java y sigue el recorrido de sshExecuteCmdOneShot(); después, inspecciona la construcción de comandos y el manejo de fallos en CAManagerImpl.java y BaremetalPingPxeResource.java. Usa verification_test.py y control-masked_output.py para reproducir el comportamiento del registro. Se considera terminado cuando las credenciales de keystore y CIFS están ausentes de los registros de depuración y de las respuestas de error de PXE.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
Advisory Details
Title: Keystore Password and CIFS Credentials Plaintext Exposure via SSH Command Logging in KVM CA Provisioning and Baremetal PXE
Description:
Summary
A critical sensitive information disclosure vulnerability (CWE-532 / CWE-209) exists in the Apache CloudStack Management Server due to flawed, position-dependent, and incomplete sanitization of SSH command logs. Highly sensitive credentials—specifically, dynamically-generated 16-character KVM keystore passwords and administrator-configured CIFS/Samba storage credentials—are logged in plaintext into the Management Server debug log files. Furthermore, during PXE command failures, the plaintext CIFS password is returned directly in the REST API error payload to the client.
Details
The core command-logging desensitization mechanism in SSHCmdHelper.java employs a naive split-token sanitization method to prevent credentials from entering debug logs:
LOGGER.debug("Executing cmd: " + cmd.split(KeyStoreUtils.KS_FILENAME)[0]);
Here, KeyStoreUtils.KS_FILENAME is the hardcoded string "cloud.jks". This sanitization model assumes that any sensitive parameter in the command string will always follow the "cloud.jks" token. This design fails under two distinct reachable paths in the codebase:
1. Core KVM Host CA Certificate Provisioning (CAManagerImpl.java)
During forced agent certificate updates via the provisionCertificate admin API, the certificate import shell command is generated as follows:
final SetupCertificateCommand certificateCommand = new SetupCertificateCommand(certificate);
final SSHCmdHelper.SSHCmdResult setupCertResult = SSHCmdHelper.sshExecuteCmdWithResult(sshConnection,
String.format("sudo /usr/share/cloudstack-common/scripts/util/%s " +
"/etc/cloudstack/agent/agent.properties %s " +
"/etc/cloudstack/agent/%s %s " +
...
KeyStoreUtils.KS_IMPORT_SCRIPT,
keystorePassword, // <-- Positional parameter before KS_FILENAME
KeyStoreUtils.KS_FILENAME,
KeyStoreUtils.SSH_MODE,
...));
Because the dynamic plaintext keystorePassword is positioned before "cloud.jks", cmd.split("cloud.jks")[0] evaluates to a string that still contains the plaintext password, causing it to be written directly into the debug logs.
2. Baremetal PXE Template Operations (BaremetalPingPxeResource.java)
When setting up or backing up baremetal PXE resources, helper scripts like prepare_tftp_bootfile.py are executed via SSH with the CIFS storage server password (_cifsPassword) passed as an argument:
String script =
String.format("python /usr/bin/prepare_tftp_bootfile.py restore %1$s %2$s %3$s %4$s %5$s %6$s %7$s %8$s %9$s %10$s %11$s", _tftpDir, cmd.getMac(),
_storageServer, _share, _dir, cmd.getTemplate(), _cifsUserName, _cifsPassword, cmd.getIp(), cmd.getNetMask(), cmd.getGateWay());
Because these command strings do not contain the "cloud.jks" token, the naive split operation evaluates to the entire original command, fully exposing the _cifsPassword in the logs. Furthermore, if the command fails, the exception returned to the caller (PreparePxeServerAnswer or Answer) appends the raw command containing the password, propagating it back in the REST API payload to the administrator.
PoC
Prerequisites
- A deployed instance of the CloudStack Management Server.
- API Key and Secret Key for an administrator account.
- A KVM host or Baremetal PXE server configured in the workspace.
Reproduction Steps
- Download the isolated container database and helper environment config from: docker-compose.yml
- Download the active integration verification test script from: verification_test.py
- Download the baseline control test script from: control-masked_output.py
- Start the laboratory background services:
docker compose up -d - Execute the verification test to demonstrate the plaintext credential logging:
python3 verification_test.py - Execute the control test to verify that the split mechanism functions correctly under baseline conditions (i.e., when
cloud.jksprecedes the password):python3 control-masked_output.py
Log of Evidence
=========================================================================
[*] Running Issue-cloudstack-12029 Keystore Password Exposure Verification
=========================================================================
[*] Stage 1: Attempting to connect to running CloudStack Management Server...
[!] CloudStack Management Server is offline (Expected in isolated environment).
[*] Switching to Academic/Logical Code-Path Verification...
--- Flow 1: CA Certificate Provisioning ---
Original constructed command:
sudo /usr/share/cloudstack-common/scripts/util/keystore-cert-import /etc/cloudstack/agent/agent.properties SecretRandomPassword123! /etc/cloudstack/agent/cloud.jks ssh /etc/cloudstack/agent/cloud.crt "CERT_DATA"
Logged command after split(KS_FILENAME)[0]:
sudo /usr/share/cloudstack-common/scripts/util/keystore-cert-import /etc/cloudstack/agent/agent.properties SecretRandomPassword123! /etc/cloudstack/agent/
🔴 [DEFECT-CONFIRMED] Plaintext password is fully exposed in Flow 1 log output!
--- Flow 2: Baremetal PXE template preparation ---
Original constructed command:
python /usr/bin/prepare_tftp_bootfile.py restore /var/lib/tftpboot 00:11:22:33:44:55 192.168.1.100 share_name /tftp_dir template_name admin_user CifsSecretPassword999! 192.168.1.101 255.255.255.0 192.168.1.254
Logged command after split(KS_FILENAME)[0]:
python /usr/bin/prepare_tftp_bootfile.py restore /var/lib/tftpboot 00:11:22:33:44:55 192.168.1.100 share_name /tftp_dir template_name admin_user CifsSecretPassword999! 192.168.1.101 255.255.255.0 192.168.1.254
🔴 [DEFECT-CONFIRMED] Plaintext CIFS password is fully exposed in Flow 2 log output!
=========================================================================
RESULT: DEFECT-CONFIRMED (TRUE POSITIVE)
=========================================================================
=========================================================================
[*] Running Issue-cloudstack-12029 Control Group Test: Masked Output Baseline
=========================================================================
Control group command (cloud.jks placed before password):
sudo /usr/share/cloudstack-common/scripts/util/keystore-cert-setup /etc/cloudstack/agent/agent.properties /etc/cloudstack/agent/cloud.jks SecretRandomPassword123! 365 /etc/cloudstack/agent/cloud.csr
Logged command after split(KS_FILENAME)[0]:
sudo /usr/share/cloudstack-common/scripts/util/keystore-cert-setup /etc/cloudstack/agent/agent.properties /etc/cloudstack/agent/
--- Control Group Verification ---
🟢 [CONTROL-SUCCESS] Plaintext password is successfully masked/omitted from the log!
The security mechanism functions correctly under normal/baseline conditions.
=========================================================================
Impact
- Vulnerability Type: CWE-532 (Insertion of Sensitive Information into Log File) / CWE-209 (Generation of Error Message Containing Sensitive Information)
- Compromised Assets: KVM host CA keystore private keys, administrative CIFS/Samba storage credentials.
- Severity Impact: High. Exposure of keystore passwords allows remote actors with system read access to decrypt agent TLS private keys and compromise hypervisor agent communication (e.g. performing MITM and executing arbitrary VM manipulation commands). Exposure of CIFS credentials gives complete read-write access to private cloud system template repositories on the corporate network.
Affected products
- Ecosystem: maven
- Package name: org.apache.cloudstack:cloudstack
- Affected versions:
<= 4.22.1.0(up to unreleased pre-release state on themainbranch) - Patched versions:
Severity
- Severity: High
- Vector string: CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:N
Weaknesses
- CWE: CWE-532: Insertion of Sensitive Information into Log File
- CWE: CWE-209: Generation of Error Message Containing Sensitive Information
Occurrences
| Permalink | Description |
|---|---|
| utils/src/main/java/com/cloud/utils/ssh/SSHCmdHelper.java#L167 | Naive command sanitization using cmd.split(KeyStoreUtils.KS_FILENAME)[0] in sshExecuteCmdOneShot(). |
| utils/src/main/java/com/cloud/utils/ssh/SSHCmdHelper.java#L230 | Naive command sanitization in the standard output/error logging statement in sshExecuteCmdOneShot(). |
| server/src/main/java/org/apache/cloudstack/ca/CAManagerImpl.java#L278-L294 | Certificate import command creation in provisionCertificateViaSsh(), positioning keystorePassword before the split-token. |
| plugins/hypervisors/baremetal/src/main/java/com/cloud/baremetal/networkservice/BaremetalPingPxeResource.java#L155-L160 | Construction and execution of Baremetal PXE TFTP restore command passing _cifsPassword without split-token and returning it in answer payload on failure. |
| plugins/hypervisors/baremetal/src/main/java/com/cloud/baremetal/networkservice/BaremetalPingPxeResource.java#L184-L189 | Construction and execution of Baremetal PXE TFTP backup command passing _cifsPassword without split-token and returning it in answer payload on failure. |
- Lenguaje dominante
- Java
- Estrellas
- 3.1k
- Forks
- 1.4k
- Merge medio
- 6 d 20 h
- PR fusionados (30 d)
- 27
Guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de apache/cloudstack
-
bug
Dificultad 1/5 Menos de una hora Aptitud para principiantes 90/100
apache/cloudstack#14222 ·
-
create-kubernetes-binaries-iso.sh builds the ISO without setting a volume ID on EL8 based os's Abiertobug component:kubernetes
Dificultad 1/5 Menos de una hora Aptitud para principiantes 88/100
apache/cloudstack#14180 ·
-
bug component:projects component:UI
Dificultad 1/5 Menos de una hora Aptitud para principiantes 88/100
apache/cloudstack#14070 · 5 comentarios ·
-
component:backup
Dificultad 2/5 1-3 horas Aptitud para principiantes 76/100
apache/cloudstack#14013 ·
-
KVM agent fails to connect to Ceph RBD storage pool after upgrading Ceph client to Tentacle 20.2.4 Abiertobug component:ceph
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
apache/cloudstack#13989 · 3 comentarios ·
Todos los issues de apache/cloudstack
Issues similares
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 75/100
elastic/gradle-plugins#157 ·
-
enhancement Tools
Dificultad 1/5 Menos de una hora Aptitud para principiantes 75/100
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 70/100
apache/rocketmq-dashboard#5008 ·
-
bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 75/100
-
DETECT_PARAMETER_NAMES=false silently disables @ConstructorProperties-based Creator detection too Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 70/100
FasterXML/jackson-databind#6229 ·