diff --git a/rules/integrations/github/defense_evasion_secret_scanning_disabled.toml b/rules/integrations/github/defense_evasion_secret_scanning_disabled.toml new file mode 100644 index 00000000000..4d48d0a58cf --- /dev/null +++ b/rules/integrations/github/defense_evasion_secret_scanning_disabled.toml @@ -0,0 +1,55 @@ +[metadata] +creation_date = "2023/12/16" +integration = ["github"] +maturity = "production" +updated_date = "2025/12/16" + +[rule] +author = ["Elastic"] +description = """ +Detects when GitHub Secret Scanning is disabled for a repository. Adversaries may disable secret scanning to +evade detection of hardcoded secrets, such as API keys or credentials, that could be used for further +compromise or data exfiltration. +""" +from = "now-9m" +index = ["logs-github.audit-*"] +language = "eql" +license = "Elastic License v2" +name = "GitHub Secret Scanning Disabled" +references = [ + "https://www.wiz.io/blog/shai-hulud-2-0-ongoing-supply-chain-attack", + "https://trigger.dev/blog/shai-hulud-postmortem", + "https://posthog.com/blog/nov-24-shai-hulud-attack-post-mortem", +] +risk_score = 21 +rule_id = "21c3536f-b674-43db-9bfc-dcf4cf9dcc37" +severity = "low" +tags = [ + "Domain: Cloud", + "Use Case: Threat Detection", + "Tactic: Defense Evasion", + "Data Source: Github", +] +timestamp_override = "event.ingested" +type = "eql" +query = ''' +configuration where event.dataset == "github.audit" and event.type == "change" and event.action == "repository_secret_scanning.disable" +''' + +[[rule.threat]] +framework = "MITRE ATT&CK" + +[[rule.threat.technique]] +id = "T1562" +name = "Impair Defenses" +reference = "https://attack.mitre.org/techniques/T1562/" + +[[rule.threat.technique.subtechnique]] +id = "T1562.001" +name = "Disable or Modify Tools" +reference = "https://attack.mitre.org/techniques/T1562/001/" + +[rule.threat.tactic] +id = "TA0005" +name = "Defense Evasion" +reference = "https://attack.mitre.org/tactics/TA0005/" diff --git a/rules/integrations/github/exfiltration_github_private_repository_turned_public.toml b/rules/integrations/github/exfiltration_github_private_repository_turned_public.toml new file mode 100644 index 00000000000..4dd89f12af6 --- /dev/null +++ b/rules/integrations/github/exfiltration_github_private_repository_turned_public.toml @@ -0,0 +1,65 @@ +[metadata] +creation_date = "2023/12/16" +integration = ["github"] +maturity = "production" +updated_date = "2025/12/16" + +[rule] +author = ["Elastic"] +description = """ +Detects when a private GitHub repository is changed to public visibility. Adversaries may change repository +visibility to public in order to exfiltrate sensitive code or data, potentially indicating a compromise or +unauthorized access. +""" +from = "now-9m" +index = ["logs-github.audit-*"] +language = "eql" +license = "Elastic License v2" +name = "GitHub Private Repository Turned Public" +risk_score = 21 +rule_id = "8c707e4c-bd20-4ff4-bda5-4dc3b34ce298" +severity = "low" +tags = [ + "Domain: Cloud", + "Use Case: Threat Detection", + "Tactic: Exfiltration", + "Tactic: Impact", + "Data Source: Github", +] +timestamp_override = "event.ingested" +type = "eql" +query = ''' +configuration where event.dataset == "github.audit" and github.operation_type == "modify" and github.category == "repo" and +event.action == "repo.access" and github.previous_visibility == "private" and github.visibility == "public" +''' + +[[rule.threat]] +framework = "MITRE ATT&CK" + +[[rule.threat.technique]] +id = "T1020" +name = "Automated Exfiltration" +reference = "https://attack.mitre.org/techniques/T1020/" + +[[rule.threat.technique]] +id = "T1567" +name = "Exfiltration Over Web Service" +reference = "https://attack.mitre.org/techniques/T1567/" + +[[rule.threat.technique.subtechnique]] +id = "T1567.001" +name = "Exfiltration to Code Repository" +reference = "https://attack.mitre.org/techniques/T1567/001/" + +[rule.threat.tactic] +id = "TA0010" +name = "Exfiltration" +reference = "https://attack.mitre.org/tactics/TA0010/" + +[[rule.threat]] +framework = "MITRE ATT&CK" + +[rule.threat.tactic] +id = "TA0040" +name = "Impact" +reference = "https://attack.mitre.org/tactics/TA0040/" diff --git a/rules/integrations/github/exfiltration_high_number_of_cloning_by_user.toml b/rules/integrations/github/exfiltration_high_number_of_cloning_by_user.toml new file mode 100644 index 00000000000..fae8f9fda03 --- /dev/null +++ b/rules/integrations/github/exfiltration_high_number_of_cloning_by_user.toml @@ -0,0 +1,79 @@ +[metadata] +creation_date = "2025/12/16" +integration = ["github"] +maturity = "production" +updated_date = "2025/12/16" + +[rule] +author = ["Elastic"] +description = """ +Detects a high number of repository cloning actions by a single user within a short time frame. Adversaries may +clone multiple repositories to exfiltrate sensitive data. +""" +from = "now-9m" +interval = "8m" +language = "esql" +license = "Elastic License v2" +name = "GitHub Exfiltration via High Number of Repository Clones by User" +references = [ + "https://www.wiz.io/blog/shai-hulud-2-0-ongoing-supply-chain-attack", + "https://trigger.dev/blog/shai-hulud-postmortem", + "https://posthog.com/blog/nov-24-shai-hulud-attack-post-mortem", +] +risk_score = 47 +rule_id = "19f3674c-f4a1-43bb-a89c-e4c6212275e0" +severity = "medium" +tags = [ + "Domain: Cloud", + "Use Case: Threat Detection", + "Tactic: Exfiltration", + "Data Source: Github", +] +timestamp_override = "event.ingested" +type = "esql" +query = ''' +from logs-github.audit* metadata _id, _index, _version +| where + data_stream.dataset == "github.audit" and event.type == "change" and event.action == "git.clone" +| stats + Esql.event_count = COUNT(*), + Esql.github_org_values = values(github.org), + Esql.github_repo_values = values(github.repo), + Esql.github_repository_public_values = values(github.repository_public), + Esql.github_token_id_values = values(github.token_id), + Esql.github_user_agent_values = values(github.user_agent), + Esql.user_name_values = values(user.name), + Esql.agent_id_values = values(agent.id), + Esql.event_dataset_values = values(event.dataset), + Esql.data_stream_namespace_values = values(data_stream.namespace) + + by user.name + +| keep Esql.* + +| where + Esql.event_count >= 25 +''' + +[[rule.threat]] +framework = "MITRE ATT&CK" + +[[rule.threat.technique]] +id = "T1020" +name = "Automated Exfiltration" +reference = "https://attack.mitre.org/techniques/T1020/" + +[[rule.threat.technique]] +id = "T1567" +name = "Exfiltration Over Web Service" +reference = "https://attack.mitre.org/techniques/T1567/" + +[[rule.threat.technique.subtechnique]] +id = "T1567.001" +name = "Exfiltration to Code Repository" +reference = "https://attack.mitre.org/techniques/T1567/001/" + +[rule.threat.tactic] +id = "TA0010" +name = "Exfiltration" +reference = "https://attack.mitre.org/tactics/TA0010/" diff --git a/rules/integrations/github/impact_github_repository_activity_from_unusual_ip.toml b/rules/integrations/github/impact_github_repository_activity_from_unusual_ip.toml new file mode 100644 index 00000000000..3338176652d --- /dev/null +++ b/rules/integrations/github/impact_github_repository_activity_from_unusual_ip.toml @@ -0,0 +1,87 @@ +[metadata] +creation_date = "2025/12/16" +integration = ["github"] +maturity = "production" +updated_date = "2025/12/16" + +[rule] +author = ["Elastic"] +description = """ +Detects when there is activity on a private GitHub repository from an unusual IP address. Adversaries may +access private repositories from unfamiliar IPs to exfiltrate sensitive code or data, potentially indicating +a compromise or unauthorized access. +""" +from = "now-9m" +index = ["logs-github.audit-*"] +language = "kuery" +license = "Elastic License v2" +name = "Github Activity on a Private Repository from an Unusual IP" +references = [ + "https://www.wiz.io/blog/shai-hulud-2-0-ongoing-supply-chain-attack", + "https://trigger.dev/blog/shai-hulud-postmortem", + "https://posthog.com/blog/nov-24-shai-hulud-attack-post-mortem", +] +risk_score = 21 +rule_id = "daf2e0e0-0bab-4672-bfa1-62db0ee5ec22" +severity = "low" +tags = [ + "Domain: Cloud", + "Use Case: Threat Detection", + "Tactic: Impact", + "Tactic: Initial Access", + "Tactic: Persistence", + "Data Source: Github", + "Resources: Investigation Guide", +] +timestamp_override = "event.ingested" +type = "new_terms" +query = ''' +event.dataset:"github.audit" and event.action:("git.push" or "git.clone") and repository_public:"false" +''' + +[[rule.threat]] +framework = "MITRE ATT&CK" + +[rule.threat.tactic] +id = "TA0040" +name = "Impact" +reference = "https://attack.mitre.org/tactics/TA0040/" + +[[rule.threat]] +framework = "MITRE ATT&CK" + +[[rule.threat.technique]] +id = "T1195" +name = "Supply Chain Compromise" +reference = "https://attack.mitre.org/techniques/T1195/" + +[[rule.threat.technique.subtechnique]] +id = "T1195.002" +name = "Compromise Software Supply Chain" +reference = "https://attack.mitre.org/techniques/T1195/002/" + +[rule.threat.tactic] +id = "TA0001" +name = "Initial Access" +reference = "https://attack.mitre.org/tactics/TA0001/" + +[[rule.threat]] +framework = "MITRE ATT&CK" + +[[rule.threat.technique]] +id = "T1059" +name = "Command and Scripting Interpreter" +reference = "https://attack.mitre.org/techniques/T1059/" + +[rule.threat.tactic] +id = "TA0002" +name = "Execution" +reference = "https://attack.mitre.org/tactics/TA0002/" + +[rule.new_terms] +field = "new_terms_fields" +value = ["source.ip", "github.repo"] + +[[rule.new_terms.history_window_start]] +field = "history_window_start" +value = "now-7d" diff --git a/rules/integrations/github/impact_high_number_of_closed_pull_requests_by_user.toml b/rules/integrations/github/impact_high_number_of_closed_pull_requests_by_user.toml new file mode 100644 index 00000000000..f850d11096f --- /dev/null +++ b/rules/integrations/github/impact_high_number_of_closed_pull_requests_by_user.toml @@ -0,0 +1,95 @@ +[metadata] +creation_date = "2025/12/16" +integration = ["github"] +maturity = "production" +updated_date = "2025/12/16" + +[rule] +author = ["Elastic"] +description = """ +Detects a high number of closed pull requests by a single user within a short time frame. Adversaries may +close multiple pull requests to disrupt development workflows or hide malicious changes. +""" +from = "now-9m" +interval = "8m" +language = "esql" +license = "Elastic License v2" +name = "High Number of Closed Pull Requests by User" +references = [ + "https://www.wiz.io/blog/shai-hulud-2-0-ongoing-supply-chain-attack", + "https://trigger.dev/blog/shai-hulud-postmortem", + "https://posthog.com/blog/nov-24-shai-hulud-attack-post-mortem", +] +risk_score = 47 +rule_id = "098bd5cc-fd55-438f-b354-7d6cd9856a08" +severity = "medium" +tags = [ + "Domain: Cloud", + "Use Case: Threat Detection", + "Tactic: Impact", + "Tactic: Exfiltration", + "Data Source: Github", +] +timestamp_override = "event.ingested" +type = "esql" +query = ''' +from logs-github.audit* metadata _id, _index, _version +| where + data_stream.dataset == "github.audit" and + github.category == "pull_request" and + event.type == "change" and + event.action == "pull_request.close" +| stats + Esql.document_count = COUNT(*), + Esql.github_org_values = values(github.org), + Esql.github_repo_values = values(github.repo), + Esql.github_user_agent_values = values(github.user_agent), + Esql.github_pull_request_url_values = values(github.pull_request_url), + Esql.user_name_values = values(user.name), + Esql.agent_id_values = values(agent.id), + Esql.event_dataset_values = values(event.dataset), + Esql.data_stream_namespace_values = values(data_stream.namespace) + + by user.name + +| keep Esql.* + +| where + Esql.document_count >= 10 +''' + +[[rule.threat]] +framework = "MITRE ATT&CK" + +[[rule.threat.technique]] +id = "T1485" +name = "Data Destruction" +reference = "https://attack.mitre.org/techniques/T1485/" + +[rule.threat.tactic] +id = "TA0040" +name = "Impact" +reference = "https://attack.mitre.org/tactics/TA0040/" + +[[rule.threat]] +framework = "MITRE ATT&CK" + +[[rule.threat.technique]] +id = "T1020" +name = "Automated Exfiltration" +reference = "https://attack.mitre.org/techniques/T1020/" + +[[rule.threat.technique]] +id = "T1567" +name = "Exfiltration Over Web Service" +reference = "https://attack.mitre.org/techniques/T1567/" + +[[rule.threat.technique.subtechnique]] +id = "T1567.001" +name = "Exfiltration to Code Repository" +reference = "https://attack.mitre.org/techniques/T1567/001/" + +[rule.threat.tactic] +id = "TA0010" +name = "Exfiltration" +reference = "https://attack.mitre.org/tactics/TA0010/" diff --git a/rules/integrations/github/impact_high_number_of_failed_protected_branch_force_pushes_by_user.toml b/rules/integrations/github/impact_high_number_of_failed_protected_branch_force_pushes_by_user.toml new file mode 100644 index 00000000000..869fccb78bd --- /dev/null +++ b/rules/integrations/github/impact_high_number_of_failed_protected_branch_force_pushes_by_user.toml @@ -0,0 +1,96 @@ +[metadata] +creation_date = "2025/12/16" +integration = ["github"] +maturity = "production" +updated_date = "2025/12/16" + +[rule] +author = ["Elastic"] +description = """ +Detects a high number of failed force push attempts to protected branches by a single user within a short +time frame. Adversaries may attempt multiple force pushes to overwrite commit history on protected branches, +potentially leading to data loss or disruption of development workflows. +""" +from = "now-9m" +interval = "8m" +language = "esql" +license = "Elastic License v2" +name = "Several Failed Protected Branch Force Pushes by User" +references = [ + "https://www.wiz.io/blog/shai-hulud-2-0-ongoing-supply-chain-attack", + "https://trigger.dev/blog/shai-hulud-postmortem", + "https://posthog.com/blog/nov-24-shai-hulud-attack-post-mortem", +] +risk_score = 47 +rule_id = "8bd1c36a-2c4f-4801-a43d-ba696c13ffc2" +severity = "medium" +tags = [ + "Domain: Cloud", + "Use Case: Threat Detection", + "Tactic: Impact", + "Tactic: Exfiltration", + "Data Source: Github", +] +timestamp_override = "event.ingested" +type = "esql" +query = ''' +from logs-github.audit* metadata _id, _index, _version +| where + data_stream.dataset == "github.audit" and + github.category == "protected_branch" and + event.action == "protected_branch.rejected_ref_update" +| stats + Esql.document_count = COUNT(*), + Esql.github_org_values = values(github.org), + Esql.github_repo_values = values(github.repo), + Esql.github_branch_values = values(github.branch), + Esql.github_reasons_code_values = values(github.reasons.code), + Esql.github_reasons_message_value = values(github.reasons.message), + Esql.user_name_values = values(user.name), + Esql.agent_id_values = values(agent.id), + Esql.event_dataset_values = values(event.dataset), + Esql.data_stream_namespace_values = values(data_stream.namespace) + + by user.name + +| keep Esql.* + +| where + Esql.document_count >= 5 +''' + +[[rule.threat]] +framework = "MITRE ATT&CK" + +[[rule.threat.technique]] +id = "T1485" +name = "Data Destruction" +reference = "https://attack.mitre.org/techniques/T1485/" + +[rule.threat.tactic] +id = "TA0040" +name = "Impact" +reference = "https://attack.mitre.org/tactics/TA0040/" + +[[rule.threat]] +framework = "MITRE ATT&CK" + +[[rule.threat.technique]] +id = "T1020" +name = "Automated Exfiltration" +reference = "https://attack.mitre.org/techniques/T1020/" + +[[rule.threat.technique]] +id = "T1567" +name = "Exfiltration Over Web Service" +reference = "https://attack.mitre.org/techniques/T1567/" + +[[rule.threat.technique.subtechnique]] +id = "T1567.001" +name = "Exfiltration to Code Repository" +reference = "https://attack.mitre.org/techniques/T1567/001/" + +[rule.threat.tactic] +id = "TA0010" +name = "Exfiltration" +reference = "https://attack.mitre.org/tactics/TA0010/" diff --git a/rules/integrations/github/impact_high_number_of_protected_branch_force_pushes_by_user.toml b/rules/integrations/github/impact_high_number_of_protected_branch_force_pushes_by_user.toml new file mode 100644 index 00000000000..21f6098c277 --- /dev/null +++ b/rules/integrations/github/impact_high_number_of_protected_branch_force_pushes_by_user.toml @@ -0,0 +1,98 @@ +[metadata] +creation_date = "2025/12/16" +integration = ["github"] +maturity = "production" +updated_date = "2025/12/16" + +[rule] +author = ["Elastic"] +description = """ +Detects a high number of force push actions to protected branches by a single user within a short +time frame. Adversaries may perform force pushes to overwrite commit history on protected branches, +potentially leading to data loss or disruption of development workflows. +""" +from = "now-9m" +interval = "8m" +language = "esql" +license = "Elastic License v2" +name = "High Number of Protected Branch Force Pushes by User" +references = [ + "https://www.wiz.io/blog/shai-hulud-2-0-ongoing-supply-chain-attack", + "https://trigger.dev/blog/shai-hulud-postmortem", + "https://posthog.com/blog/nov-24-shai-hulud-attack-post-mortem", +] +risk_score = 47 +rule_id = "0428c618-27f5-4d94-99e6-b254585aba69" +severity = "medium" +tags = [ + "Domain: Cloud", + "Use Case: Threat Detection", + "Tactic: Impact", + "Tactic: Exfiltration", + "Data Source: Github", +] +timestamp_override = "event.ingested" +type = "esql" +query = ''' +from logs-github.audit* metadata _id, _index, _version +| where + data_stream.dataset == "github.audit" and + event.type == "change" and + event.action == "protected_branch.policy_override" and + github.category == "protected_branch" and + mv_contains(github.reasons.code, "force_push") +| stats + Esql.event_count = COUNT(*), + Esql.github_org_values = values(github.org), + Esql.github_repo_values = values(github.repo), + Esql.github_overridden_codes_values = values(github.overridden_codes), + Esql.github_reasons_code_values = values(github.reasons.code), + Esql.github_reasons_message_values = values(github.reasons.message), + Esql.user_name_values = values(user.name), + Esql.agent_id_values = values(agent.id), + Esql.event_dataset_values = values(event.dataset), + Esql.data_stream_namespace_values = values(data_stream.namespace) + + by user.name + +| keep Esql.* + +| where + Esql.event_count >= 10 +''' + +[[rule.threat]] +framework = "MITRE ATT&CK" + +[[rule.threat.technique]] +id = "T1485" +name = "Data Destruction" +reference = "https://attack.mitre.org/techniques/T1485/" + +[rule.threat.tactic] +id = "TA0040" +name = "Impact" +reference = "https://attack.mitre.org/tactics/TA0040/" + +[[rule.threat]] +framework = "MITRE ATT&CK" + +[[rule.threat.technique]] +id = "T1020" +name = "Automated Exfiltration" +reference = "https://attack.mitre.org/techniques/T1020/" + +[[rule.threat.technique]] +id = "T1567" +name = "Exfiltration Over Web Service" +reference = "https://attack.mitre.org/techniques/T1567/" + +[[rule.threat.technique.subtechnique]] +id = "T1567.001" +name = "Exfiltration to Code Repository" +reference = "https://attack.mitre.org/techniques/T1567/001/" + +[rule.threat.tactic] +id = "TA0010" +name = "Exfiltration" +reference = "https://attack.mitre.org/tactics/TA0010/" diff --git a/rules/integrations/github/persistence_new_pat_created.toml b/rules/integrations/github/persistence_new_pat_created.toml new file mode 100644 index 00000000000..c43b1681339 --- /dev/null +++ b/rules/integrations/github/persistence_new_pat_created.toml @@ -0,0 +1,69 @@ +[metadata] +creation_date = "2023/12/16" +integration = ["github"] +maturity = "production" +updated_date = "2025/12/16" + +[rule] +author = ["Elastic"] +description = """ +Detects when a new GitHub Personal Access Token (PAT) is created. Adversaries may create new PATs to maintain +persistent access to a compromised account or to escalate privileges within an organization. +""" +from = "now-9m" +index = ["logs-github.audit-*"] +language = "eql" +license = "Elastic License v2" +name = "New GitHub Personal Access Token (PAT) Added" +references = [ + "https://www.wiz.io/blog/shai-hulud-2-0-ongoing-supply-chain-attack", + "https://trigger.dev/blog/shai-hulud-postmortem", + "https://posthog.com/blog/nov-24-shai-hulud-attack-post-mortem", +] +risk_score = 21 +rule_id = "214d4e03-90b0-4813-9ab6-672b47158590" +severity = "low" +tags = [ + "Domain: Cloud", + "Use Case: Threat Detection", + "Tactic: Persistence", + "Tactic: Credential Access", + "Data Source: Github", +] +timestamp_override = "event.ingested" +type = "eql" +query = ''' +configuration where event.dataset == "github.audit" and github.operation_type == "create" and +github.category == "personal_access_token" and event.action == "personal_access_token.access_granted" +''' + +[[rule.threat]] +framework = "MITRE ATT&CK" + +[[rule.threat.technique]] +id = "T1136" +name = "Create Account" +reference = "https://attack.mitre.org/techniques/T1136/" + +[[rule.threat.technique.subtechnique]] +id = "T1136.003" +name = "Cloud Account" +reference = "https://attack.mitre.org/techniques/T1136/003/" + +[rule.threat.tactic] +id = "TA0003" +name = "Persistence" +reference = "https://attack.mitre.org/tactics/TA0003/" + +[[rule.threat]] +framework = "MITRE ATT&CK" + +[[rule.threat.technique]] +id = "T1528" +name = "Steal Application Access Token" +reference = "https://attack.mitre.org/techniques/T1528/" + +[rule.threat.tactic] +id = "TA0006" +name = "Credential Access" +reference = "https://attack.mitre.org/tactics/TA0006/"