Skip to content

Commit

Permalink
Add initial Correlation Rules (#1260)
Browse files Browse the repository at this point in the history
* GitHub advanced security change not followed by repo archived

* StopInstance FOLLOWED BY ModifyInstanceAttributes (correlation rule)

* GCP run.services.create Privilege Escalation - correlation rule

* GCP run.services.create Privilege Escalation - linter fix

* Add gcp_cloud_run_service_created.py changes

Signed-off-by: egibs <20933572+egibs@users.noreply.github.com>

* updated to follow CR style guide/best practices

* instance_ids as lists for comparison

* added unit tests to correlation rules

* updated packs

---------

Signed-off-by: egibs <20933572+egibs@users.noreply.github.com>
Co-authored-by: akozlovets098 <an.kozlovets@gmail.com>
Co-authored-by: Ariel Ropek <ariel.ropek@panther.com>
Co-authored-by: Ben Airey <benjaminjohnairey@gmail.com>
Co-authored-by: Ariel Ropek <79653153+arielkr256@users.noreply.github.com>
  • Loading branch information
5 people authored Jul 9, 2024
1 parent dd05da4 commit e68dabf
Show file tree
Hide file tree
Showing 15 changed files with 962 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
AnalysisType: correlation_rule
RuleID: "AWS.EC2.StopInstance.FOLLOWED.BY.ModifyInstanceAttributes"
DisplayName: "StopInstance FOLLOWED BY ModifyInstanceAttributes"
Enabled: true
Severity: High
Description: Identifies when StopInstance and ModifyInstanceAttributes CloudTrail events occur in a short period of time. Since EC2 startup scripts cannot be modified without first stopping the instance, StopInstances should be a signal.
Reference: https://unit42.paloaltonetworks.com/malicious-operations-of-exposed-iam-keys-cryptojacking/
Reports:
MITRE ATT&CK:
- TA0002:T1059
Detection:
- Sequence:
- ID: StopInstance
RuleID: AWS.EC2.StopInstances
- ID: StartupScriptChange
RuleID: AWS.EC2.Startup.Script.Change
Transitions:
- ID: StopInstance FOLLOWED BY StartupScriptChange
From: StopInstance
To: StartupScriptChange
Match:
- On: p_alert_context.instance_ids
LookbackWindowMinutes: 90
Schedule:
RateMinutes: 60
TimeoutMinutes: 1
Tests:
- Name: Instance Stopped, Followed By Script Change
ExpectedResult: true
RuleOutputs:
- ID: StopInstance
Matches:
p_alert_context.instance_ids:
'i-abcdef0123456789a':
- "2024-06-01T10:00:01Z"
- ID: StartupScriptChange
Matches:
p_alert_context.instance_ids:
'i-abcdef0123456789a':
- "2024-06-01T10:01:01Z"
- Name: Instance Stopped, Not Followed By Script Change
ExpectedResult: false
RuleOutputs:
- ID: StopInstance
Matches:
p_alert_context.instance_ids:
'i-abcdef0123456789a':
- "2024-06-01T10:00:01Z"
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
AnalysisType: correlation_rule
RuleID: "GCP.Cloud.Run.Service.Created.FOLLOWED.BY.Set.IAM.Policy"
DisplayName: "GCP Cloud Run Service Created FOLLOWED BY Set IAM Policy"
Enabled: true
Severity: High
Description: Detects run.services.create method for privilege escalation in GCP. The exploit creates a new Cloud Run
Service that, when invoked, returns the Service Account's access token by accessing the metadata API of the server
it is running on.
Reference: https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/
Runbook: Confirm this was authorized and necessary behavior
Reports:
MITRE ATT&CK:
- TA0004:T1548 # Abuse Elevation Control Mechanism
Detection:
- Sequence:
- ID: ServiceCreated
RuleID: GCP.Cloud.Run.Service.Created
- ID: SetIAMPolicy
RuleID: GCP.Cloud.Run.Set.IAM.Policy
Transitions:
- ID: ServiceCreated FOLLOWED BY SetIAMPolicy
From: ServiceCreated
To: SetIAMPolicy
Match:
- On: p_alert_context.caller_ip
LookbackWindowMinutes: 90
Schedule:
RateMinutes: 60
TimeoutMinutes: 1
Tests:
- Name: GCP Service Run, Followed By IAM Policy Change From Same IP
ExpectedResult: true
RuleOutputs:
- ID: ServiceCreated
Matches:
p_alert_context.caller_ip:
1.1.1.1:
- "2024-06-01T10:00:00Z"
- ID: SetIAMPolicy
Matches:
p_alert_context.caller_ip:
1.1.1.1:
- "2024-06-01T10:00:01Z"
- Name: GCP Service Run, Not Followed By IAM Policy Change
ExpectedResult: false
RuleOutputs:
- ID: ServiceCreated
Matches:
p_alert_context.caller_ip:
1.1.1.1:
- "2024-06-01T10:00:00Z"
- Name: IAM Policy Change, Not Preceeded By GCP Service Run
ExpectedResult: false
RuleOutputs:
- ID: SetIAMPolicy
Matches:
p_alert_context.caller_ip:
1.1.1.1:
- "2024-06-01T10:00:01Z"
- Name: GCP Service Run, Followed By IAM Policy Change From Different IP
ExpectedResult: false
RuleOutputs:
- ID: ServiceCreated
Matches:
p_alert_context.caller_ip:
1.1.1.1:
- "2024-06-01T10:00:00Z"
- ID: SetIAMPolicy
Matches:
p_alert_context.caller_ip:
2.2.2.2:
- "2024-06-01T10:00:01Z"
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
AnalysisType: correlation_rule
RuleID: "GitHub.Advanced.Security.Change.NOT.FOLLOWED.BY.Repo.Archived"
DisplayName: "GitHub Advanced Security Change NOT FOLLOWED BY Repo Archived"
Enabled: true
Severity: Critical
Description: Identifies when advances security change was made not to archive a repo. Eliminates false positives in the Advances Security Change Rule when the repo is archived.
Reference: https://docs.github.com/en/code-security/getting-started/auditing-security-alerts
Detection:
- Sequence:
- ID: GHASChange
RuleID: GitHub.Advanced.Security.Change
- ID: RepoArchived
RuleID: Github.Repo.Archived
Absence: true
Transitions:
- ID: GHASChange NOT FOLLOWED BY RepoArchived
From: GHASChange
To: RepoArchived
Match:
- On: p_alert_context.repo
LookbackWindowMinutes: 15
Schedule:
RateMinutes: 10
TimeoutMinutes: 1
Tests:
- Name: Security Change on Repo, Followed By Same Repo Archived
ExpectedResult: false
RuleOutputs:
- ID: GHASChange
Matches:
p_alert_context.repo:
my-org/example-repo:
- "2024-06-01T10:00:00Z"
- ID: RepoArchived
Matches:
p_alert_context.repo:
my-org/example-repo:
- "2024-06-01T10:00:01Z"
- Name: Security Change on Repo, Followed By Different Repo Archived
ExpectedResult: true
RuleOutputs:
- ID: GHASChange
Matches:
p_alert_context.repo:
my-org/example-repo:
- "2024-06-01T10:00:00Z"
- ID: RepoArchived
Matches:
p_alert_context.repo:
my-org/other-repo:
- "2024-06-01T10:00:01Z"
- Name: Security Change on Repo, Not Followed By Repo Archived
ExpectedResult: true
RuleOutputs:
- ID: GHASChange
Matches:
p_alert_context.repo:
my-org/example-repo:
- "2024-06-01T10:00:00Z"
2 changes: 2 additions & 0 deletions packs/aws.yml
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ PackDefinition:
- AWS.DynamoDB.Autoscaling
- AWS.EC2.Instance.EBSOptimization
- AWS.EC2.Startup.Script.Change
- AWS.EC2.StopInstances
- AWS.EC2.StopInstance.FOLLOWED.BY.ModifyInstanceAttributes
- AWS.ELBV2.LoadBalancer.HasSSLPolicy
- AWS.ELBv2.SSLPolicy
- AWS.GuardDuty.Enabled
Expand Down
3 changes: 3 additions & 0 deletions packs/gcp_audit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ PackDefinition:
- GCP.CloudBuild.Potential.Privilege.Escalation
- GCP.Cloudfunctions.Functions.Create
- GCP.Cloudfunctions.Functions.Update
- GCP.Cloud.Run.Service.Created
- GCP.Cloud.Run.Service.Created.FOLLOWED.BY.Set.IAM.Policy
- GCP.Cloud.Run.Set.IAM.Policy
- GCP.Destructive.Queries
- GCP.DNS.Zone.Modified.or.Deleted
- GCP.Firewall.Rule.Created
Expand Down
1 change: 1 addition & 0 deletions packs/github.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ DisplayName: "Panther GitHub Audit Pack"
PackDefinition:
IDs:
- GitHub.Advanced.Security.Change
- GitHub.Advanced.Security.Change.NOT.FOLLOWED.BY.Repo.Archived
- GitHub.Branch.PolicyOverride
- GitHub.Branch.ProtectionDisabled
- GitHub.Org.AuthChange
Expand Down
4 changes: 3 additions & 1 deletion rules/aws_cloudtrail_rules/aws_ec2_startup_script_change.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,6 @@ def dedup(event):


def alert_context(event):
return aws_rule_context(event)
context = aws_rule_context(event)
context["instance_ids"] = [deep_get(event, "requestParameters", "instanceId"), "no_instance_id"]
return context
29 changes: 29 additions & 0 deletions rules/aws_cloudtrail_rules/aws_ec2_stopinstances.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
from panther_base_helpers import aws_rule_context


def rule(event):
return all(
[
not event.get("errorCode"),
not event.get("errorMessage"),
event.get("eventName") == "StopInstances",
]
)


def title(event):
instances = [
instance["instanceId"]
for instance in event.deep_get("requestParameters", "instancesSet", "items", default=[])
]
account = event.get("recipientAccountId")
return f"EC2 instances {instances} stopped in account {account}."


def alert_context(event):
context = aws_rule_context(event)
context["instance_ids"] = [
instance["instanceId"]
for instance in event.deep_get("requestParameters", "instancesSet", "items", default=[])
]
return context
Loading

0 comments on commit e68dabf

Please sign in to comment.