Skip to content

Commit aea5a39

Browse files
arielkr256Evan Giblerben-githubs
authored
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]>
1 parent e68dabf commit aea5a39

11 files changed

+244
-2
lines changed

.github/workflows/release.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ on:
44
workflow_dispatch:
55

66
permissions:
7-
contents: read
7+
contents: read
88

99
jobs:
1010
release:

.github/workflows/upload.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ on:
44
- main
55

66
permissions:
7-
contents: read
7+
contents: read
88

99
jobs:
1010
upload:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
AnalysisType: correlation_rule
2+
RuleID: "Snowflake.Data.Exfiltration"
3+
DisplayName: "Snowflake Data Exfiltration"
4+
Enabled: true
5+
Severity: Critical
6+
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.
7+
Reference: https://cloud.google.com/blog/topics/threat-intelligence/unc5537-snowflake-data-theft-extortion/
8+
Reports:
9+
MITRE ATT&CK:
10+
- TA0010:T1041 # Exfiltration Over C2 Channel
11+
Detection:
12+
- Sequence:
13+
- ID: SnowflakeTempStageCreated
14+
RuleID: Snowflake.TempStageCreated
15+
- ID: SnowflakeCopyIntoStage
16+
RuleID: Snowflake.CopyIntoStage
17+
- ID: SnowflakeFileDownloaded
18+
RuleID: Snowflake.FileDownloaded
19+
Transitions:
20+
- ID: Match SnowflakeTempStageCreated and SnowflakeCopyIntoStage on stage
21+
From: SnowflakeTempStageCreated
22+
To: SnowflakeCopyIntoStage
23+
Match:
24+
- On: stage
25+
- ID: Match SnowflakeCopyIntoStage and SnowflakeFileDownloaded on path
26+
From: SnowflakeCopyIntoStage
27+
To: SnowflakeFileDownloaded
28+
Match:
29+
- On: stage
30+
Schedule:
31+
RateMinutes: 720
32+
TimeoutMinutes: 2
33+
LookbackWindowMinutes: 1440
34+
Tests:
35+
- Name: Data Exfiltration
36+
ExpectedResult: true
37+
RuleOutputs:
38+
- ID: SnowflakeTempStageCreated
39+
Matches:
40+
stage:
41+
LOGS.PUBLIC.data_exfil:
42+
- "2006-01-02T15:04:05Z"
43+
- "2006-01-02T15:04:06Z"
44+
- ID: SnowflakeCopyIntoStage
45+
Matches:
46+
stage:
47+
LOGS.PUBLIC.data_exfil:
48+
- "2006-01-02T15:04:05Z"
49+
- "2006-01-02T15:04:06Z"
50+
- ID: SnowflakeFileDownloaded
51+
Matches:
52+
stage:
53+
LOGS.PUBLIC.data_exfil:
54+
- "2006-01-02T15:04:05Z"
55+
- "2006-01-02T15:04:06Z"
56+
- Name: Data Staged but not Downloaded
57+
ExpectedResult: false
58+
RuleOutputs:
59+
- ID: SnowflakeTempStageCreated
60+
Matches:
61+
stage:
62+
LOGS.PUBLIC.data_exfil:
63+
- "2006-01-02T15:04:05Z"
64+
- "2006-01-02T15:04:06Z"
65+
- ID: SnowflakeCopyIntoStage
66+
Matches:
67+
stage:
68+
LOGS.PUBLIC.data_exfil:
69+
- "2006-01-02T15:04:05Z"
70+
- "2006-01-02T15:04:06Z"

packs/snowflake.yml

+7
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,13 @@ PackDefinition:
1313
- Query.Snowflake.BruteForceByIp
1414
- Query.Snowflake.BruteForceByUsername
1515
- Query.Snowflake.ClientIp
16+
- Query.Snowflake.CopyIntoStage
1617
- Query.Snowflake.External.Shares
18+
- Query.Snowflake.FileDownloaded
1719
- Query.Snowflake.KeyUserPasswordLogin
1820
- Query.Snowflake.Multiple.Logins.Followed.By.Success
1921
- Query.Snowflake.SuspectedUserAccess
22+
- Query.Snowflake.TempStageCreated
2023
- Query.Snowflake.UserCreated
2124
- Query.Snowflake.UserEnabled
2225
# Rules
@@ -25,9 +28,13 @@ PackDefinition:
2528
- Snowflake.BruteForceByUsername
2629
- Snowflake.Client.IP
2730
- Snowflake.Configuration.Drift
31+
- Snowflake.CopyIntoStage
32+
- Snowflake.Data.Exfiltration
2833
- Snowflake.External.Shares
34+
- Snowflake.FileDownloaded
2935
- Snowflake.KeyUserPasswordLogin
3036
- Snowflake.Multiple.Failed.Logins.Followed.By.Success
37+
- Snowflake.TempStageCreated
3138
- Snowflake.User.Access
3239
- Snowflake.UserCreated
3340
- Snowflake.UserEnabled
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
def rule(_):
2+
return True
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
AnalysisType: scheduled_query
2+
QueryName: "Query.Snowflake.FileDownloaded"
3+
Enabled: true
4+
Description: https://cloud.google.com/blog/topics/threat-intelligence/unc5537-snowflake-data-theft-extortion/
5+
Query: >
6+
SELECT
7+
user_name,
8+
role_name,
9+
start_time AS p_event_time,
10+
query_type,
11+
execution_status,
12+
regexp_substr(query_text, 'GET\\s+(\\$\\$|\\\')?@([a-zA-Z0-9_\\.]+)', 1, 1, 'i', 2) as stage,
13+
regexp_substr(query_text, 'GET\\s+(\\$\\$|\\\')?@([a-zA-Z0-9_\\./]+)(\\$\\$|\\\')?\\s', 1, 1, 'i', 2) as path,
14+
query_text
15+
16+
FROM SNOWFLAKE.ACCOUNT_USAGE.QUERY_HISTORY
17+
WHERE query_type = 'GET_FILES'
18+
AND path IS NOT NULL
19+
AND p_occurs_since('1 day')
20+
AND execution_status = 'SUCCESS'
21+
LIMIT 100
22+
Schedule:
23+
RateMinutes: 1440
24+
TimeoutMinutes: 1
25+
Tags:
26+
- data exfil
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
AnalysisType: scheduled_rule
2+
Filename: scheduled_rule_default_snowflake.py
3+
RuleID: "Snowflake.FileDownloaded"
4+
Description: >
5+
A file was downloaded from a stage
6+
DisplayName: "Snowflake File Downloaded"
7+
Enabled: true
8+
CreateAlert: false
9+
Reference: https://cloud.google.com/blog/topics/threat-intelligence/unc5537-snowflake-data-theft-extortion/
10+
Reports:
11+
MITRE ATT&CK:
12+
- TA0010:T1041 # Exfiltration Over C2 Channel
13+
ScheduledQueries:
14+
- Query.Snowflake.FileDownloaded
15+
Severity: Info
16+
Tests:
17+
- Name: Value Returned By Query
18+
ExpectedResult: true
19+
Log:
20+
{
21+
"execution_status": "SUCCESS",
22+
"path": "LOGS.PUBLIC.data_exfil/DATA.csv",
23+
"query_text": "GET '@LOGS.PUBLIC.data_exfil/DATA.csv' 'file:///Users/evil.genius/Documents'",
24+
"query_type": "GET_FILES",
25+
"role_name": "SYSADMIN",
26+
"stage": "LOGS.PUBLIC.data_exfil",
27+
"start_time": "2024-06-10 19:37:15.698Z",
28+
"user_name": "ADMIN"
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
AnalysisType: scheduled_query
2+
QueryName: "Query.Snowflake.CopyIntoStage"
3+
Enabled: true
4+
Description: https://cloud.google.com/blog/topics/threat-intelligence/unc5537-snowflake-data-theft-extortion/
5+
Query: >
6+
SELECT
7+
user_name,
8+
role_name,
9+
start_time AS p_event_time,
10+
query_type,
11+
execution_status,
12+
regexp_substr(query_text, 'COPY\\s+INTO\\s+(\\$\\$|\\\')?@([a-zA-Z0-9_\\.]+)', 1, 1, 'i', 2) as stage,
13+
regexp_substr(query_text, 'COPY\\s+INTO\\s+(\\$\\$|\\\')?@([a-zA-Z0-9_\\./]+)(\\$\\$|\\\')?\\s+FROM', 1, 1, 'i', 2) as path,
14+
query_text
15+
16+
FROM SNOWFLAKE.ACCOUNT_USAGE.QUERY_HISTORY
17+
WHERE query_type = 'UNLOAD'
18+
AND stage IS NOT NULL
19+
AND p_occurs_since('1 day')
20+
AND execution_status = 'SUCCESS'
21+
LIMIT 100
22+
Schedule:
23+
RateMinutes: 1440
24+
TimeoutMinutes: 1
25+
Tags:
26+
- data exfil
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
AnalysisType: scheduled_rule
2+
Filename: scheduled_rule_default_snowflake.py
3+
RuleID: "Snowflake.CopyIntoStage"
4+
Description: >
5+
A table was copied into a stage
6+
DisplayName: "Snowflake Table Copied Into Stage"
7+
Enabled: true
8+
CreateAlert: false
9+
Reference: https://cloud.google.com/blog/topics/threat-intelligence/unc5537-snowflake-data-theft-extortion/
10+
Reports:
11+
MITRE ATT&CK:
12+
- TA0010:T1041 # Exfiltration Over C2 Channel
13+
ScheduledQueries:
14+
- Query.Snowflake.CopyIntoStage
15+
Severity: Info
16+
Tests:
17+
- Name: Value Returned By Query
18+
ExpectedResult: true
19+
Log:
20+
{
21+
"execution_status": "SUCCESS",
22+
"path": "LOGS.PUBLIC.data_exfil/DATA.csv",
23+
"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",
24+
"query_type": "UNLOAD",
25+
"role_name": "SYSADMIN",
26+
"stage": "LOGS.PUBLIC.data_exfil",
27+
"start_time": "2024-06-10 19:15:37.445Z",
28+
"user_name": "ADMIN"
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
AnalysisType: scheduled_query
2+
QueryName: "Query.Snowflake.TempStageCreated"
3+
Enabled: true
4+
Description: https://cloud.google.com/blog/topics/threat-intelligence/unc5537-snowflake-data-theft-extortion/
5+
Query: >
6+
SELECT
7+
user_name,
8+
role_name,
9+
start_time AS p_event_time,
10+
query_type,
11+
execution_status,
12+
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,
13+
query_text
14+
15+
FROM SNOWFLAKE.ACCOUNT_USAGE.QUERY_HISTORY
16+
WHERE query_type = 'CREATE'
17+
AND stage IS NOT NULL
18+
AND p_occurs_since('1 day')
19+
AND execution_status = 'SUCCESS'
20+
LIMIT 100
21+
Schedule:
22+
RateMinutes: 1440
23+
TimeoutMinutes: 1
24+
Tags:
25+
- data exfil
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
AnalysisType: scheduled_rule
2+
Filename: scheduled_rule_default_snowflake.py
3+
RuleID: "Snowflake.TempStageCreated"
4+
Description: >
5+
A temporary stage was created
6+
DisplayName: "Snowflake Temporary Stage Created"
7+
Enabled: true
8+
CreateAlert: false
9+
Reference: https://cloud.google.com/blog/topics/threat-intelligence/unc5537-snowflake-data-theft-extortion/
10+
Reports:
11+
MITRE ATT&CK:
12+
- TA0010:T1041 # Exfiltration Over C2 Channel
13+
ScheduledQueries:
14+
- Query.Snowflake.TempStageCreated
15+
Severity: Info
16+
Tests:
17+
- Name: Value Returned By Query
18+
ExpectedResult: true
19+
Log:
20+
{
21+
"execution_status": "SUCCESS",
22+
"query_text": "CREATE OR REPLACE TEMP STAGE logs.PUBLIC.data_exfil",
23+
"query_type": "CREATE",
24+
"role_name": "SYSADMIN",
25+
"stage": "logs.PUBLIC.data_exfil",
26+
"start_time": "2024-06-10 19:48:52.068Z",
27+
"user_name": "ADMIN"
28+
}

0 commit comments

Comments
 (0)