gcp-certmanager-impersonate-via-forged-cert
Issue a cert for an attacker-chosen subject/SAN that a downstream trust accepts, impersonating that identity.
match
A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.
where
node_type(?capool) == CaPool (
SigningKey)
the pool issuancePolicy / bound certificate template ALLOWS the attacker to set the target subject/SAN: identityConstraints.allowSubjectPassthrough OR allowSubjectAltNamesPassthrough is true, OR the celExpression admits it, OR no restricting template is bound
a downstream trust consumes CAS-issued certs and maps the forged subject/SAN to ?target (mTLS mesh / SPIFFE-SPIRE / VPN-LB client-cert store / device or workload cert bound to a GCP identity)
node_type(?target) in [ServiceAccount, MachineIdentity, ApplicationIdentity]
emit
| source type | Identity |
|---|---|
| source | <principal> |
| target | <forged identity the consuming trust authenticates> |
| permissions | privateca.certificates.create privateca.caPools.use |
| conditions | iam_permission condition_expression trust_relationship |
| state logic | Inherits the CanSignAs state (ACTIVE / CONDITIONAL(key_permission) for KMS- backed / BLOCKED). Then: ACTIVE only if the issuancePolicy/template confirmed permits the target subject/SAN AND a consuming trust is identified; CONDITIONAL(condition_expression) if the issuance policy is unknown/unconfirmed; CONDITIONAL(trust_relationship) if no CAS-cert consumer is identified; BLOCKED if the policy pins the subject (allowSubjectPassthrough=false + no passthrough SAN + restrictive template/celExpression) or the CanSignAs input is BLOCKED. |
Narrative
{principal.name} can issue a certificate from {capool.name} for subject/SAN naming {target.name} (issuance policy permits the subject), which a downstream trust consumes to authenticate - impersonating {target.name}.
Raw rule rules/derived/gcp/certmanager.yaml
id: gcp-certmanager-impersonate-via-forged-cert
emits: CanImpersonate
description: Issue a cert for an attacker-chosen subject/SAN that a downstream trust accepts, impersonating
that identity.
match:
- - principal: null
- CanSignAs
- capool: null
where:
- node_type(?capool) == CaPool (SigningKey)
- 'the pool issuancePolicy / bound certificate template ALLOWS the attacker to set the target subject/SAN:
identityConstraints.allowSubjectPassthrough OR allowSubjectAltNamesPassthrough is true, OR the celExpression
admits it, OR no restricting template is bound'
- a downstream trust consumes CAS-issued certs and maps the forged subject/SAN to ?target (mTLS mesh /
SPIFFE-SPIRE / VPN-LB client-cert store / device or workload cert bound to a GCP identity)
- node_type(?target) in [ServiceAccount, MachineIdentity, ApplicationIdentity]
emit:
source_type: Identity
source: <principal>
target: <forged identity the consuming trust authenticates>
permissions:
- privateca.certificates.create
- privateca.caPools.use
conditions:
- iam_permission
- condition_expression
- trust_relationship
state_logic: 'Inherits the CanSignAs state (ACTIVE / CONDITIONAL(key_permission) for KMS- backed / BLOCKED).
Then: ACTIVE only if the issuancePolicy/template confirmed permits the target subject/SAN AND a consuming
trust is identified; CONDITIONAL(condition_expression) if the issuance policy is unknown/unconfirmed;
CONDITIONAL(trust_relationship) if no CAS-cert consumer is identified; BLOCKED if the policy pins
the subject (allowSubjectPassthrough=false + no passthrough SAN + restrictive template/celExpression)
or the CanSignAs input is BLOCKED.'
confidence: min(contributing_confidences) * 0.8
derived_from:
- <CanSignAs edge_id>
- <pool issuancePolicy / certificate template evidence>
- <downstream CAS-cert trust evidence>
false_positive_note: "DOUBLY CONDITIONAL. (1) Forgery gate: a pool with allowSubjectPassthrough=false\
\ / allowSubjectAltNamesPassthrough=false and a restrictive celExpression or bound certificate template\
\ PINS the subject \u2014 the principal can obtain a cert but NOT for an arbitrary identity; keep\
\ CONDITIONAL(condition_expression) until the policy is confirmed permissive. (2) Trust gate: a CAS\
\ cert authenticates to nothing unless some system trusts the CA and maps the subject to a principal;\
\ default CONDITIONAL(trust_relationship). createForSelf (subject == caller) is NOT impersonation.\
\ Only emit a concrete ?target when a consuming trust maps the forgeable subject to it; otherwise\
\ emit POTENTIAL or omit."
narrative: "{principal.name} can issue a certificate from {capool.name} for subject/SAN naming {target.name}\
\ (issuance policy permits the subject), which a downstream trust consumes to authenticate \u2014\
\ impersonating {target.name}."