aws-kms-escalate-via-decrypt-credential
Decrypting a KMS-encrypted secret whose credential is a more-privileged identity is privilege escalation.
match
A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.
{'principal': None}
CanReadSecret {'secret': None}
{'secret': None} CredentialsFor {'identity': None}
where
node_class(?principal) == Identity AND node_class(?identity) == Identity (
CanEscalateTo source/target are both Identity)
?identity.privilege_level > ?principal.privilege_level
the CanReadSecret was gated by a KMS CanDecrypt (rule aws-kms-decrypt-unlocks-secret) — i.e. the KMS key_permission gate is the enabling step (doc §14 decrypt->credential escalation)
emit
| source type | Identity |
|---|---|
| target type | Identity |
| source | ?principal |
| target | ?identity |
| permissions | kms:Decrypt |
| state logic | inherit state from the contributing CanReadSecret edge (ACTIVE only if both the store-read and KMS-decrypt halves are met and the secret is a credential for a strictly-more-privileged identity) |
Narrative
{principal.name} can escalate to {identity.name} by decrypting a KMS-encrypted secret (kms:Decrypt gate) that holds {identity.name}'s credentials.
Raw rule rules/derived/aws/kms.yaml
id: aws-kms-escalate-via-decrypt-credential
emits: CanEscalateTo
description: Decrypting a KMS-encrypted secret whose credential is a more-privileged identity is privilege
escalation.
match:
- - principal: null
- CanReadSecret
- secret: null
- - secret: null
- CredentialsFor
- identity: null
where:
- node_class(?principal) == Identity AND node_class(?identity) == Identity (CanEscalateTo source/target
are both Identity)
- ?identity.privilege_level > ?principal.privilege_level
- "the CanReadSecret was gated by a KMS CanDecrypt (rule aws-kms-decrypt-unlocks-secret) \u2014 i.e. the\
\ KMS key_permission gate is the enabling step (doc \xA714 decrypt->credential escalation)"
emit:
source_type: Identity
target_type: Identity
source: ?principal
target: ?identity
permissions:
- kms:Decrypt
conditions: []
state_logic: inherit state from the contributing CanReadSecret edge (ACTIVE only if both the store-read
and KMS-decrypt halves are met and the secret is a credential for a strictly-more-privileged identity)
confidence: min(contributing_confidences)
derived_from:
- <CanReadSecret edge_id>
- <CredentialsFor secret->identity edge_id>
false_positive_note: "Only when the identity the decrypted secret authenticates as is strictly more\
\ privileged than the caller. Lateral/same-privilege credential access is not escalation. Inherits\
\ state from CanReadSecret \u2014 do not emit if the secret is not actually readable (KEY or store-read\
\ half unmet). This is the decrypt->credential counterpart to aws-kms-escalate-via-sign, completing\
\ doc \xA714's two escalation families (sign-forgery AND decrypt->credential) at the CanEscalateTo\
\ roll-up."
narrative: '{principal.name} can escalate to {identity.name} by decrypting a KMS-encrypted secret (kms:Decrypt
gate) that holds {identity.name}''s credentials.'