# vCenter Server Appliance (VCSA): Multiple Critical Vulnerabilities ## Vendors * Broadcom ## Affected Products VCSA 3.0 to 9.1 prior to vendor's July 2026 patch ## Summary VCSA is susceptible to the following issues that could lead to remote code execution as `root` and authentication bypass for arbitrary VCSA's integrated LDAP users: * Unauthenticated remote code execution as `root` via misconfiguration in `rsyslogd` * Cryptographic flaws in the Secure Remote Password (SRP) implementation allowing authentication bypass ## Remediation/Mitigation Customers should follow vendor instructions to apply patches to their VCSA deployments. ## Credit These issues were found by Matt South and Phil Brass of Atredis Partners. ## References * vCenter Server: https://www.vmware.com/products/cloud-infrastructure/vcenter/future-overview * Broadcom Advisory: https://support.broadcom.com/web/ecx/support-content-notification/-/external/content/SecurityAdvisories/0/38017 ## Report Timeline * 2026-07-08: Atredis Partners reached out to the vendor to initiate coordinated disclosure * 2026-07-09: Vendor provided reporting instructions and PGP key. Atredis reported findings same day * 2026-07-10: Vendor stated they have begun investigation * 2026-07-28: Vendor stated they will be disclosing these vulnerabilities the following day * 2026-07-29: Atredis Partners publishes advisory ATREDIS-2026-0008 ## Technical Details ### Unauthenticated remote code execution as `root` via misconfiguration in `rsyslogd` (CVE-2026-59310) By default, VCSA allows inbound syslog messages on UDP and TCP port 514, and TCP port 1514. The `rsyslogd` configuration files that ship with the appliance allow an inbound syslog message that specifies a hostname to be placed in `/var/log/vmware/esx//-syslog.log`, with no secure-path handling. This file contains a timestamp and metadata on the first line, and the log message after it. Because `rsyslogd` runs as `root` and does not sanitize the hostname, directory traversal characters in the hostname can be used to place the log file anywhere on the system. Portions of the syslog configuration are shown below: ``` 27 $template defaultLoc,"/var/log/vmware/%app-name%/%app-name%-syslog.log" 33 $template esxLoc,"/var/log/vmware/esx/%hostname%/%hostname%-syslog.log" 34 $template esxFmt,"%timestamp:::date-rfc3339% %syslogseverity-text% %hostname% %app-name% %msg%\n" ... 19 $EscapeControlCharactersOnReceive off ... # last rule, reached by any message whose hostname != this host: if ($hostname != $$myhostname ) then ?esxLoc;esxFmt ``` Logging Template in `/etc/rsyslog.conf` For example the file can be placed in the `/etc/bash_completion.d/` directory, where it would be executed the next time a user logs in or `/etc/profile` is sourced. The timestamp and metadata on the first line would just be ignored by bash. A "command not found" error would be produced, and execution would continue on the next line. Rather than wait for a user to log in to get the command run, an attacker can submit an authentication request with any username and password to the `vmware-pod` service on TCP port 5580. This service will run a shell script as `root` that sources `/etc/profile` on any login attempt, before it validates the password. Relevant source snippets are below: `/usr/lib/vmware-pod/py/vmware/auth.py` ```python 50 def _call_pod_pam_auth(cls, user, passwd): 51 proc = subprocess.Popen(["sudo", pod_consts.SUDO_PY_WRAPPER, 52 "/var/vmware-pod/scripts/pod_pam_auth.py"], stdin=subprocess.PIPE) ``` Auth attempts from `vmware-pod` call the sudo wrapper script `/var/vmware-pod/scripts/sudo_py_wrapper.sh` ```bash 1 #!/bin/bash 9 source /etc/profile # sources /etc/bash_completion.d/* as root 11 exec ${VMWARE_PYTHON_BIN} -E "$@" ``` The sudo wrapper script sources `/etc/profile` `/etc/sudoers.d/pod` ```sudoers pod ALL= NOPASSWD: POD_PAM_N # pod user may run the wrapper as root, no password ``` Passwordless sudo enabled for the `vmware-pod` user This vulnerability chain allows an attacker that can send syslog messages and talk to the `vmware-pod` service on TCP 5580 to execute commands as `root`. ### Passwordless LDAP authentication as any valid user (CVE-2026-59309) VCSA includes an LDAP server, which stores users and their roles and privileges. The LDAP server on VCSA is called `vmdird`. This LDAP server supports a variety of authentication mechanisms, one of which is Secure Remote Password (SRP). The SRP mechanism is meant to be a secure way for clients to authenticate to a server without having to send their password over the network. Clients perform calculations detailed below to prove that they know the user's password and send the result to the server. The server checks their work and if it gets the same result decides the client must have known the password. However, the `vmdird` LDAP server was missing an important step when validating the calculation performed by the client. Because of this missing check, the server allowed an attacker to authenticate as any user without knowing their password. No password or certificate was required, only a valid account name, which could be the well-known `administrator@`, the Single Sign-On (SSO) domain being readable on the LDAP server by an anonymous user. #### Background: The SRP Protocol The SRP authentication and key exchange system is standardized in the Internet Engineering Task Force (IETF) Request For Comments (RFC) number 2945, published in September 2000. It defines a registration step and a four-step message exchange for clients to prove their identity to the server. #### Fixed Parameters The `vmdird` server has several values that are constant through its lifetime and used on every registration and authentication request: - **`N`** - a large, fixed, safe prime. - **`g`** - a fixed base number whose successive powers `g^1, g^2, g^3, … mod N` produce a very large number of distinct results, scattered unpredictably across `1 … N-1`. In this case `g` is always the number **2**. - **`H`** - a hash function. In this case the `vmdird` server always uses **`SHA-1`**. #### Registration During the registration (user creation) step, an authenticated client sends the username `U` and password `P` of the new user to the server. The server then creates: - **`s`** - a password salt. - **`x`** - the private key, computed as `SHA-1(s || SHA-1(U || ":" || P))`. - **`v`** - the verifier, computed as `g^x mod N`. The salt `s` and verifier `v` are then stored for the registered username `U`. #### Authentication Step 1 - Client Sends Identity When a client wants to authenticate, it sends four elements to the server: - **`U`** - username. - **`I`** - authorization ID. Normally empty; can be used to request impersonation as another user. Empty in our case. - **`sid`** - session resumption ID, if resuming from a previous session. Empty in our case. - **`cn`** - client nonce used in the session resumption flow. Empty in our case. #### Authentication Step 2 - Server Sends Group Parameters In response to the client's identity assertion, the server looks up the username `U` and sends the following items to the client: - **`N`** - the safe large prime that is the modulus for the calculations. - **`g`** - the group generator for `N` that maps `1 … N-1` to unpredictable other values in `1 … N-1`. For our case it is **2**. - **`s`** - the user's salt that the server created at registration. - **`B`** - the server chooses a random value `b` as its ephemeral session secret, then computes `B = (k·v + g^b) mod N`, where `k` is always **3** in our case. - **`L`** - server options, as text strings, simply repeated back by the client in the next step. #### Authentication Step 3 - Client Sends Proof of Knowledge After receiving the authentication parameters from the server, the client uses the username and password, along with the group parameters, to compute proof that it knows the user's password. These values are sent back to the server: - **`A`** - should be `g^a mod N`, where `a` is a randomly chosen number. - In the exploit, rather than choosing `a`, the attacker sends `N` where `A` should be sent. - **`M1`** - the number that proves the client knows the password. - **`o`** - client options, simply copied from the server options in our case. - **`cIV`** - client initialization vector. The client first computes: `x = SHA-1(s || SHA-1(U || ":" || P))` where `x` is a a hash of the server-provided salt together with a hash of the colon-delimited username and password. Note that `||` denotes string concatenation. The client then computes `u`, a scrambling parameter derived from the two public values `A` and `B`: `u = SHA-1(A || B)` and uses it to compute the session secret `S`: `S = (B − 3·g^x)^(a + u·x) mod N` Then the client transforms `S` into `K`, which is simply: `K = SHA-1(S)` Now `M1` can be computed as: `M1 = SHA-1( [SHA-1(N) ⊕ SHA-1(g)] || SHA-1(U) || s || A || B || K || SHA-1(I) || SHA-1(L) )` Note that `⊕` denotes bitwise Boolean XOR here. Recall that: - `N` comes from the server in step 2, - `g` comes from the server in step 2, - `U` is the username, - `s` is the salt, from the server in step 2, - `A` is computed by the client as specified above, - `B` comes from the server in step 2, - `K` is computed as described above, - `I` is the delegation ID requested by the client in step 1 (empty in our case), - `L` is the server options specified by the server in step 2. #### The Vulnerability - Missing `A mod N` Check The key to the attack is that the attacker can set any `A` where `A > 0` and `A mod N = 0`, for example **`A = N`**. When the server computes its own `M1` value, it uses this formula for `S`: `S = (A·v^u)^b mod N` where `u = SHA-1(A || B)` is the same scrambling parameter the client used. If `A = N`, this becomes: `S = (N·v^u)^b mod N` `N` times anything, raised to any power, modulo `N`, is zero. So `S` is zero, represented by the empty string in this protocol, and `K` becomes `SHA-1("")`. The attacker computes their version of `M1` using `N` instead of calculating a value for `A`, and `SHA-1("")` instead of `K`, and sends it to the server. The server gets the same value for `K`, because it computed `S` from `A = N` as described above, so its `M1` matches the attacker's `M1` even though the attacker did not know the password. Note that the SRP specification explicitly states: > The host MUST abort the authentication attempt if `A % N` is zero. Note that `%` represents mod in the specification. That requirement exists to prevent this exact attack. Unfortunately, it was never implemented in the Cyrus SASL SRP library - the vulnerability has been in the SRP code since 2001. Only the following checks were made in the SRP library: - `A` must be `> 0` - `A·v^u` must not be `1` - `S` must not be `N` The library does not check for `A mod N = 0`, so the attack succeeds. While there is a fourth message from the server to the client, the attacker does not need to process it. Once the authentication process completes, the attacker has an authenticated TCP connection to the VCSA LDAP server. If they authenticated as `administrator`, they can register a new user with a known password, add the `Administrators` role to the user, log into the VCSA administrative web application with those new credentials, and manage the cluster.