-
Notifications
You must be signed in to change notification settings - Fork 173
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Snowflake Data Exfiltration CR (#1257)
* Update Action versions; use SHAs (#1231) * Update Action versions; use SHAs * Add dependabot.yml to keep Actions updated * Update PAT to 0.49.0 * scheduled rules and correlation rule for snowflake data exfiltration * transition names * updates to comply with CR style guide * cleanup and pack update * MITRE ATT&CK tags --------- Co-authored-by: Evan Gibler <[email protected]> Co-authored-by: Ben Airey <[email protected]>
- Loading branch information
1 parent
e68dabf
commit aea5a39
Showing
11 changed files
with
244 additions
and
2 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 |
---|---|---|
|
@@ -4,7 +4,7 @@ on: | |
workflow_dispatch: | ||
|
||
permissions: | ||
contents: read | ||
contents: read | ||
|
||
jobs: | ||
release: | ||
|
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 |
---|---|---|
|
@@ -4,7 +4,7 @@ on: | |
- main | ||
|
||
permissions: | ||
contents: read | ||
contents: read | ||
|
||
jobs: | ||
upload: | ||
|
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,70 @@ | ||
AnalysisType: correlation_rule | ||
RuleID: "Snowflake.Data.Exfiltration" | ||
DisplayName: "Snowflake Data Exfiltration" | ||
Enabled: true | ||
Severity: Critical | ||
Description: In April 2024, Mandiant received threat intelligence on database records that were subsequently determined to have originated from a victim’s Snowflake instance. Mandiant notified the victim, who then engaged Mandiant to investigate suspected data theft involving their Snowflake instance. During this investigation, Mandiant determined that the organization’s Snowflake instance had been compromised by a threat actor using credentials previously stolen via infostealer malware. The threat actor used these stolen credentials to access the customer’s Snowflake instance and ultimately exfiltrate valuable data. At the time of the compromise, the account did not have multi-factor authentication (MFA) enabled. | ||
Reference: https://cloud.google.com/blog/topics/threat-intelligence/unc5537-snowflake-data-theft-extortion/ | ||
Reports: | ||
MITRE ATT&CK: | ||
- TA0010:T1041 # Exfiltration Over C2 Channel | ||
Detection: | ||
- Sequence: | ||
- ID: SnowflakeTempStageCreated | ||
RuleID: Snowflake.TempStageCreated | ||
- ID: SnowflakeCopyIntoStage | ||
RuleID: Snowflake.CopyIntoStage | ||
- ID: SnowflakeFileDownloaded | ||
RuleID: Snowflake.FileDownloaded | ||
Transitions: | ||
- ID: Match SnowflakeTempStageCreated and SnowflakeCopyIntoStage on stage | ||
From: SnowflakeTempStageCreated | ||
To: SnowflakeCopyIntoStage | ||
Match: | ||
- On: stage | ||
- ID: Match SnowflakeCopyIntoStage and SnowflakeFileDownloaded on path | ||
From: SnowflakeCopyIntoStage | ||
To: SnowflakeFileDownloaded | ||
Match: | ||
- On: stage | ||
Schedule: | ||
RateMinutes: 720 | ||
TimeoutMinutes: 2 | ||
LookbackWindowMinutes: 1440 | ||
Tests: | ||
- Name: Data Exfiltration | ||
ExpectedResult: true | ||
RuleOutputs: | ||
- ID: SnowflakeTempStageCreated | ||
Matches: | ||
stage: | ||
LOGS.PUBLIC.data_exfil: | ||
- "2006-01-02T15:04:05Z" | ||
- "2006-01-02T15:04:06Z" | ||
- ID: SnowflakeCopyIntoStage | ||
Matches: | ||
stage: | ||
LOGS.PUBLIC.data_exfil: | ||
- "2006-01-02T15:04:05Z" | ||
- "2006-01-02T15:04:06Z" | ||
- ID: SnowflakeFileDownloaded | ||
Matches: | ||
stage: | ||
LOGS.PUBLIC.data_exfil: | ||
- "2006-01-02T15:04:05Z" | ||
- "2006-01-02T15:04:06Z" | ||
- Name: Data Staged but not Downloaded | ||
ExpectedResult: false | ||
RuleOutputs: | ||
- ID: SnowflakeTempStageCreated | ||
Matches: | ||
stage: | ||
LOGS.PUBLIC.data_exfil: | ||
- "2006-01-02T15:04:05Z" | ||
- "2006-01-02T15:04:06Z" | ||
- ID: SnowflakeCopyIntoStage | ||
Matches: | ||
stage: | ||
LOGS.PUBLIC.data_exfil: | ||
- "2006-01-02T15:04:05Z" | ||
- "2006-01-02T15:04:06Z" |
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
2 changes: 2 additions & 0 deletions
2
queries/snowflake_queries/scheduled_rule_default_snowflake.py
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,2 @@ | ||
def rule(_): | ||
return True |
26 changes: 26 additions & 0 deletions
26
queries/snowflake_queries/snowflake_file_downloaded_query.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,26 @@ | ||
AnalysisType: scheduled_query | ||
QueryName: "Query.Snowflake.FileDownloaded" | ||
Enabled: true | ||
Description: https://cloud.google.com/blog/topics/threat-intelligence/unc5537-snowflake-data-theft-extortion/ | ||
Query: > | ||
SELECT | ||
user_name, | ||
role_name, | ||
start_time AS p_event_time, | ||
query_type, | ||
execution_status, | ||
regexp_substr(query_text, 'GET\\s+(\\$\\$|\\\')?@([a-zA-Z0-9_\\.]+)', 1, 1, 'i', 2) as stage, | ||
regexp_substr(query_text, 'GET\\s+(\\$\\$|\\\')?@([a-zA-Z0-9_\\./]+)(\\$\\$|\\\')?\\s', 1, 1, 'i', 2) as path, | ||
query_text | ||
FROM SNOWFLAKE.ACCOUNT_USAGE.QUERY_HISTORY | ||
WHERE query_type = 'GET_FILES' | ||
AND path IS NOT NULL | ||
AND p_occurs_since('1 day') | ||
AND execution_status = 'SUCCESS' | ||
LIMIT 100 | ||
Schedule: | ||
RateMinutes: 1440 | ||
TimeoutMinutes: 1 | ||
Tags: | ||
- data exfil |
29 changes: 29 additions & 0 deletions
29
queries/snowflake_queries/snowflake_file_downloaded_signal.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,29 @@ | ||
AnalysisType: scheduled_rule | ||
Filename: scheduled_rule_default_snowflake.py | ||
RuleID: "Snowflake.FileDownloaded" | ||
Description: > | ||
A file was downloaded from a stage | ||
DisplayName: "Snowflake File Downloaded" | ||
Enabled: true | ||
CreateAlert: false | ||
Reference: https://cloud.google.com/blog/topics/threat-intelligence/unc5537-snowflake-data-theft-extortion/ | ||
Reports: | ||
MITRE ATT&CK: | ||
- TA0010:T1041 # Exfiltration Over C2 Channel | ||
ScheduledQueries: | ||
- Query.Snowflake.FileDownloaded | ||
Severity: Info | ||
Tests: | ||
- Name: Value Returned By Query | ||
ExpectedResult: true | ||
Log: | ||
{ | ||
"execution_status": "SUCCESS", | ||
"path": "LOGS.PUBLIC.data_exfil/DATA.csv", | ||
"query_text": "GET '@LOGS.PUBLIC.data_exfil/DATA.csv' 'file:///Users/evil.genius/Documents'", | ||
"query_type": "GET_FILES", | ||
"role_name": "SYSADMIN", | ||
"stage": "LOGS.PUBLIC.data_exfil", | ||
"start_time": "2024-06-10 19:37:15.698Z", | ||
"user_name": "ADMIN" | ||
} |
26 changes: 26 additions & 0 deletions
26
queries/snowflake_queries/snowflake_table_copied_into_stage_query.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,26 @@ | ||
AnalysisType: scheduled_query | ||
QueryName: "Query.Snowflake.CopyIntoStage" | ||
Enabled: true | ||
Description: https://cloud.google.com/blog/topics/threat-intelligence/unc5537-snowflake-data-theft-extortion/ | ||
Query: > | ||
SELECT | ||
user_name, | ||
role_name, | ||
start_time AS p_event_time, | ||
query_type, | ||
execution_status, | ||
regexp_substr(query_text, 'COPY\\s+INTO\\s+(\\$\\$|\\\')?@([a-zA-Z0-9_\\.]+)', 1, 1, 'i', 2) as stage, | ||
regexp_substr(query_text, 'COPY\\s+INTO\\s+(\\$\\$|\\\')?@([a-zA-Z0-9_\\./]+)(\\$\\$|\\\')?\\s+FROM', 1, 1, 'i', 2) as path, | ||
query_text | ||
FROM SNOWFLAKE.ACCOUNT_USAGE.QUERY_HISTORY | ||
WHERE query_type = 'UNLOAD' | ||
AND stage IS NOT NULL | ||
AND p_occurs_since('1 day') | ||
AND execution_status = 'SUCCESS' | ||
LIMIT 100 | ||
Schedule: | ||
RateMinutes: 1440 | ||
TimeoutMinutes: 1 | ||
Tags: | ||
- data exfil |
29 changes: 29 additions & 0 deletions
29
queries/snowflake_queries/snowflake_table_copied_into_stage_signal.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,29 @@ | ||
AnalysisType: scheduled_rule | ||
Filename: scheduled_rule_default_snowflake.py | ||
RuleID: "Snowflake.CopyIntoStage" | ||
Description: > | ||
A table was copied into a stage | ||
DisplayName: "Snowflake Table Copied Into Stage" | ||
Enabled: true | ||
CreateAlert: false | ||
Reference: https://cloud.google.com/blog/topics/threat-intelligence/unc5537-snowflake-data-theft-extortion/ | ||
Reports: | ||
MITRE ATT&CK: | ||
- TA0010:T1041 # Exfiltration Over C2 Channel | ||
ScheduledQueries: | ||
- Query.Snowflake.CopyIntoStage | ||
Severity: Info | ||
Tests: | ||
- Name: Value Returned By Query | ||
ExpectedResult: true | ||
Log: | ||
{ | ||
"execution_status": "SUCCESS", | ||
"path": "LOGS.PUBLIC.data_exfil/DATA.csv", | ||
"query_text": "COPY INTO @LOGS.PUBLIC.data_exfil/DATA.csv\nFROM (SELECT * FROM PANTHER_LOGS.PUBLIC.GITLAB_API_VARIANT LIMIT 100)\nFILE_FORMAT = ( \n TYPE='CSV' \n COMPRESSION=GZIP\n FIELD_DELIMITER=',' \n ESCAPE=NONE \n ESCAPE_UNENCLOSED_FIELD=NONE \n date_format='AUTO' \n time_format='AUTO' \n timestamp_format='AUTO'\n binary_format='UTF-8' \n field_optionally_enclosed_by='\"' \n null_if='' \n EMPTY_FIELD_AS_NULL = FALSE \n) \noverwrite=TRUE \nsingle=FALSE \nmax_file_size=5368709120 \nheader=TRUE", | ||
"query_type": "UNLOAD", | ||
"role_name": "SYSADMIN", | ||
"stage": "LOGS.PUBLIC.data_exfil", | ||
"start_time": "2024-06-10 19:15:37.445Z", | ||
"user_name": "ADMIN" | ||
} |
25 changes: 25 additions & 0 deletions
25
queries/snowflake_queries/snowflake_temp_stage_created_query.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,25 @@ | ||
AnalysisType: scheduled_query | ||
QueryName: "Query.Snowflake.TempStageCreated" | ||
Enabled: true | ||
Description: https://cloud.google.com/blog/topics/threat-intelligence/unc5537-snowflake-data-theft-extortion/ | ||
Query: > | ||
SELECT | ||
user_name, | ||
role_name, | ||
start_time AS p_event_time, | ||
query_type, | ||
execution_status, | ||
regexp_substr(query_text, 'CREATE\\s+(OR\\s+REPLACE\\s+)?(TEMPORARY\\s+|TEMP\\s+)STAGE\\s+(IF\\s+NOT\\s+EXISTS\\s+)?([a-zA-Z0-9_\\.]+)', 1, 1, 'i', 4) as stage, | ||
query_text | ||
FROM SNOWFLAKE.ACCOUNT_USAGE.QUERY_HISTORY | ||
WHERE query_type = 'CREATE' | ||
AND stage IS NOT NULL | ||
AND p_occurs_since('1 day') | ||
AND execution_status = 'SUCCESS' | ||
LIMIT 100 | ||
Schedule: | ||
RateMinutes: 1440 | ||
TimeoutMinutes: 1 | ||
Tags: | ||
- data exfil |
28 changes: 28 additions & 0 deletions
28
queries/snowflake_queries/snowflake_temp_stage_created_signal.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,28 @@ | ||
AnalysisType: scheduled_rule | ||
Filename: scheduled_rule_default_snowflake.py | ||
RuleID: "Snowflake.TempStageCreated" | ||
Description: > | ||
A temporary stage was created | ||
DisplayName: "Snowflake Temporary Stage Created" | ||
Enabled: true | ||
CreateAlert: false | ||
Reference: https://cloud.google.com/blog/topics/threat-intelligence/unc5537-snowflake-data-theft-extortion/ | ||
Reports: | ||
MITRE ATT&CK: | ||
- TA0010:T1041 # Exfiltration Over C2 Channel | ||
ScheduledQueries: | ||
- Query.Snowflake.TempStageCreated | ||
Severity: Info | ||
Tests: | ||
- Name: Value Returned By Query | ||
ExpectedResult: true | ||
Log: | ||
{ | ||
"execution_status": "SUCCESS", | ||
"query_text": "CREATE OR REPLACE TEMP STAGE logs.PUBLIC.data_exfil", | ||
"query_type": "CREATE", | ||
"role_name": "SYSADMIN", | ||
"stage": "logs.PUBLIC.data_exfil", | ||
"start_time": "2024-06-10 19:48:52.068Z", | ||
"user_name": "ADMIN" | ||
} |