Skip to content

Invite an External User to a GCP Project

idempotent

Platform: GCP

MITRE ATT&CK Tactics

  • Persistence

Description

Persists in the GCP project by inviting an external (fictitious) user to the project. The attacker could then use the external user to access the project.

Warm-up: None

Detonation:

  • Updates the project IAM policy to grant the attacker account the role roles/editor

Note

Since the target e-mail must exist for this attack simulation to work, Stratus Red Team grants the role to stratusredteam@gmail.com by default. This is a real Google account, owned by Stratus Red Team maintainers and that is not used for any other purpose than this attack simulation. However, you can override this behavior by setting the environment variable STRATUS_RED_TEAM_ATTACKER_EMAIL, for instance:

export STRATUS_RED_TEAM_ATTACKER_EMAIL="your-own-gmail-account@gmail.com"
stratus detonate gcp.persistence.invite-external-user

Instructions

Detonate with Stratus Red Team
stratus detonate gcp.persistence.invite-external-user

Detection

The Google Cloud Admin logs event SetIamPolicy is generated when a principal is granted non-owner permissions at the project level.

{
  "protoPayload": {
    "@type": "type.googleapis.com/google.cloud.audit.AuditLog",
    "serviceName": "cloudresourcemanager.googleapis.com",
    "methodName": "SetIamPolicy",
    "serviceData": {
      "@type": "type.googleapis.com/google.iam.v1.logging.AuditData",
      "policyDelta": {
        "bindingDeltas": [
          {
            "action": "ADD",
            "role": "roles/editor",
            "member": "user:stratusredteam@gmail.com"
          }
        ]
      }
    },
    "request": {
      "resource": "target-project",
      "policy": {
        // ...
      },
      "@type": "type.googleapis.com/google.iam.v1.SetIamPolicyRequest"
    }
  }
}

Although this attack technique does not simulate it, an attacker can also use the GCP console to invite an external user as owner of a GCP project, which cannot be done through the SetIamPolicy API call. In that case, an InsertProjectOwnershipInvite event is generated:

{
  "protoPayload": {
    "@type": "type.googleapis.com/google.cloud.audit.AuditLog",
    "serviceName": "cloudresourcemanager.googleapis.com",
    "methodName": "InsertProjectOwnershipInvite",
    "resourceName": "projects/target-project",
    "request": {
      "member": "user:attacker@gmail.com",
      "projectId": "target-project",
      "@type": "type.googleapis.com/google.internal.cloud.resourcemanager.InsertProjectOwnershipInviteRequest"
    },
    "response": {
      "@type": "type.googleapis.com/google.internal.cloud.resourcemanager.InsertProjectOwnershipInviteResponse"
    }
  }
}