-
Notifications
You must be signed in to change notification settings - Fork 176
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
GCP iam.serviceAccounts.signJwt Privilege Escalation - rule (#1126)
Co-authored-by: Ariel Ropek <[email protected]>
- Loading branch information
1 parent
6768251
commit f66e438
Showing
2 changed files
with
153 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
from gcp_base_helpers import gcp_alert_context | ||
from panther_base_helpers import deep_get, deep_walk | ||
|
||
|
||
def rule(event): | ||
if deep_get(event, "protoPayload", "methodName") != "SignJwt": | ||
return False | ||
|
||
authorization_info = deep_walk(event, "protoPayload", "authorizationInfo") | ||
if not authorization_info: | ||
return False | ||
|
||
for auth in authorization_info: | ||
if auth.get("permission") == "iam.serviceAccounts.signJwt" and auth.get("granted") is True: | ||
return True | ||
return False | ||
|
||
|
||
def title(event): | ||
actor = deep_get( | ||
event, "protoPayload", "authenticationInfo", "principalEmail", default="<ACTOR_NOT_FOUND>" | ||
) | ||
operation = deep_get(event, "protoPayload", "methodName", default="<OPERATION_NOT_FOUND>") | ||
project_id = deep_get(event, "resource", "labels", "project_id", default="<PROJECT_NOT_FOUND>") | ||
|
||
return f"[GCP]: [{actor}] performed [{operation}] on project [{project_id}]" | ||
|
||
|
||
def alert_context(event): | ||
context = gcp_alert_context(event) | ||
context["serviceAccountKeyName"] = deep_get( | ||
event, "protoPayload", "authenticationInfo", "serviceAccountKeyName" | ||
) | ||
return context |
119 changes: 119 additions & 0 deletions
119
rules/gcp_audit_rules/gcp_iam_serviceaccounts_signjwt.yml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
AnalysisType: rule | ||
Filename: gcp_iam_serviceaccounts_signjwt.py | ||
RuleID: "GCP.IAM.serviceAccounts.signJwt.Privilege.Escalation" | ||
DisplayName: "GCP IAM serviceAccounts.signJwt Privilege Escalation" | ||
Enabled: true | ||
LogTypes: | ||
- GCP.AuditLog | ||
Reports: | ||
MITRE ATT&CK: | ||
- TA0004:T1548 | ||
Severity: High | ||
Description: Detects iam.serviceAccounts.signJwt method for privilege escalation in GCP. This method works | ||
by signing well-formed JSON web tokens (JWTs). The script for this method will sign a well-formed JWT and | ||
request a new access token belonging to the Service Account with it. | ||
Runbook: These is not a vulnerability in GCP, this is a vulnerability in how you have configured your GCP environment, | ||
so it is your responsibility to be aware of these attack vectors and to defend against them. Make sure | ||
to follow the principle of least-privilege in your environments to help mitigate these security risks. | ||
Reference: https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/ | ||
Tests: | ||
- | ||
Name: JWT Signed | ||
ExpectedResult: true | ||
Log: | ||
{ | ||
"protoPayload": { | ||
"@type": "type.googleapis.com/google.cloud.audit.AuditLog", | ||
"status": { }, | ||
"authenticationInfo": { | ||
"principalEmail": "[email protected]", | ||
"serviceAccountKeyName": "//iam.googleapis.com/projects/some-project/serviceAccounts/[email protected]/keys/a378358365ff3d22e9c1a72fecf4605ddff76b47", | ||
"principalSubject": "serviceAccount:[email protected]" | ||
}, | ||
"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.signJwt", | ||
"granted": true, | ||
"resourceAttributes": { } | ||
} | ||
], | ||
"resourceName": "projects/-/serviceAccounts/114885146936855121342", | ||
"request": { | ||
"name": "projects/-/serviceAccounts/[email protected]", | ||
"@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": "[email protected]" | ||
} | ||
}, | ||
"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: JWT Not Signed | ||
ExpectedResult: false | ||
Log: | ||
{ | ||
"protoPayload": { | ||
"@type": "type.googleapis.com/google.cloud.audit.AuditLog", | ||
"status": { }, | ||
"authenticationInfo": { | ||
"principalEmail": "[email protected]", | ||
"serviceAccountKeyName": "//iam.googleapis.com/projects/some-project/serviceAccounts/[email protected]/keys/a378358365ff3d22e9c1a72fecf4605ddff76b47", | ||
"principalSubject": "serviceAccount:[email protected]" | ||
}, | ||
"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.signJwt", | ||
"granted": false, | ||
"resourceAttributes": { } | ||
} | ||
], | ||
"resourceName": "projects/-/serviceAccounts/114885146936855121342", | ||
"request": { | ||
"name": "projects/-/serviceAccounts/[email protected]", | ||
"@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": "[email protected]" | ||
} | ||
}, | ||
"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" | ||
} |