aws-rolesanywhere-config-add-trust-anchor

Registering an attacker-controlled CA as a trust anchor lets the attacker mint certs that federate into any role trusting the Roles Anywhere service principal.

derived aws emits CanModifyTrust

match

A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.

{'principal': None} CanAdminister {'raConfig': None} {'role': None} TrustsExternalIdentity {'ext': None}

where

node_type(?raConfig) == ManagementService # the Roles Anywhere config resource (trust-anchor surface) ?principal has EFFECTIVE rolesanywhere:CreateTrustAnchor OR rolesanywhere:UpdateTrustAnchor on ?raConfig (+ rolesanywhere:EnableTrustAnchor if disabled) node_type(?role) == Role the ?role -> ?ext TrustsExternalIdentity fact names Principal.Service == rolesanywhere.amazonaws.com with NO aws:SourceArn pin (so the newly-registered anchor qualifies) and a cert-attribute condition the attacker can satisfy with a self-minted cert

emit

source typeIdentity
target typeRole
source?principal
target?role
permissionsrolesanywhere:CreateTrustAnchor rolesanywhere:UpdateTrustAnchor rolesanywhere:EnableTrustAnchor?
conditionstrust_condition iam_permission
state logicACTIVE when a target role trusts the service principal with NO aws:SourceArn pin (any anchor qualifies) AND either no cert-subject condition or one the attacker can satisfy with a cert minted from its own CA (attacker chooses the subject/SAN). CONDITIONAL(trust_condition) when every candidate role pins aws:SourceArn to an EXISTING anchor (the new anchor won't match) or pins a cert subject/issuer the attacker cannot mint. BLOCKED if an SCP denies rolesanywhere:CreateTrustAnchor/UpdateTrustAnchor. Also needs a profile mapping the target role (see rule 3) unless one already exists — otherwise POTENTIAL(profile_required).

Narrative

{principal.name} can register a certificate authority it controls as a Roles Anywhere trust anchor (rolesanywhere:CreateTrustAnchor); it can then mint a client certificate and federate into {role.name} (which trusts the Roles Anywhere service principal), self-granting access to {role.name}.

Raw rule rules/derived/aws/rolesanywhere.yaml

id: aws-rolesanywhere-config-add-trust-anchor
emits: CanModifyTrust
description: Registering an attacker-controlled CA as a trust anchor lets the attacker mint certs that
  federate into any role trusting the Roles Anywhere service principal.
match:
- - principal: null
  - CanAdminister
  - raConfig: null
- - role: null
  - TrustsExternalIdentity
  - ext: null
where:
- 'node_type(?raConfig) == ManagementService  # the Roles Anywhere config resource (trust-anchor surface)'
- ?principal has EFFECTIVE rolesanywhere:CreateTrustAnchor OR rolesanywhere:UpdateTrustAnchor on ?raConfig
  (+ rolesanywhere:EnableTrustAnchor if disabled)
- node_type(?role) == Role
- the ?role -> ?ext TrustsExternalIdentity fact names Principal.Service == rolesanywhere.amazonaws.com
  with NO aws:SourceArn pin (so the newly-registered anchor qualifies) and a cert-attribute condition
  the attacker can satisfy with a self-minted cert
emit:
  source_type: Identity
  target_type: Role
  source: ?principal
  target: ?role
  permissions:
  - rolesanywhere:CreateTrustAnchor
  - rolesanywhere:UpdateTrustAnchor
  - rolesanywhere:EnableTrustAnchor?
  conditions:
  - trust_condition
  - iam_permission
  state_logic: "ACTIVE when a target role trusts the service principal with NO aws:SourceArn pin (any\
    \ anchor qualifies) AND either no cert-subject condition or one the attacker can satisfy with a cert\
    \ minted from its own CA (attacker chooses the subject/SAN). CONDITIONAL(trust_condition) when every\
    \ candidate role pins aws:SourceArn to an EXISTING anchor (the new anchor won't match) or pins a cert\
    \ subject/issuer the attacker cannot mint. BLOCKED if an SCP denies rolesanywhere:CreateTrustAnchor/UpdateTrustAnchor.\
    \ Also needs a profile mapping the target role (see rule 3) unless one already exists \u2014 otherwise\
    \ POTENTIAL(profile_required)."
  confidence: min(contributing_confidences) * 0.9
  derived_from:
  - ?principal CanAdminister ?raConfig (effective rolesanywhere:CreateTrustAnchor|UpdateTrustAnchor decision)
  - ?role TrustsExternalIdentity ?ext (role trusts rolesanywhere.amazonaws.com, no aws:SourceArn pin)
  note: 'Registering the anchor is only half the takeover: the attacker also needs a PROFILE that lists
    the target role (rule 3) and the role''s trust must admit the new anchor. Where a permissive profile
    already lists the role, this alone completes the self-grant.'
  false_positive_note: "Do NOT emit ACTIVE against roles that pin aws:SourceArn to a specific existing\
    \ trust anchor \u2014 a newly registered anchor's ARN will not match, so a self-minted cert is rejected\
    \ (keep CONDITIONAL(trust_condition)). An external-CA trust anchor requires the attacker to hold that\
    \ CA's private key; an ACM PCA anchor requires CanSignAs on the PCA (Phase-5 aws:acmpca) \u2014 if\
    \ the attacker cannot actually issue from the referenced CA, downgrade. Requires no iam:PassRole for\
    \ the anchor itself, but the paired profile (rule 3) does. This models trust ADDITION, distinct from\
    \ aws-update-assume-role-policy (which rewrites an existing role trust) \u2014 cite, do not double-count."
  narrative: '{principal.name} can register a certificate authority it controls as a Roles Anywhere trust
    anchor (rolesanywhere:CreateTrustAnchor); it can then mint a client certificate and federate into
    {role.name} (which trusts the Roles Anywhere service principal), self-granting access to {role.name}.'
move · open · esc close