GCP Cloud Run Service Created


Description

Detects creation of new Cloud Run Service, which, if configured maliciously, may be part of the attack aimed to invoke the service and retrieve the access token.

Query · python

from panther_gcp_helpers import gcp_alert_context


def rule(event):
    if event.get("severity") == "ERROR":
        return False

    method_name = event.deep_get("protoPayload", "methodName", default="")
    if not method_name.endswith("Services.CreateService"):
        return False

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

    for auth in authorization_info:
        if auth.get("permission") == "run.services.create" and auth.get("granted") is True:
            return True
    return False


def title(event):
    actor = event.deep_get(
        "protoPayload", "authenticationInfo", "principalEmail", default="<ACTOR_NOT_FOUND>"
    )
    project_id = event.deep_get("resource", "labels", "project_id", default="<PROJECT_NOT_FOUND>")

    return f"[GCP]: [{actor}] created new Run Service in project [{project_id}]"


def alert_context(event):
    context = gcp_alert_context(event)
    context["service_account"] = event.deep_get(
        "protoPayload",
        "request",
        "service",
        "spec",
        "template",
        "spec",
        default="<SERVICE_ACCOUNT_NOT_FOUND>",
    )
    return context

Analyst notes

Confirm this was authorized and necessary behavior

Raw source GCP Cloud Run Service Created · Panther Python
Esc
Published by panther-labs/panther-analysis ↗, licensed under Apache 2.0 ↗. Reproduced here unmodified.
AnalysisType: rule
LogTypes:
  - GCP.AuditLog
Description:
  Detects creation of new Cloud Run Service, which, if configured maliciously, may be part of the attack
  aimed to invoke the service and retrieve the access token.
DisplayName: "GCP Cloud Run Service Created"
RuleID: "GCP.Cloud.Run.Service.Created"
Filename: gcp_cloud_run_service_created.py
Enabled: true
CreateAlert: false
Reference: https://cloud.google.com/run/docs/quickstarts/deploy-container
Runbook: Confirm this was authorized and necessary behavior
Severity: Low
DedupPeriodMinutes: 60
Threshold: 1
Tests:
  - Name: GCP No methodName found
    ExpectedResult: false
    Log:
      {
        "p_event_time": "2024-07-22 14:20:56.237323088",
        "p_log_type": "GCP.AuditLog",
        "insertId": "123456789xyz",
        "logName": "projects/internal-sentry/logs/cloudaudit.googleapis.com%2Factivity",
        "protoPayload":
          {
            "at_sign_type": "type.googleapis.com/google.cloud.audit.AuditLog",
            "authenticationInfo":
              {
                "principalEmail": "0000000000000@cloudbuild.gserviceaccount.com",
              },
            "authorizationInfo":
              [
                {
                  "granted": true,
                  "permission": "cloudbuild.builds.create",
                  "resource": "projects/00000000aaaaaaaa",
                  "resourceAttributes": {},
                },
              ],
            "requestMetadata":
              {
                "destinationAttributes": {},
                "requestAttributes":
                  { "auth": {}, "time": "2024-07-22T14:20:55.898367039Z" },
              },
          },
        "receiveTimestamp": "2024-07-22 14:20:56.428021476",
        "resource":
          {
            "labels":
              { "method": "", "project_id": "some-project", "service": "" },
            "type": "audited_resource",
          },
        "severity": "NOTICE",
        "timestamp": "2024-07-22 14:20:56.237323088",
      }
  - Name: GCP Run Service Created
    ExpectedResult: true
    Log:
      {
        "insertId": "jzm5rucrn2",
        "logName": "projects/some-project/logs/cloudaudit.googleapis.com%2Factivity",
        "protoPayload":
          {
            "at_sign_type": "type.googleapis.com/google.cloud.audit.AuditLog",
            "authenticationInfo":
              {
                "principalEmail": "some.user@company.com",
                "principalSubject": "user:some.user@company.com",
              },
            "authorizationInfo":
              [
                {
                  "granted": true,
                  "permission": "run.services.create",
                  "resource": "namespaces/some-project/services/cloudrun-exfil",
                  "resourceAttributes": {},
                },
              ],
            "methodName": "google.cloud.run.v1.Services.CreateService",
            "request":
              {
                "@type": "type.googleapis.com/google.cloud.run.v1.CreateServiceRequest",
                "parent": "namespaces/some-project",
                "service":
                  {
                    "apiVersion": "serving.knative.dev/v1",
                    "kind": "Service",
                    "metadata":
                      {
                        "annotations":
                          {
                            "client.knative.dev/user-image": "us-west1-docker.pkg.dev/some-project/abc-test/run_services_create_test",
                          },
                        "name": "cloudrun-exfil",
                        "namespace": "some-project",
                      },
                    "spec":
                      {
                        "template":
                          {
                            "metadata":
                              {
                                "annotations":
                                  {
                                    "client.knative.dev/user-image": "us-west1-docker.pkg.dev/some-project/abc-test/run_services_create_test",
                                  },
                                "labels":
                                  {
                                    "cloud.googleapis.com/location": "us-west1",
                                  },
                                "name": "cloudrun-exfil-00001-zif",
                              },
                            "spec":
                              {
                                "serviceAccountName": "abc-test@some-project.iam.gserviceaccount.com",
                              },
                          },
                      },
                  },
              },
            "requestMetadata":
              {
                "callerIP": "1.2.3.4",
                "callerSuppliedUserAgent": "(gzip),gzip(gfe)",
                "destinationAttributes": {},
                "requestAttributes":
                  { "auth": {}, "time": "2024-02-02T09:43:54.690161Z" },
              },
            "resourceLocation": { "currentLocations": ["us-west1"] },
            "resourceName": "namespaces/some-project/services/cloudrun-exfil",
            "response":
              {
                "@type": "type.googleapis.com/google.cloud.run.v1.Service",
                "apiVersion": "serving.knative.dev/v1",
                "kind": "Service",
                "metadata":
                  {
                    "annotations":
                      {
                        "client.knative.dev/user-image": "us-west1-docker.pkg.dev/some-project/abc-test/run_services_create_test",
                        "run.googleapis.com/ingress": "all",
                        "run.googleapis.com/operation-id": "6fdf115a-1bdd-4836-b0ca-ae71f8ba6718",
                        "serving.knative.dev/creator": "some.user@company.com",
                        "serving.knative.dev/lastModifier": "some.user@company.com",
                      },
                    "creationTimestamp": "2024-02-02T09:43:54.640837Z",
                    "generation": 1,
                    "labels": { "cloud.googleapis.com/location": "us-west1" },
                    "name": "cloudrun-exfil",
                    "namespace": "1028347275902",
                    "resourceVersion": "AAYQYvNHUcU",
                    "selfLink": "/apis/serving.knative.dev/v1/namespaces/1028347275902/services/cloudrun-exfil",
                    "uid": "45101e8e-7b91-4c41-81a1-969e876923f4",
                  },
                "spec":
                  {
                    "template":
                      {
                        "metadata":
                          {
                            "annotations":
                              {
                                "autoscaling.knative.dev/maxScale": "100",
                                "client.knative.dev/user-image": "us-west1-docker.pkg.dev/some-project/abc-test/run_services_create_test",
                              },
                            "labels":
                              {
                                "run.googleapis.com/startupProbeType": "Default",
                              },
                            "name": "cloudrun-exfil-00001-zif",
                          },
                        "spec":
                          {
                            "containerConcurrency": 80,
                            "serviceAccountName": "abc-test@some-project.iam.gserviceaccount.com",
                            "timeoutSeconds": 300,
                          },
                      },
                    "traffic": [{ "latestRevision": true, "percent": 100 }],
                  },
                "status": {},
              },
            "serviceName": "run.googleapis.com",
          },
        "receiveTimestamp": "2024-02-02 09:43:54.723840817",
        "resource":
          {
            "labels":
              {
                "configuration_name": "",
                "location": "us-west1",
                "project_id": "some-project",
                "revision_name": "",
                "service_name": "cloudrun-exfil",
              },
            "type": "cloud_run_revision",
          },
        "severity": "NOTICE",
        "timestamp": "2024-02-02 09:43:54.497796000",
      }
  - Name: GCP Run Service Not Created
    ExpectedResult: false
    Log:
      {
        "insertId": "jfca5rd3wqn",
        "logName": "projects/some-project/logs/cloudaudit.googleapis.com%2Factivity",
        "protoPayload":
          {
            "at_sign_type": "type.googleapis.com/google.cloud.audit.AuditLog",
            "authenticationInfo":
              {
                "principalEmail": "some.user@company.com",
                "principalSubject": "user:some.user@company.com",
              },
            "authorizationInfo":
              [
                {
                  "granted": true,
                  "permission": "run.services.create",
                  "resource": "namespaces/some-project/services/cloudrun-exfil",
                  "resourceAttributes": {},
                },
              ],
            "methodName": "google.cloud.run.v1.Services.CreateService",
            "request": ...,
            "requestMetadata": ...,
            "resourceLocation": ...,
            "resourceName": ...,
            "serviceName": "run.googleapis.com",
            "status":
              {
                "code": 6,
                "message": "Resource 'cloudrun-exfil' already exists.",
              },
          },
        "receiveTimestamp": "2024-02-02 09:36:22.250430490",
        "resource": ...,
        "severity": "ERROR",
        "timestamp": "2024-02-02 09:36:21.212182000",
      }


# ------ paired body: gcp_cloud_run_service_created.py ------

from panther_gcp_helpers import gcp_alert_context


def rule(event):
    if event.get("severity") == "ERROR":
        return False

    method_name = event.deep_get("protoPayload", "methodName", default="")
    if not method_name.endswith("Services.CreateService"):
        return False

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

    for auth in authorization_info:
        if auth.get("permission") == "run.services.create" and auth.get("granted") is True:
            return True
    return False


def title(event):
    actor = event.deep_get(
        "protoPayload", "authenticationInfo", "principalEmail", default="<ACTOR_NOT_FOUND>"
    )
    project_id = event.deep_get("resource", "labels", "project_id", default="<PROJECT_NOT_FOUND>")

    return f"[GCP]: [{actor}] created new Run Service in project [{project_id}]"


def alert_context(event):
    context = gcp_alert_context(event)
    context["service_account"] = event.deep_get(
        "protoPayload",
        "request",
        "service",
        "spec",
        "template",
        "spec",
        default="<SERVICE_ACCOUNT_NOT_FOUND>",
    )
    return context

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.