This is a control room with one jammed doorbell and one password scribbled in a maintenance log
Plugin tenable:168746 rolls up two different issues from VMSA-2022-0030 affecting VMware vCenter Server 6.5 before 6.5 U3u, 6.7 before 6.7 U3s, and 7.0 before 7.0 U3i. CVE-2022-31697 leaks plaintext credentials into logs, but only during specific VCSA ISO lifecycle operations such as install, upgrade, migrate, or restore, and the attacker needs access to the workstation involved in that workflow. CVE-2022-31698 is the more reachable bug: a pre-auth denial of service in the content library service over TCP/443 via a crafted HTTP header.
The vendor's MEDIUM label is basically fair, but for enterprise patch prioritization I'd shave it down from the headline score. One half of this plugin is post-compromise and workflow-dependent, and the other half is availability-only, not code execution, auth bypass, or privilege escalation. On a badly exposed internet-facing vCenter, the DoS path matters; in most real deployments where vCenter sits on an admin network, this is important hygiene rather than a stop-everything incident.
4 steps from start to impact.
Reach the vCenter management plane
curl or a short Python requests script is enough to touch the vulnerable content library handler; this is not an authentication-dependent path.- Target is running vCenter Server below 6.5 U3u / 6.7 U3s / 7.0 U3i
- Attacker can reach TCP/443 on the vCenter server
- Content library service path is exposed through the standard management interface
- Many enterprises keep vCenter on a restricted management VLAN or behind VPN/bastion access
- North-south firewalls often block arbitrary Internet reachability to vCenter
- If vCenter is not externally exposed, this becomes an internal-only abuse path
Send the crafted header
- Attacker can send arbitrary HTTP requests to the target
- Target is unpatched for CVE-2022-31698
- Reverse proxies, WAFs, or strict header normalization can reduce reliability
- Operational monitoring may quickly reveal repeated malformed requests against vCenter
Disrupt content-library-backed operations
- Crafted request successfully triggers the vulnerable service state
- Operational staff do not rapidly detect and recover the affected service
- Service restarts, monitoring, and administrator intervention limit dwell time
- Blast radius is largely confined to vCenter management functions rather than guest OS takeover
Alternate path: harvest plaintext credentials from logs
- A vulnerable vCenter version was used during the affected ISO workflow
- Attacker already has local access to the involved workstation
- Relevant logs are still present and readable
- Requires prior foothold on an admin or operator system
- Only specific lifecycle workflows create the exposure
- Many environments do these operations infrequently
The supporting signals.
| In-the-wild status | No public evidence of active exploitation found in the reviewed sources, and no CISA KEV entry was located for CVE-2022-31697 or CVE-2022-31698. |
|---|---|
| Proof-of-concept availability | CVE-2022-31698 has a public technical write-up from Cisco Talos (TALOS-2022-1588) plus Snort rule 60408. I did not find a widely used weaponized GitHub exploit for either CVE in the reviewed results. |
| EPSS / exploit likelihood | Secondary feeds show very low EPSS scores: Feedly snippets show about 0.04% for CVE-2022-31697 and 0.05% for CVE-2022-31698, which aligns with a *low near-term exploitation probability*. |
| KEV status | Not KEV-listed based on reviewed CISA catalog search results; no known ransomware-campaign linkage was identified for these CVEs. |
| CVSS and what it really means | CVE-2022-31697: CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N = local, low-priv, confidentiality-only. CVE-2022-31698: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L = pre-auth network reachable, but availability-only. |
| Affected version range | vCenter Server 6.5 < U3u, 6.7 < U3s, 7.0 < U3i. VMware Cloud Foundation deployments that bundle these vCenter components are also affected; VMware points VCF customers to KB90336. |
| Fixed versions | Fixed at vCenter 6.5 U3u (build 20510539), 6.7 U3s (vpxd build 20504362 on VCSA), and 7.0 U3i (build 20845200). |
| Scanning / exposure reality | The product family is not hypothetical on the public Internet: Censys has historically observed thousands of Internet-facing vCenter services. That does not make this a critical bug, but it does mean any externally exposed vCenter leaves the CVE-2022-31698 DoS path directly reachable. |
| Disclosure date | VMware published VMSA-2022-0030 on 2022-12-08; NVD published both CVEs on 2022-12-13. |
| Researcher / reporting org | VMware credits Marcin 'Icewall' Noga of Cisco Talos for CVE-2022-31698. Public attribution for CVE-2022-31697 is not similarly emphasized in the reviewed advisory text. |
noisgate verdict.
The decisive factor is that the scary-sounding half of this plugin, CVE-2022-31697, is not an initial-access bug at all; it assumes the attacker already has foothold on the right admin workstation during a narrow maintenance workflow. The remotely reachable half, CVE-2022-31698, is pre-auth but lands only in availability impact, which matters for operations but does not create the takeover path defenders usually reserve HIGH or CRITICAL for.
Why this verdict
- Downward adjustment: CVE-2022-31697 is post-compromise by design — it requires access to a workstation that already performed a VCSA ISO install/upgrade/migrate/restore operation, which implies the attacker is already on an admin path.
- Downward adjustment: the unauthenticated remote path is only DoS — CVE-2022-31698 is reachable over the network, but the impact is service disruption, not code execution, auth bypass, or durable compromise.
- Downward adjustment: exposure population is narrower than generic HTTPS bugs — healthy enterprises do not publish vCenter broadly, so the reachable population is much smaller than a typical edge appliance.
- Upward adjustment: this is still the virtualization control plane — even low-grade disruption on vCenter can interrupt admin workflows, maintenance, provisioning, and some dependent operations.
Why not higher?
There is no reviewed evidence of active exploitation, KEV listing, or commodity exploit ecosystem around these specific CVEs. More importantly, the only network-reachable branch here is availability-only, and the credential-leak branch assumes an attacker is already on the right workstation at the right time.
Why not lower?
I am not dropping this to LOW because a pre-auth network path still exists against a high-value management platform, and many shops have weaker-than-ideal segmentation around vCenter. If your vCenter is Internet-facing or broadly reachable from user or server networks, the operational impact of a remote DoS is real enough to keep this in MEDIUM.
What to do — in priority order.
- Restrict vCenter reachability — Limit TCP/443 to admin jump hosts, VPN ranges, and automation systems that truly need it. For a MEDIUM verdict there is no noisgate mitigation SLA — go straight to the 365-day remediation window, but if your vCenter is Internet-facing, do this immediately because it removes the only remotely reachable branch.
- Monitor for malformed-header abuse — Turn on or review reverse-proxy, load balancer, and vCenter web logging for unusual header patterns and bursts of failed requests to content-library-related paths. This is a practical way to catch CVE-2022-31698 attempts while you work through patching in the normal remediation window.
- Harden admin workstations — Treat systems used for VCSA install/upgrade/migrate/restore as privileged assets: EDR, admin segregation, restricted local admin, and log access monitoring all reduce the only meaningful path for CVE-2022-31697. There is no separate mitigation deadline for MEDIUM, but this belongs in the same hardening queue as other privileged-management tooling.
- Review historical lifecycle logs — If you recently performed affected ISO-based workflows before patching, inspect and securely purge any logs that may contain plaintext credentials, then rotate those credentials if exposure is confirmed. This is less about the remote bug and more about cleaning up the post-compromise residue left by the credential-logging issue.
- A standard EDR-only posture does not meaningfully stop the pre-auth HTTP header DoS path; this is a network/service robustness problem, not a malware execution problem.
- Relying on MFA does not help for CVE-2022-31698 because the remote DoS path does not require authentication.
- Patching only ESXi hosts does nothing for this plugin's vCenter findings; the affected components are in vCenter Server and VCF bundles that include it.
Crowdsourced verification payload.
Run this on the target vCenter host itself — VCSA or legacy Windows vCenter — not from an auditor workstation. Invoke it as python3 check_vcenter_vmsa_2022_0030.py on VCSA or py -3 check_vcenter_vmsa_2022_0030.py on Windows; root/Administrator is recommended so the script can query local binaries, files, or registry keys reliably.
#!/usr/bin/env python3
# check_vcenter_vmsa_2022_0030.py
# Detects whether the local VMware vCenter host is vulnerable to VMSA-2022-0030
# (Tenable plugin 168746 / CVE-2022-31697 and CVE-2022-31698)
#
# Exit codes:
# 0 = PATCHED
# 1 = VULNERABLE
# 2 = UNKNOWN
import os
import platform
import re
import subprocess
import sys
THRESHOLDS = {
'6.5': 20510539, # 6.5 U3u
'6.7': 20504362, # 6.7 U3s (VCSA vpxd build)
'7.0': 20845200, # 7.0 U3i
}
def run(cmd):
try:
p = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, timeout=10)
return p.stdout.strip()
except Exception:
return ''
def parse_version_build(text):
# Accepts common outputs like:
# VMware VirtualCenter 7.0.3 build-20845200
# 7.0.3.01100 build 20845200
if not text:
return None, None
version = None
build = None
m = re.search(r'(\d+\.\d+\.\d+(?:\.\d+)?)', text)
if m:
version = m.group(1)
m = re.search(r'build[-\s:]*(\d{5,})', text, re.IGNORECASE)
if m:
build = int(m.group(1))
else:
nums = re.findall(r'\b(\d{7,})\b', text)
if nums:
build = int(nums[-1])
return version, build
def linux_collect():
candidates = [
['/usr/sbin/vpxd', '-v'],
['/usr/lib/vmware-vpxd/vpxd', '-v'],
['vpxd', '-v'],
]
for cmd in candidates:
out = run(cmd)
v, b = parse_version_build(out)
if v and b:
return v, b, 'command: ' + ' '.join(cmd)
for path in ['/etc/vmware/.buildInfo', '/etc/applmgmt/appliance/update.conf']:
if os.path.exists(path):
try:
data = open(path, 'r', encoding='utf-8', errors='ignore').read()
v, b = parse_version_build(data)
if v and b:
return v, b, 'file: ' + path
except Exception:
pass
return None, None, ''
def windows_collect():
try:
import winreg
except Exception:
return None, None, ''
reg_paths = [
r'SOFTWARE\VMware, Inc.\VMware VirtualCenter',
r'SOFTWARE\WOW6432Node\VMware, Inc.\VMware VirtualCenter',
]
values = []
for root in (0x80000002,): # HKEY_LOCAL_MACHINE
for reg_path in reg_paths:
try:
key = winreg.OpenKey(root, reg_path)
i = 0
while True:
try:
name, val, _ = winreg.EnumValue(key, i)
values.append(f'{name}={val}')
i += 1
except OSError:
break
except OSError:
continue
joined = '\n'.join(values)
v, b = parse_version_build(joined)
if v and b:
return v, b, 'registry'
candidates = [
r'C:\Program Files\VMware\Infrastructure\VirtualCenter Server\vpxd.exe',
r'C:\Program Files\VMware\Infrastructure\vCenter Server\vpxd.exe',
]
for path in candidates:
if os.path.exists(path):
out = run([path, '-v'])
v, b = parse_version_build(out)
if v and b:
return v, b, 'binary: ' + path
return None, None, ''
def branch(version_str):
if version_str.startswith('6.5.'):
return '6.5'
if version_str.startswith('6.7.'):
return '6.7'
if version_str.startswith('7.0.'):
return '7.0'
return None
def main():
system = platform.system().lower()
version = build = source = None
if 'windows' in system:
version, build, source = windows_collect()
else:
version, build, source = linux_collect()
if not version or not build:
print('UNKNOWN - could not determine local vCenter version/build')
sys.exit(2)
rel = branch(version)
if rel is None:
print(f'UNKNOWN - detected version {version} build {build} from {source}, but it is outside 6.5/6.7/7.0 scope')
sys.exit(2)
threshold = THRESHOLDS[rel]
if build < threshold:
print(f'VULNERABLE - detected vCenter {version} build {build} from {source}; fixed threshold for {rel} is build {threshold}')
sys.exit(1)
else:
print(f'PATCHED - detected vCenter {version} build {build} from {source}; meets or exceeds fixed threshold {threshold}')
sys.exit(0)
if __name__ == '__main__':
main()
If you remember one thing.
Sources
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.