Skip to content

Commit

Permalink
Merge branch 'develop' into THREAT-394/snowflake-anomaly-queries
Browse files Browse the repository at this point in the history
  • Loading branch information
ben-githubs authored Oct 23, 2024
2 parents 3c5b6ce + d737f4f commit 3f23ec9
Show file tree
Hide file tree
Showing 49 changed files with 1,204 additions and 829 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/check-deprecated.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
on:
pull_request:
branches:
- develop

permissions:
contents: read
Expand Down
7 changes: 5 additions & 2 deletions .github/workflows/check-packs.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
on:
workflow_dispatch:
pull_request:
branches:
- develop

permissions:
contents: read
Expand Down Expand Up @@ -52,7 +55,7 @@ jobs:
```diff
${{ steps.check-packs.outputs.errors }}
```
comment_tag: check-packs
comment-tag: check-packs
- name: Delete comment
uses: thollander/actions-comment-pull-request@e2c37e53a7d2227b61585343765f73a9ca57eda9
if: ${{ !steps.check-packs.outputs.errors }}
Expand All @@ -64,4 +67,4 @@ jobs:
```diff
${{ steps.check-packs.outputs.errors }}
```
comment_tag: check-packs
comment-tag: check-packs
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,4 @@ jobs:

- name: test
run: |
pipenv run panther_analysis_tool test --api-host ${{ env.API_HOST }} --api-token ${{ env.API_TOKEN }}
pipenv run panther_analysis_tool test --api-host ${{ env.API_HOST }} --api-token ${{ env.API_TOKEN }} --show-failures-only
2 changes: 1 addition & 1 deletion .github/workflows/upload.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
on:
push:
branches:
- release
- develop

permissions:
contents: read
Expand Down
2 changes: 1 addition & 1 deletion Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ wrapt = "~=1.15"
[packages]
policyuniverse = "==1.5.1.20230817"
requests = "==2.31.0"
panther-analysis-tool = "~=0.53.0"
panther-analysis-tool = "~=0.54.0"
panther-detection-helpers = "==0.4.0"

[requires]
Expand Down
1,427 changes: 774 additions & 653 deletions Pipfile.lock

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions global_helpers/panther_thinkstcanary_helpers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
def additional_details(event):
details = event.get("AdditionalDetails", [])
return {detail[0]: detail[-1] for detail in details}
5 changes: 5 additions & 0 deletions global_helpers/panther_thinkstcanary_helpers.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
AnalysisType: global
Filename: panther_thinkstcanary_helpers.py
GlobalID: "panther_thinkstcanary_helpers"
Description: >
Global helpers for ThinkstCanary detections
1 change: 1 addition & 0 deletions packs/aws.yml
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ PackDefinition:
- AWS.VPC.FlowLogs
- AWS.WAF.Disassociation
- AWS.WAF.HasXSSPredicate
- AWS.WAF.LoggingConfigured
# Other rules
- AWS.CloudTrail.Account.Discovery
- AWS.CloudTrail.CloudWatchLogs
Expand Down
11 changes: 11 additions & 0 deletions packs/thinkstcanary.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
AnalysisType: pack
PackID: PantherManaged.ThinkstCanary
Description: Group of all ThinkstCanary detections
PackDefinition:
IDs:
- Thinkst.CanaryDCRC
- Thinkst.CanaryIncident
- Thinkst.CanaryTokenIncident
# Globals used in these detections
- panther_thinkstcanary_helpers
DisplayName: "Panther ThinkstCanary Pack"
29 changes: 29 additions & 0 deletions policies/aws_waf_policies/aws_waf_logging_configured.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
def is_valid_arn(arn, service):
if service == "logs":
return arn.startswith("arn:aws:logs:") and ":log-group:" in arn
if service == "s3":
return arn.startswith("arn:aws:s3:::") and len(arn.split(":")) == 6
if service == "firehose":
return arn.startswith("arn:aws:firehose:") and ":deliverystream/" in arn
return False


def policy(resource):
# Check if WAF logging configuration exists
logging_config = resource.get("LoggingConfiguration")
if not logging_config:
return False

# Get the logging destinations
destinations = logging_config.get("LogDestinationConfigs", [])

# Validate the ARNs for CloudWatch Logs, S3, or Kinesis Firehose
for destination in destinations:
if (
is_valid_arn(destination, "logs")
or is_valid_arn(destination, "s3")
or is_valid_arn(destination, "firehose")
):
return True

return False
91 changes: 91 additions & 0 deletions policies/aws_waf_policies/aws_waf_logging_configured.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
AnalysisType: policy
Filename: aws_waf_logging_configured.py
PolicyID: "AWS.WAF.LoggingConfigured"
DisplayName: "AWS WAF Logging Configured"
Enabled: true
ResourceTypes:
- AWS.WAF.Regional.WebACL
- AWS.WAF.WebACL
Tags:
- AWS
- Monitoring
- Logging
- Security Control
- Defense Evasion:Impair Defenses
Reports:
PCI:
- 10.5.5
MITRE ATT&CK:
- TA0005:T1562
Severity: High
Description: >
Ensures that AWS WAF logging is enabled and that the logs are being sent to a valid destination (S3, CloudWatch, or Kinesis Firehose). Without logging, visibility into WAF activity is severely limited, increasing the risk of undetected attacks.
Runbook: >
Ensure AWS WAF logging is configured to at least one valid destination such as an Amazon S3 bucket, Amazon CloudWatch Logs, or Amazon Kinesis Data Firehose. Refer to the AWS WAF logging documentation for setup instructions.
Reference: https://docs.aws.amazon.com/waf/latest/developerguide/logging.html
Tests:
- Name: WAF Logging Configured to CloudWatch Logs
ExpectedResult: true
Resource:
LoggingConfiguration:
LogDestinationConfigs:
- "arn:aws:logs:us-west-2:123456789012:log-group:example-log-group"
RedactedFields: null

- Name: WAF Logging Configured to S3
ExpectedResult: true
Resource:
LoggingConfiguration:
LogDestinationConfigs:
- "arn:aws:s3:::example-bucket/waf-logs/"
RedactedFields: null

- Name: WAF Logging Configured to Kinesis Firehose
ExpectedResult: true
Resource:
LoggingConfiguration:
LogDestinationConfigs:
- "arn:aws:firehose:us-west-2:123456789012:deliverystream/example-firehose"
RedactedFields: null

- Name: WAF Logging Not Configured
ExpectedResult: false
Resource:
LoggingConfiguration: null

# Edge Case 1: Malformed CloudWatch Logs ARN
- Name: WAF Logging Configured with Malformed CloudWatch Logs ARN
ExpectedResult: false
Resource:
LoggingConfiguration:
LogDestinationConfigs:
- "arn:aws:logs:us-west-2:123456789012" # Incorrect ARN format
RedactedFields: null

# Edge Case 2: Malformed S3 ARN
- Name: WAF Logging Configured with Malformed S3 ARN
ExpectedResult: false
Resource:
LoggingConfiguration:
LogDestinationConfigs:
- "arn:aws:s3::example-bucket-wrong-format" # Incorrect ARN format
RedactedFields: null

# Edge Case 3: Multiple Valid Logging Destinations (S3 and Kinesis Firehose)
- Name: WAF Logging Configured to Both S3 and Kinesis Firehose
ExpectedResult: true
Resource:
LoggingConfiguration:
LogDestinationConfigs:
- "arn:aws:s3:::example-bucket/waf-logs/"
- "arn:aws:firehose:us-west-2:123456789012:deliverystream/example-firehose"
RedactedFields: null

# Edge Case 4: Malformed Kinesis Firehose ARN
- Name: WAF Logging Configured with Malformed Kinesis Firehose ARN
ExpectedResult: false
Resource:
LoggingConfiguration:
LogDestinationConfigs:
- "arn:aws:firehose:us-west-2" # Incorrect ARN format
RedactedFields: null
5 changes: 1 addition & 4 deletions queries/aws_queries/cloudtrail_password_spraying_query.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,7 @@ QueryName: "Query.CloudTrail.Password.Spraying"
Enabled: false
Description: >
Detect password spraying in cloudtrail logs
AthenaQuery: |
/* athena query not supported */
SELECT count(1)
SnowflakeQuery: |
Query: |
SELECT
-- this information will be in the alert events
awsRegion as region,
Expand Down
5 changes: 1 addition & 4 deletions queries/aws_queries/ec2_crud_activity_by_role_query.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,7 @@ QueryName: "Query.EC2.CRUD.Activity.Role"
Enabled: false
Description: >
This query searches for CRUD activity in EC2 by role arn. Activities from a role outside typical deployment processes may warrant investigation.
AthenaQuery: |
/* athena query not supported */
SELECT count(1)
SnowflakeQuery: |
Query: |
SELECT
count(*) as num_logs,
recipientAccountId,
Expand Down
5 changes: 1 addition & 4 deletions queries/aws_queries/ec2_crud_activity_by_useragent_query.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,7 @@ QueryName: "Query.EC2.CRUD.Activity.Useragent"
Enabled: false
Description: >
This query searches for CRUD activity in EC2 by userAgent. A low count or previously unseen useragent may indicate that the action was not performed by an automated process.
AthenaQuery: |
/* athena query not supported */
SELECT count(1)
SnowflakeQuery: |
Query: |
SELECT
count(*) as num_logs,
recipientAccountId,
Expand Down
5 changes: 1 addition & 4 deletions queries/aws_queries/vpc_dns_tunneling_query.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,7 @@ QueryName: "Query.VPC.DNS.Tunneling"
Enabled: false
Description: >
Detect activity similar to DNS tunneling traffic in AWS VPC Logs
AthenaQuery: |
/* athena query not supported */
SELECT count(1)
SnowflakeQuery: |
Query: |
SELECT
account_id,
region,
Expand Down
12 changes: 1 addition & 11 deletions queries/okta_queries/okta_activity_audit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,7 @@ QueryName: "Okta Investigate User Activity"
Enabled: false
Description: >
Audit user activity across your environment. Customize to filter on specific users, time ranges, etc
AthenaQuery: |
SELECT actor.displayName AS actor_name, actor.alternateId AS actor_email, eventType, COUNT(*) AS activity_count
FROM panther_logs.okta_systemlog
WHERE p_occurs_since('7 days')
AND actor.type = 'User'
-- Uncomment lines below to filter by user email and/or eventType
-- and actor_email = '<EMAIL_GOES_HERE>'
-- and eventType = '<EVENTTYPE_GOES_HERE>'
GROUP BY actor.displayName, actor.alternateId, eventType
ORDER BY actor_name, activity_count DESC
SnowflakeQuery: |
Query: |
SELECT actor:displayName AS actor_name, actor:alternateId AS actor_email, eventType, COUNT(*) AS activity_count
FROM panther_logs.public.okta_systemlog
WHERE p_occurs_since('7 days')
Expand Down
25 changes: 1 addition & 24 deletions queries/okta_queries/okta_admin_access_granted.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,7 @@ QueryName: "Okta Admin Access Granted"
Enabled: false
Description: >
Audit instances of admin access granted in your okta tenant
AthenaQuery: |
SELECT
p_event_time as event_time,
actor.alternateid as actor_email,
actor.displayName as actor_name,
displayMessage,
eventType,
json_extract(debugcontext.debugdata, '$.privilegeGranted') as priv_granted,
target as target_name,
client.ipAddress as src_ip,
client.geographicalContext.city as city,
client.geographicalContext.country as country,
client.useragent.rawUserAgent as user_agent
FROM panther_logs.okta_systemlog
WHERE
(
eventType = 'user.account.privilege.grant' OR
eventType = 'group.privilege.grant' AND
cast(json_extract(debugcontext.debugdata, '$.privilegeGranted') as varchar) LIKE '%Admin%'
) AND
p_occurs_between('2022-01-14','2022-03-22')
ORDER BY
event_time desc
SnowflakeQuery: |
Query: |
SELECT
p_event_time as event_time,
actor:alternateId as actor_email,
Expand Down
10 changes: 1 addition & 9 deletions queries/okta_queries/okta_mfa_password_reset_audit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,7 @@ QueryName: "Okta Investigate MFA and Password resets"
Enabled: false
Description: >
Investigate Password and MFA resets for the last 7 days
AthenaQuery: |
SELECT p_event_time,actor.alternateId as actor_user,target[1].alternateId as target_user, eventType,client.ipAddress as ip_address
FROM panther_logs.okta_systemlog
WHERE eventType IN ('user.mfa.factor.reset_all', 'user.mfa.factor.deactivate', 'user.mfa.factor.suspend', 'user.account.reset_password', 'user.account.update_password')
and p_occurs_since('7 days')
-- If you wish to investigate an individual user , uncomment this line and add their email here
-- and actor:alternateId = '<EMAIL_GOES_HERE>'
ORDER by p_event_time DESC
SnowflakeQuery: |
Query: |
SELECT p_event_time,actor:alternateId as actor_user,target[0]:alternateId as target_user, eventType,client:ipAddress as ip_address
FROM panther_logs.public.okta_systemlog
WHERE eventType IN ('user.mfa.factor.reset_all', 'user.mfa.factor.deactivate', 'user.mfa.factor.suspend', 'user.account.reset_password', 'user.account.update_password','user.mfa.factor.update')
Expand Down
19 changes: 1 addition & 18 deletions queries/okta_queries/okta_session_id_audit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,7 @@ QueryName: "Okta Investigate Session ID Activity"
Enabled: false
Description: >
Search for activity related to a specific SessionID in Okta panther_logs.okta_systemlog
AthenaQuery: |
SELECT
p_event_time as event_time,
actor.alternateId as actor_email,
actor.displayName as actor_name,
authenticationContext.externalSessionId as sessionId,
displayMessage,
eventType,
client.ipAddress as src_ip,
client.geographicalContext.city as city,
client.geographicalContext.country as country,
client.userAgent.rawUserAgent as user_agent
FROM panther_logs.okta_systemlog
WHERE p_occurs_since('7 days')
-- Uncomment the line below and replace 'sessionId' with the sessionId you are investigating
-- and authenticationContext:externalSessionId = '<SESSIONID_GOES_HERE>'
ORDER BY event_time DESC
SnowflakeQuery: |
Query: |
SELECT
p_event_time as event_time,
actor:alternateId as actor_email,
Expand Down
22 changes: 1 addition & 21 deletions queries/okta_queries/okta_support_access.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,7 @@ QueryName: "Okta Support Access"
Enabled: false
Description: >
Show instances that Okta support was granted to your account
AthenaQuery: |
SELECT
p_event_time as event_time,
actor.alternateid as actor_email,
actor.displayName as actor_name,
displayMessage,
eventType,
client.ipAddress as src_ip,
client.geographicalContext.city as city,
client.geographicalContext.country as country,
client.useragent.rawUserAgent as user_agent
FROM panther_logs.okta_systemlog
WHERE
(
eventType = 'user.session.impersonation.grant' OR
eventType = 'user.session.impersonation.initiate'
) and
p_occurs_between('2022-01-14','2022-03-22')
ORDER BY
event_time desc
SnowflakeQuery: |
Query: |
SELECT
p_event_time as event_time,
actor:alternateId as actor_email,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Description: >
Monitor for configuration drift made by malicious actors as part of ongoing cyber threat activity reported May 31st, 2024
Tags:
- Configuration Required
SnowflakeQuery: |
Query: |
-- https://community.snowflake.com/s/article/Communication-ID-0108977-Additional-Information
-- adjust query/limit to narrow as necessary
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ AnalysisType: saved_query
QueryName: "Query.Snowflake.ThreatHunting.ConfigurationDrift"
Description: >
Monitor for configuration drift made by malicious actors as part of ongoing cyber threat activity reported May 31st, 2024
SnowflakeQuery: |
Query: |
-- https://community.snowflake.com/s/article/Communication-ID-0108977-Additional-Information
-- adjust query/limit to narrow as necessary
Expand Down
Loading

0 comments on commit 3f23ec9

Please sign in to comment.