Advisory Details
Title: Plaintext CIFS Storage Credential Leakage in Log Files and Exception Traces
Description:
Summary
An information exposure vulnerability exists in Apache CloudStack where plaintext CIFS secondary storage credentials (including passwords) are logged directly to system files (such as agent.log, vmops.log or management server logs) and exception message traces. During the mounting, status checking, and automatic discovery phases of a CIFS storage pool containing sensitive query parameters (e.g. cifs://host/share?user=foo&password=bar), the application directly records the raw, unsanitized URI or URL objects, bypassing the standard log sanitization filters.
Details
In CloudStack, the NfsSecondaryStorageResource.java, LocalNfsSecondaryStorageResource.java, and SecondaryStorageDiscoverer.java classes handle mounting and discovering secondary storage networks. The original patch for Issue-cloudstack-8853 introduced StringUtils.cleanString(extraOptions) to scrub plaintext passwords from the parsed mount options log block. However, multiple critical logging paths print raw URI.toString() or secUrl strings without wrapping them in the sanitization mechanism.
Specifically:
- SSVM Mounting Phase (
NfsSecondaryStorageResource.java):
Raw uri and secUrl strings are formatted into logger warnings, debug logs, and exceptions when executing mount commands, creating directory structures, and throwing scheme exceptions.
- Local Mounting Phase (
LocalNfsSecondaryStorageResource.java):
The raw secUrl string is printed within the catch block of the getRootDir method.
- Management Server Discovery Phase (
SecondaryStorageDiscoverer.java):
Raw unsanitized uri.toString() is logged during secondary storage type discovery validation and mounting failure checkpoints.
This allows any administrative user or malicious operator with access to standard logs, ELK/Splunk collectors, or REST API error response payloads to retrieve the plaintext Samba/Windows domain credentials.
PoC
Prerequisites
- Administrative credentials for CloudStack Management Server REST API (
/client/api).
- Standard environment configured to register secondary storage pools.
Reproduction Steps
- Download the defect verification PoC script from: verification_test.py
- Download the scientific control group script from: control-masked_output.py
- Execute the verification script:
python3 verification_test.py
- Observe that under a live or academic offline analysis, the script detects the unpatched raw URI variables which expose credentials within
NfsSecondaryStorageResource, LocalNfsSecondaryStorageResource, and SecondaryStorageDiscoverer.
- Execute the control script to verify baseline security under normal usage parameters:
python3 control-masked_output.py
Log of Evidence
=== Verification Test Output ===
[*] Running Issue-cloudstack-8853 CIFS Storage Plaintext Password Exposure Verification Test...
[*] Attempting to add an image store with sensitive URL: cifs://192.168.1.200/share?user=cifsuser&password=mysecretpassword123
[-] Connection failed: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /client/api?name=CIFS_Image_Store_Test&provider=DefaultImageStore&zoneid=1&url=cifs%3A%2F%2F192.168.1.200%2Fshare%3Fuser%3Dcifsuser%26password%3Dmysecretpassword123&command=addImageStore&apiKey=ADMIN_API_KEY_PLACEHOLDER&response=json&signature=SxUFwcMwJgdiJu7Dti0UXENmbKc%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: CIFS logging in NfsSecondaryStorageResource.java,
LocalNfsSecondaryStorageResource.java, and SecondaryStorageDiscoverer.java confirmed.
[*] Specifically, raw cifs URIs/URLs containing plaintext passwords were logged by:
- NfsSecondaryStorageResource: logger.debug("mount " + uri.toString() ...)
- LocalNfsSecondaryStorageResource: logger.error("GetRootDir for " + secUrl ...)
- SecondaryStorageDiscoverer: logger.warn("Unable to mount " + uri.toString() ...)
[*] The fixes have successfully wrapped these values in StringUtils.cleanString(...) to mask the passwords.
=== Control Test Output ===
[*] Running Issue-cloudstack-8853 CIFS Storage Control Test (Baseline)...
[*] Attempting to add an image store with normal URL: cifs://192.168.1.200/share?user=cifsuser
[-] Connection failed: HTTPConnectionPool(host='localhost', port=8080): Max retries exceeded with url: /client/api?name=CIFS_Image_Store_Control&provider=DefaultImageStore&zoneid=1&url=cifs%3A%2F%2F192.168.1.200%2Fshare%3Fuser%3Dcifsuser&command=addImageStore&apiKey=ADMIN_API_KEY_PLACEHOLDER&response=json&signature=D6r2YQ7xC4QlHFw12qNNu2bz9Oc%3D (Caused by NewConnectionError("HTTPConnection(host='localhost', port=8080): Failed to establish a new connection: [Errno 111] Connection refused"))
[*] CloudStack Management Server is offline.
[*] Academic verification (Control Group): Omission of sensitive 'password' query parameter.
[*] Verifying that without password parameters in the URI, no passwords will be exposed.
[*] Expected behavior: Security mechanism functions correctly and no plaintext password is leaked.
Impact
- Vulnerability Type: Sensitive Information Exposure (Plaintext Credentials Exposure)
- Impact: Full compromise of secondary storage credentials (Samba/CIFS/Windows Share secrets). An attacker or low-privileged operator with log-read capabilities can steal domain credentials to view, alter, delete, or backdoor global VM templates, ISOs, and snapshot volumes.
- Access Privilege: Administrative log collection access / REST exception trace exposure.
Affected products
- Ecosystem: maven
- Package name: org.apache.cloudstack:cloudstack
- Affected versions: <= 4.23.0.0-SNAPSHOT
- 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
Occurrences
| Permalink |
Description |
|
logger.debug("mount " + uri.toString() + " on " + localRootPath + ((nfsVersion != null) ? " nfsVersion=" + nfsVersion : "")); |
|
Logging of raw unsanitized CIFS URI string in the mounting lifecycle methods in NfsSecondaryStorageResource. |
|
logger.debug("Make cmdline call to mount " + remoteDevice + " at " + localRootPath + " based on uri " + uri + ((nfsVersion != null) ? " nfsVersion=" + nfsVersion : "")); |
|
Unsanitized logging of CIFS mounting URI during cmdline script setup parameters in NfsSecondaryStorageResource. |
|
String errMsg = "Unsupported storage device scheme " + scheme + " in uri " + uri.toString(); |
|
Exposing plaintext credentials when formatting storage scheme validation error messages in NfsSecondaryStorageResource. |
|
logger.debug("Some device already mounted at " + localRootPath + ", no need to mount " + uri.toString()); |
|
Plaintext URI string formatting when outputting debug messages inside mountExists check paths in NfsSecondaryStorageResource. |
|
logger.debug("making available " + localRootPath + " on " + uri.toString()); |
|
Printing raw unsanitized URI in debug log block of ensureLocalRootPathExists in NfsSecondaryStorageResource. |
|
String errMsg = "Unable to create local folder for: " + localRootPath + " in order to mount " + uri.toString(); |
|
Logging of raw URI on folder creation failure exception paths in NfsSecondaryStorageResource. |
|
String msg = "GetRootDir for " + secUrl + " failed due to " + e.toString(); |
|
Raw secUrl parameter string formatting inside the executeRequest catch-blocks in NfsSecondaryStorageResource. |
|
String msg = "GetRootDir for " + secUrl + " failed due to " + e.toString(); |
|
Logging of un-scrubbed secUrl string on getDir method path failures in NfsSecondaryStorageResource. |
|
logger.debug(String.format("Trying to get root directory from secondary storage URL [%s] using NFS version [%s].", secUrl, nfsVersion)); |
|
Raw secUrl logging inside debug messages in getRootDir under NfsSecondaryStorageResource. |
|
String msg = String.format("Failed to get root directory from secondary storage URL [%s], using NFS version [%s], due to [%s].", secUrl, nfsVersion, e.getMessage()); |
|
Exposing secUrl when constructing and throwing CloudRuntimeException inside NfsSecondaryStorageResource. |
|
String msg = "GetRootDir for " + secUrl + " failed due to " + e; |
|
Logging and throwing unscrubbed secUrl strings inside the getRootDir method exception handler of LocalNfsSecondaryStorageResource. |
|
logger.debug("It's not NFS or file or ISO, so not a secondary storage server: " + uri.toString()); |
|
Logging of raw uri.toString() string during storage discovery checks in SecondaryStorageDiscoverer. |
|
logger.warn("Unable to mount " + uri.toString() + " due to " + result); |
|
Logging of unsanitized CIFS URI string on storage server mount execution warnings in SecondaryStorageDiscoverer. |
Advisory Details
Title: Plaintext CIFS Storage Credential Leakage in Log Files and Exception Traces
Description:
Summary
An information exposure vulnerability exists in Apache CloudStack where plaintext CIFS secondary storage credentials (including passwords) are logged directly to system files (such as
agent.log,vmops.logor management server logs) and exception message traces. During the mounting, status checking, and automatic discovery phases of a CIFS storage pool containing sensitive query parameters (e.g.cifs://host/share?user=foo&password=bar), the application directly records the raw, unsanitizedURIorURLobjects, bypassing the standard log sanitization filters.Details
In CloudStack, the
NfsSecondaryStorageResource.java,LocalNfsSecondaryStorageResource.java, andSecondaryStorageDiscoverer.javaclasses handle mounting and discovering secondary storage networks. The original patch for Issue-cloudstack-8853 introducedStringUtils.cleanString(extraOptions)to scrub plaintext passwords from the parsed mount options log block. However, multiple critical logging paths print rawURI.toString()orsecUrlstrings without wrapping them in the sanitization mechanism.Specifically:
NfsSecondaryStorageResource.java):Raw
uriandsecUrlstrings are formatted into logger warnings, debug logs, and exceptions when executing mount commands, creating directory structures, and throwing scheme exceptions.LocalNfsSecondaryStorageResource.java):The raw
secUrlstring is printed within the catch block of thegetRootDirmethod.SecondaryStorageDiscoverer.java):Raw unsanitized
uri.toString()is logged during secondary storage type discovery validation and mounting failure checkpoints.This allows any administrative user or malicious operator with access to standard logs, ELK/Splunk collectors, or REST API error response payloads to retrieve the plaintext Samba/Windows domain credentials.
PoC
Prerequisites
/client/api).Reproduction Steps
NfsSecondaryStorageResource,LocalNfsSecondaryStorageResource, andSecondaryStorageDiscoverer.Log of Evidence
Impact
Affected products
Severity
Weaknesses
Occurrences
cloudstack/services/secondary-storage/server/src/main/java/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java
Line 3077 in 3f6866d
NfsSecondaryStorageResource.cloudstack/services/secondary-storage/server/src/main/java/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java
Line 3094 in 3f6866d
NfsSecondaryStorageResource.cloudstack/services/secondary-storage/server/src/main/java/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java
Line 3117 in 3f6866d
NfsSecondaryStorageResource.cloudstack/services/secondary-storage/server/src/main/java/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java
Line 3178 in 3f6866d
mountExistscheck paths inNfsSecondaryStorageResource.cloudstack/services/secondary-storage/server/src/main/java/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java
Line 3186 in 3f6866d
ensureLocalRootPathExistsinNfsSecondaryStorageResource.cloudstack/services/secondary-storage/server/src/main/java/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java
Line 3195 in 3f6866d
NfsSecondaryStorageResource.cloudstack/services/secondary-storage/server/src/main/java/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java
Line 1995 in 3f6866d
secUrlparameter string formatting inside theexecuteRequestcatch-blocks inNfsSecondaryStorageResource.cloudstack/services/secondary-storage/server/src/main/java/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java
Line 2697 in 3f6866d
secUrlstring ongetDirmethod path failures inNfsSecondaryStorageResource.cloudstack/services/secondary-storage/server/src/main/java/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java
Line 2709 in 3f6866d
secUrllogging inside debug messages ingetRootDirunderNfsSecondaryStorageResource.cloudstack/services/secondary-storage/server/src/main/java/org/apache/cloudstack/storage/resource/NfsSecondaryStorageResource.java
Line 2714 in 3f6866d
secUrlwhen constructing and throwingCloudRuntimeExceptioninsideNfsSecondaryStorageResource.cloudstack/services/secondary-storage/server/src/main/java/org/apache/cloudstack/storage/resource/LocalNfsSecondaryStorageResource.java
Line 55 in 3f6866d
secUrlstrings inside thegetRootDirmethod exception handler ofLocalNfsSecondaryStorageResource.cloudstack/services/secondary-storage/server/src/main/java/org/apache/cloudstack/storage/resource/SecondaryStorageDiscoverer.java
Line 78 in 3f6866d
uri.toString()string during storage discovery checks inSecondaryStorageDiscoverer.cloudstack/services/secondary-storage/server/src/main/java/org/apache/cloudstack/storage/resource/SecondaryStorageDiscoverer.java
Line 116 in 3f6866d
SecondaryStorageDiscoverer.