GCP IAM serviceAccounts getAccessToken Privilege Escalation


Description

The Identity and Access Management (IAM) service manages authorization and authentication for a GCP environment. This means that there are very likely multiple privilege escalation methods that use the IAM service and/or its permissions.

Query · python

from panther_gcp_helpers import gcp_alert_context


def rule(event):
    authorization_info = event.deep_walk("protoPayload", "authorizationInfo")
    if not authorization_info:
        return False

    for auth in authorization_info:
        if (
            auth.get("permission") == "iam.serviceAccounts.getAccessToken"
            and auth.get("granted") is True
        ):
            return True
    return False


def title(event):
    actor = event.udm("actor_user")
    operation = event.deep_get("protoPayload", "methodName", default="<OPERATION_NOT_FOUND>")
    project_id = event.deep_get("resource", "labels", "project_id", default="<PROJECT_NOT_FOUND>")

    return f"[GCP]: [{actor}] performed [{operation}] on project [{project_id}]"


def alert_context(event):
    return gcp_alert_context(event)
Raw source GCP IAM serviceAccounts getAccessToken Privilege Escalation · Panther Python
Esc
Published by panther-labs/panther-analysis ↗, licensed under Apache 2.0 ↗. Reproduced here unmodified.
AnalysisType: rule
Filename: gcp_iam_service_accounts_get_access_token_privilege_escalation.py
RuleID: "GCP.IAM.serviceAccounts.getAccessToken.Privilege.Escalation"
DisplayName: "GCP IAM serviceAccounts getAccessToken Privilege Escalation"
Enabled: true
LogTypes:
  - GCP.AuditLog
Reports:
  MITRE ATT&CK:
    - TA0004:T1548
Severity: High
Description:
  The Identity and Access Management (IAM) service manages authorization and authentication for a GCP environment.
  This means that there are very likely multiple privilege escalation methods that use the IAM service and/or its permissions.
Reference: https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/
Tests:
  - Name: iam.serviceAccounts.getAccessToken granted
    ExpectedResult: true
    Log:
      {
        "p_log_type": "GCP.AuditLog",
        "protoPayload":
          {
            "@type": "type.googleapis.com/google.cloud.audit.AuditLog",
            "status": {},
            "authenticationInfo":
              {
                "principalEmail": "some-project@company.iam.gserviceaccount.com",
                "serviceAccountKeyName": "//iam.googleapis.com/projects/some-project/serviceAccounts/some-project@company.iam.gserviceaccount.com/keys/a378358365ff3d22e9c1a72fecf4605ddff76b47",
                "principalSubject": "serviceAccount:some-project@company.iam.gserviceaccount.com",
              },
            "requestMetadata":
              {
                "callerIp": "1.2.3.4",
                "requestAttributes":
                  { "time": "2024-02-26T17:15:16.327542536Z", "auth": {} },
                "destinationAttributes": {},
              },
            "serviceName": "iamcredentials.googleapis.com",
            "methodName": "SignJwt",
            "authorizationInfo":
              [
                {
                  "permission": "iam.serviceAccounts.getAccessToken",
                  "granted": true,
                  "resourceAttributes": {},
                },
              ],
            "resourceName": "projects/-/serviceAccounts/114885146936855121342",
            "request":
              {
                "name": "projects/-/serviceAccounts/some-project@company.iam.gserviceaccount.com",
                "@type": "type.googleapis.com/google.iam.credentials.v1.SignJwtRequest",
              },
          },
        "insertId": "1hu88qbef4d2o",
        "resource":
          {
            "type": "service_account",
            "labels":
              {
                "project_id": "some-project",
                "unique_id": "114885146936855121342",
                "email_id": "some-project@company.iam.gserviceaccount.com",
              },
          },
        "timestamp": "2024-02-26T17:15:16.314854637Z",
        "severity": "INFO",
        "logName": "projects/some-project/logs/cloudaudit.googleapis.com%2Fdata_access",
        "receiveTimestamp": "2024-02-26T17:15:17.100020459Z",
      }
  - Name: iam.serviceAccounts.getAccessToken not granted
    ExpectedResult: false
    Log:
      {
        "p_log_type": "GCP.AuditLog",
        "protoPayload":
          {
            "@type": "type.googleapis.com/google.cloud.audit.AuditLog",
            "status": {},
            "authenticationInfo":
              {
                "principalEmail": "some-project@company.iam.gserviceaccount.com",
                "serviceAccountKeyName": "//iam.googleapis.com/projects/some-project/serviceAccounts/some-project@company.iam.gserviceaccount.com/keys/a378358365ff3d22e9c1a72fecf4605ddff76b47",
                "principalSubject": "serviceAccount:some-project@company.iam.gserviceaccount.com",
              },
            "requestMetadata":
              {
                "callerIp": "1.2.3.4",
                "requestAttributes":
                  { "time": "2024-02-26T17:15:16.327542536Z", "auth": {} },
                "destinationAttributes": {},
              },
            "serviceName": "iamcredentials.googleapis.com",
            "methodName": "SignJwt",
            "authorizationInfo":
              [
                {
                  "permission": "iam.serviceAccounts.getAccessToken",
                  "granted": false,
                  "resourceAttributes": {},
                },
              ],
            "resourceName": "projects/-/serviceAccounts/114885146936855121342",
            "request":
              {
                "name": "projects/-/serviceAccounts/some-project@company.iam.gserviceaccount.com",
                "@type": "type.googleapis.com/google.iam.credentials.v1.SignJwtRequest",
              },
          },
        "insertId": "1hu88qbef4d2o",
        "resource":
          {
            "type": "service_account",
            "labels":
              {
                "project_id": "some-project",
                "unique_id": "114885146936855121342",
                "email_id": "some-project@company.iam.gserviceaccount.com",
              },
          },
        "timestamp": "2024-02-26T17:15:16.314854637Z",
        "severity": "INFO",
        "logName": "projects/some-project/logs/cloudaudit.googleapis.com%2Fdata_access",
        "receiveTimestamp": "2024-02-26T17:15:17.100020459Z",
      }
  - Name: Principal Subject Used
    ExpectedResult: true
    Log:
      {
        "p_log_type": "GCP.AuditLog",
        "insertId": "1dy9ihte4iyjz",
        "logName": "projects/mylogs/logs/cloudaudit.googleapis.com%2Fdata_access",
        "operation": {
          "first": true,
          "id": "10172500524907939495",
          "last": true,
          "producer": "iamcredentials.googleapis.com"
        },
        "protoPayload": {
          "at_sign_type": "type.googleapis.com/google.cloud.audit.AuditLog",
          "authenticationInfo": {
            "principalSubject": "example_principal_subject",
            "serviceAccountDelegationInfo": [
              {}
            ]
          },
          "authorizationInfo": [
            {
              "granted": true,
              "permission": "iam.serviceAccounts.getAccessToken",
              "resourceAttributes": {}
            }
          ],
          "metadata": {
            "identityDelegationChain": [
              "projects/-/serviceAccounts/xxxxx.iam.gserviceaccount.com"
            ]
          },
          "methodName": "GenerateAccessToken",
          "request": {
            "@type": "type.googleapis.com/google.iam.credentials.v1.GenerateAccessTokenRequest",
            "name": "projects/-/serviceAccounts/xxxxx.iam.gserviceaccount.com"
          },
          "requestMetadata": {
            "callerIP": "gce-internal-ip",
            "callerSuppliedUserAgent": "google-api-go-client/0.5 gke-metadata-server,gzip(gfe)",
            "destinationAttributes": {},
            "requestAttributes": {
              "auth": {},
              "time": "2024-08-29T19:30:36.353462175Z"
            }
          },
          "resourceName": "projects/-/serviceAccounts/11111222223333444455",
          "serviceName": "iamcredentials.googleapis.com",
          "status": {}
        },
        "receiveTimestamp": "2024-08-29 19:30:36.424542070",
        "resource": {
          "labels": {
            "email_id": "sample@email.com",
            "project_id": "sample_project_id",
            "unique_id": "11111222223333444455"
          },
          "type": "service_account"
        },
        "severity": "INFO",
        "timestamp": "2024-08-29 19:30:36.339983306"
      }


# ------ paired body: gcp_iam_service_accounts_get_access_token_privilege_escalation.py ------

from panther_gcp_helpers import gcp_alert_context


def rule(event):
    authorization_info = event.deep_walk("protoPayload", "authorizationInfo")
    if not authorization_info:
        return False

    for auth in authorization_info:
        if (
            auth.get("permission") == "iam.serviceAccounts.getAccessToken"
            and auth.get("granted") is True
        ):
            return True
    return False


def title(event):
    actor = event.udm("actor_user")
    operation = event.deep_get("protoPayload", "methodName", default="<OPERATION_NOT_FOUND>")
    project_id = event.deep_get("resource", "labels", "project_id", default="<PROJECT_NOT_FOUND>")

    return f"[GCP]: [{actor}] performed [{operation}] on project [{project_id}]"


def alert_context(event):
    return gcp_alert_context(event)

Detection rules belong to the projects that publish them and remain under their own licenses. This site indexes and links to them; it claims no rights in them.