diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..e35fb84 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "workbench.colorTheme": "YARA-L Theme" +} \ No newline at end of file diff --git a/README.md b/README.md index bba95a1..f7c411d 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,14 @@ This section details the available Terraform blueprints for deploying and managi
+## SecOps AI Migration Helper + +

This [blueprint](./blueprints/secops-ai-migration-helper/) is a tool that helps you migrate rules from a SIEM to Google SecOps and reduce the migration time significantly. It uses GenAI to help you migrate the rules in multiple steps.

+ +
+ + + # Modules This folder contains a suite of Terraform modules for Google SecOps automation. These modules are designed to be composed together and can be forked and modified where the use of third-party code and sources is not allowed. diff --git a/blueprints/secops-ai-migration-helper/.gemini/GEMINI.md b/blueprints/secops-ai-migration-helper/.gemini/GEMINI.md new file mode 100644 index 0000000..d098577 --- /dev/null +++ b/blueprints/secops-ai-migration-helper/.gemini/GEMINI.md @@ -0,0 +1,253 @@ +## Persona + +You are gemini-cli, an expert Google SecOps security engineer. Your primary goal is to understand the request, investigate the codebase and relevant resources, formulate a robust strategy, and then present a clear, step-by-step plan for approval. You are forbidden from making any modifications without approval. + +## Google SecOps Configuration +My Google SecOps environment details are: +- Customer ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx +- Region: eu +- Project ID: xxxxxxxx +**Rule:** Always use these exact parameters for EVERY SecOps tool request. + +## Planning steps + +1. **Acknowledge and Analyze:** Begin by thoroughly analyzing the user's request and the existing codebase to build context. +2. **Reasoning First:** Before presenting the plan, you must first output your analysis and reasoning. Explain what you've learned from your investigation (e.g., "I've inspected the following files...", "The current architecture uses...", "Based on the documentation for [library], the best approach is..."). This reasoning section must come **before** the final plan. +3. **Create the Plan:** Formulate a detailed, step-by-step implementation plan. Each step should be a clear, actionable instruction. +4. **Present for Approval:** The final step of every plan must be to present it to the user for review and approval. Do not proceed with the plan until you have received approval. + +## Output Format + +Your output must be a well-formatted markdown response containing two distinct sections in the following order: + +1. **Analysis:** A paragraph or bulleted list detailing your findings and the reasoning behind your proposed strategy. +2. **Plan:** A numbered list of the precise steps to be taken for implementation. The final step must always be presenting the plan for approval. + +## Repository Overview + +This repository contains a "Detection as Code" project for managing and deploying YARA-L security detection rules and reference lists to Google SecOps. The project uses a combination of Terraform for infrastructure as code and a Python CLI for interacting with the Google SecOps API. The main components are: + +* **Terraform Scripts:** Located in the root directory (`main.tf`, `variables.tf`, etc.), these scripts manage the deployment of YARA-L rules and reference lists to Google SecOps. +* **Detection Rules:** YARA-L rules are stored in the `rules/` directory, with each rule in its own subdirectory. +* **Reference Lists:** These are defined in `secops_reference_lists.yaml` and the corresponding files are in the `reference_lists/` directory. +* **Configuration:** The deployment of rules is controlled by `secops_rules.yaml`. + +## Development Conventions + +* **Rule Structure:** Each YARA-L rule should be placed in its own directory within the `rules/` directory. The directory should be named after the rule. The YARA-L file should also be named after the rule (e.g., `rules/MyRule/MyRule.yaral`). +* **Sample Logs:** Sample logs for testing rules should be placed in a `sample_logs/` subdirectory within the rule's directory. The sample log should be named after the log type (e.g., rules/MyRule/sample_logs/AZURE_AD_SIGNIN.log) +* **Configuration:** Rule deployment settings (e.g., `enabled`, `alerting`) are managed in `secops_rules.yaml`. Reference lists are defined in `secops_reference_lists.yaml`. +* **External lists**, like R0AssetsIPDyn, ComputerGroup etc in the source rule use reference YARAL data tables without creating it. Example $e.principal.hostname in %Reference_list.exchange_servers +* **Aggregate the excluded IPs or hosts** or similar to referenced YARA-L data table without creating it. Example not $e.principal.ip in %Excluded.ip +* **Output section** of YARA-L rule must contain the relevant UDM mappings + +**Rule:** Always use these exact parameters for EVERY SecOps tool request. + +## YARA-L 2.0 Syntax & Guidance + +### General structure: + +Rule sections must appear in this order: + +1) `meta` → 2) `events` → 3) `match` *(optional)* → 4) `outcome` *(optional)* → 5) `condition` → 6) `options` *(optional)* + + +## YARA-L functions: + + +Here is a consolidated list of commonly used YARA-L 2.0 functions with examples, based on the official Google Cloud documentation. 🧑‍💻 + +--- + +### String Functions +These functions are used to manipulate and analyze string data. + +| Function | Description | Example | +|---|---|---| +| **`strings.coalesce(val1, val2, ...)`** | Returns the first non-null string value from a list of arguments. | `strings.coalesce($e.principal.user.userid, $e.principal.user.email_addresses)` | +| **`strings.concat(str1, str2, ...)`** | Concatenates two or more strings together. | `strings.concat("File path: ", $e.target.file.full_path)` | +| **`strings.to_lower(str)`** | Converts a string to lowercase. | `strings.to_lower($e.principal.hostname)` | +| **`strings.to_upper(str)`** | Converts a string to uppercase. | `strings.to_upper($e.target.process.name)` | +| **`strings.contains(haystack, needle)`** | Returns `true` if the `haystack` string contains the `needle` string. | `strings.contains($e.principal.process.command_line, "powershell")` | +| **`strings.extract_domain(url)`** | Extracts the domain from a URL. | `strings.extract_domain($e.network.http.url)` | +| **`strings.split(str, delimiter)`** | Splits a string into an array of strings based on a delimiter. | `strings.split($e.principal.process.command_line, " ")` | +| **`strings.starts_with(str, prefix)`** | Returns `true` if the string starts with the specified prefix. | `strings.starts_with($e.target.file.full_path, "/tmp/")` | +| **`strings.substr(str, offset, length)`** | Returns a substring of a given string. | `strings.substr($e.principal.user.userid, 0, 5)` | +| **`strings.trim(str)`**| Removes leading and trailing whitespace from a string. | `strings.trim(" some text ")` | + +--- + +### Regular Expression Functions +These functions allow you to use regular expressions for more complex pattern matching. + +| Function | Description | Example | +|---|---|---| +| **`re.regex(text, pattern)`** | Returns `true` if the `text` matches the regular expression `pattern`. | `re.regex($e.principal.process.command_line, `\\bsvchost(\\.exe)?\\b`)` | +| **`re.capture(text, pattern)`** | Returns the first captured group from a regular expression match. | `re.capture($e.network.http.url, `user = ([^&]+)`)` | +| **`re.replace(text, pattern, replacement)`** | Replaces all occurrences of a pattern in a string with a replacement string. | `re.replace($e.target.file.full_path, `\\.log$`, ".txt")` | + +--- + +### Math Functions +These functions perform mathematical operations. + +| Function | Description | Example | +|---|---|---| +| **`math.abs(num)`** | Returns the absolute value of a number. | `math.abs(-10)` | +| **`math.ceil(num)`** | Rounds a number up to the nearest integer. | `math.ceil(3.14)` | +| **`math.floor(num)`** | Rounds a number down to the nearest integer. | `math.floor(3.14)` | +| **`math.round(num)`** | Rounds a number to the nearest integer. | `math.round(3.5)` | + +--- + +### Array Functions +These functions are used to work with arrays of data. + +| Function | Description | Example | +|---|---|---| +| **`arrays.contains(array, value)`** | Returns `true` if the array contains the specified value. | `arrays.contains($e.principal.ip, "192.168.1.100")` | +| **`arrays.length(array)`**| Returns the number of elements in an array. | `arrays.length($e.principal.user.email_addresses)` | +| **`arrays.index_to_str(array, index)`** | Returns the string element at a specific index in an array. | `arrays.index_to_str(strings.split($e.principal.process.command_line, " "), 0)`| + +--- + +### Timestamp Functions +These functions help you work with time-based data. 🕰️ + +| Function | Description | Example | +|---|---|---| +| **`timestamp.now()`** | Returns the current Unix timestamp in seconds. | `timestamp.now()` | +| **`timestamp.get_hour(unix_seconds)`** | Returns the hour (0-23) from a Unix timestamp. | `timestamp.get_hour($e.metadata.event_timestamp.seconds)` | +| **`timestamp.diff(t1, t2)`** | Returns the difference in seconds between two Unix timestamps. | `timestamp.diff($e2.metadata.event_timestamp.seconds, $e1.metadata.event_timestamp.seconds)` | + +**Rule Example** + +``` + rule mitre_attack_T1140_encoded_powershell_command_0003 { + + meta: + author = "Google Professional Services" + description = "Adversaries performing actions related to account management, account logon and directory service access, etc. may choose to clear the events in order to hide their activities." + title = "CSOC - Audit Log was Cleared on DC" + mitre_attack_tactic = "TA0005" + mitre_attack_technique = "T1070.001" + responsible = "SOC1" + creation_date = "08.06.2025" + last_rework_date = "" + old_ucid = "2006" + secops_ucid = "0003" + version = "0.5" + mitre_attack_url = "https://attack.mitre.org/versions/v17/techniques/T1070.001/" + mitre_attack_version = "" + type = "Alert" + data_source = "Windows" + severity = "High" + status = "prototype" + events: + $process.metadata.event_type = "PROCESS_LAUNCH" + $process.principal.hostname = $hostname + $process.target.hostname in %Domain_Controller.hostname // This is a reference to data table named Domain_Controller with key hostname + not $process.principal.ip in %Excluded.ip // Data table Excluded containing excluded assets with key ip + re.regex($process.target.process.file.full_path, `(system32|syswow64)\\WindowsPowerShell\\v1\.0\\powershell(|\_ise)\.exe`) nocase + re.regex($process.target.process.command_line, `(?i)(?:-enc|-ec|-en)\s*\S*`) + $encoded_value = re.capture($process.target.process.command_line, `(?i)(?:-enc|-ec|-en)\s*(\S*)`) + $decoded_value = re.replace(strings.base64_decode(re.capture($process.target.process.command_line, `(?i)(?:-enc|-ec|-en)\s*(\S*)`)),`\0`, "") + match: + $hostname over 5m + + outcome: + + $Count_logs = count_distinct($process.metadata.id) + $Source_user = array_distinct($process.principal.user.userid) + $Source_hostname = array_distinct($process.principal.hostname) + $Domain = array_distinct($process.target.administrative_domain) + $Event_id = array_distinct($process.metadata.product_event_type) + $Task = array_distinct($process.security_result.detection_fields["Task"]) + $Level = array_distinct($process.security_result.detection_fields["Level"]) + $Channel = array_distinct($process.about.labels["Channel"]) + $Target_process_command_line = array_distinct($process.target.process.command_line) + $Source_process_pid = array_distinct($process.principal.process.pid) + $Vendor_name = array_distinct($process.metadata.vendor_name) + $Product_name = array_distinct($process.metadata.product_name) + + condition: + $process +} +``` + +More examples read misc/yaral_examples/*.yaral + +**Output section of YARA-L** + +Output section of the YARA-L rule must contain relevant UDM mapping from this list + + $Source_user: principal.user.userid + $Target_user: target.user.userid + $Source_hostname: principal.hostname + $Target_hostname: target.hostname + $Logon_type: extensions.auth.auth_details + $Source_ip: principal.ip + $Target_ip: target.ip + $Workstation_Name: principal.hostname + $Event_id: metadata.product_event_type + $Channel: additional.fields["Channel"] + $CertThumbprint: security_result.detection_fields["CertThumbprint"] + $Task: additional.fields["Task"] + $Level: additional.fields["Level"] + $Source_port: src.port + $Service_name: target.application + $Status: security_result[0].description + $Domain: principal.administrative_domain + $Target_sid: target.user.windows_sid + $Source_sid: principal.user.windows_sid + $AccessMask: additional.fields["AccessMask"] + $Target_file_path: target.file.full_path + $Object_type: target.resource.resource_subtype + $Target_File_Names: target.file.names + $Share_name: target.resource.name + $Task_Name: target.resource.name + $Target_resource_name: target.resource.name + $Authentication_Type: security_result[0].about.resource.name + $Product_name: metadata.product_name + $Activity: security_result.detection_fields["Activity"] + $Key_Length: additional.fields["Key_Length"] + $Lm_Package_Name: target.labels["Lm_Package_Name"] + $Logon_Guid: additional.fields["Logon_Guid"] + $Source_proccess_path: principal.process.file.full_path + $Target_proccess_path: target.process.file.full_path + $Source_process_command_line: principal.process.command_line + $Target_process_command_line: target.process.command_line + $Source_process_pid: principal.process.pid + $Target_process_pid: target.process.pid + $Subject_Logon_Id: principal.labels["Subject_Logon_Id"] + $Target_logon_id: additional.fields["Target_logon_id"] + $Target_file_name: target.file.names + $Target_user_permissions: target.user.attribute.permissions[0].name + $Count_logs: metadata.id + $Result: additional.fields["Result"] + $Tenant_id: additional.fields["Tenant_id"] + $Security_result_action: security_result.action + $Security_result_description: security_result.description + $AlertLink: principal.resource.attribute.labels["AlertLink"] + $Compromised_Entity: principal.resource.attribute.labels["Compromised_Entity"] + $Rule_name: security_result.rule_name + $Threat_name: security_result.threat_name + $Severity: security_result.severity + $Source_system: security_result.detection_fields["Source_system"] + $Attack_tactic: security_result.attack_details.tactics.name + $Source_resource: principal.resource.name + $Source_resource_type: principal.resource.resource_subtype + $Summary: security_result.summary + $Severity_details: security_result.severity_details + $Target_user_display_name: target.user.user_display_name + $Target_user_email_addresses: target.user.email_addresses + $App_id: security_result.detection_fields["App_id"] + $User_agent: network.http.user_agent + $Source_location: principal.location.country_or_region + $Source_state: principal.ip_geo_artifact.location.state + $Network_Direction: network.direction + $Target_Url: target.url + $Method: network.http.method + $Protocol: network.application_protocol + $Response_Code: network.http.response_code + $Vendor_name: metadata.vendor_name \ No newline at end of file diff --git a/blueprints/secops-ai-migration-helper/.gemini/commands/clark/author_notes.toml b/blueprints/secops-ai-migration-helper/.gemini/commands/clark/author_notes.toml new file mode 100644 index 0000000..ea96ee2 --- /dev/null +++ b/blueprints/secops-ai-migration-helper/.gemini/commands/clark/author_notes.toml @@ -0,0 +1,11 @@ +description = "Author rule notes for a YARA-L rule" +prompt = """ +Your primary role is to update the RULE PARAMETERS, DEPENDENCIES, TUNING, TESTING, DOCS, and NOTES section of {{args}}.yaral. + + 1) Read {{args}}.yaral. If lines are shortened or you recieve a truncation error, immediately stop. + 2) Perform detailed analysis on the {{args}}.yaral and understand exactly how the rule is configured. + 3) Re-write the contents of RULE PARAMETERS, DEPENDENCIES, TUNING, TESTING, DOCS, and NOTES with your findings. You are forbiden from modifying SOURCE RULE or the YARA-L rule blocks in any way. +... +""" + +#EXAMPLE: /clark:author_notes azure_testrule_123 \ No newline at end of file diff --git a/blueprints/secops-ai-migration-helper/.gemini/commands/clark/format.toml b/blueprints/secops-ai-migration-helper/.gemini/commands/clark/format.toml new file mode 100644 index 0000000..9fe306c --- /dev/null +++ b/blueprints/secops-ai-migration-helper/.gemini/commands/clark/format.toml @@ -0,0 +1,17 @@ +description = "Format a source rule and place it into a specific template." + +prompt = """ +Your task is to take the rule content provided in {{args1}} and insert it into the template structure of {{args2}}. + +Follow these constraints strictly: +1) CONTENT INTEGRITY: You are forbidden from shortening, trimming, or modifying the logic/code within {{args1}}. Every character must be preserved. +2) FORMATTING: Improve the indentation and spacing of {{args1}} for maximum readability before insertion. +3) PLACEMENT: Locate the placeholder `` within {{args2}} and replace it with the formatted content from {{args1}}. +4) ERROR HANDLING: If the input in {{args1}} appears truncated or incomplete, stop immediately and alert the user. + +Output the final, merged result as a single code block. +""" + +#first: /clark:format @./migraiton_rules/demo_kql_9101.md rule_9904_audit_log_deleted_dc.yaral +#then: /copy + diff --git a/blueprints/secops-ai-migration-helper/.gemini/commands/clark/generate_log.toml b/blueprints/secops-ai-migration-helper/.gemini/commands/clark/generate_log.toml new file mode 100644 index 0000000..6d21147 --- /dev/null +++ b/blueprints/secops-ai-migration-helper/.gemini/commands/clark/generate_log.toml @@ -0,0 +1,28 @@ +description = "Generate sample logs for a YARA-L rule" +prompt = """ +### ROLE +You are a Chronicle Security Engineer specializing in YARA-L rule validation. Your task is to generate a RAW source log (not UDM) that will successfully trigger a specific detection rule. + +### CONTEXT +- Rule File: {{args}}.yaral +- Output Directory: {{args}}/sample_logs/ + +### INSTRUCTIONS + 1. **Rule Analysis:** Read {{args}}.yaral. If the file content appears truncated or incomplete, stop and alert the user immediately. Analyze the 'events' section and 'condition' section to understand exactly which field values and logic will trigger a match. + 2. **Identify Log Type:** - Extract the `log_type` from the rule metadata or event filters (e.g., $log.metadata.log_type = "WINEVTLOG"). + - If the log type is explicitly defined, use it. + - If the log type is unknown or ambiguous, PAUSE and propose the most likely type to the user (e.g., "This looks like WINEVTLOG, should I proceed?"). + 3. **Format Research:** - Search the local repository for existing logs matching the pattern **.log (e.g., IIS.log) to use as a structural template. + - If no local samples exist, search the internet for the official RAW schema/format for that specific log source. + 4. **Log Generation:** - Generate a **RAW** log entry. + - **CRITICAL:** Do NOT generate UDM JSON. The output must be in the original source format (e.g., Syslog, Windows XML/Event, JSON, CSV) as it would appear before ingestion into Chronicle. + - Ensure the log contains the specific values required to satisfy the YARA-L rule conditions. + 5. **Output:** - Save the generated log to: `{{args}}/sample_logs/.log`. + - Example: If the type is "MICROSOFT_DEFENDER_CLOUD_ALERTS", save as `MICROSOFT_DEFENDER_CLOUD_ALERTS.log`. + +### CONSTRAINTS +- Strict RAW format only. No UDM wrappers. +- Validation: Before finishing, verify that the generated log adheres to the known schema of the source log type. +""" + +#EXAMPLE: /clark:generate_log azure_testrule_123 \ No newline at end of file diff --git a/blueprints/secops-ai-migration-helper/.gemini/commands/clark/init.toml b/blueprints/secops-ai-migration-helper/.gemini/commands/clark/init.toml new file mode 100644 index 0000000..2f04f51 --- /dev/null +++ b/blueprints/secops-ai-migration-helper/.gemini/commands/clark/init.toml @@ -0,0 +1,17 @@ +description = "Initialiaze a Rule Directory" +prompt = """ +Your primary role is to create a new directory {{args}} in the existing repository and initialize the .yaral file with the rule_template. Use absolute paths when creating folders & files. Be sure to present your plan and await approval. + +Add the following structure to the working repository: + +├── rules +│ ├── {{args}} +│ │ └── {{args}}.yaral + |── sample_logs + + +Create {{args}}.yaral with contents of .gemini/commands/clark/templates/rule_template.md. Ensure to replace the rule name with {{args}} +... +""" + +#EXAMPLE: /clark:init azure_testrule_123 \ No newline at end of file diff --git a/blueprints/secops-ai-migration-helper/.gemini/commands/clark/migrate_rule.toml b/blueprints/secops-ai-migration-helper/.gemini/commands/clark/migrate_rule.toml new file mode 100644 index 0000000..d37d5f9 --- /dev/null +++ b/blueprints/secops-ai-migration-helper/.gemini/commands/clark/migrate_rule.toml @@ -0,0 +1,34 @@ +description = "Migrate a source rule to YARA-L" +prompt = """ +Your primary role is to migrate the Source Rule section in {{args}}.yaral into YARA-L 2.0. Be sure to present your plan and await approval. + + 1) Clear your file cache and read {{args}}.yaral. If lines are shortened or you receive a truncation error, immediately stop. + 2) Perform a detailed analysis of the rule under the Source Rule section. + 3) Find most similar YARA-L rules excludig {{args}}.yaral in your repo that contain similar description keywords and use them as context for logic creation. Example input rule descriptions "Rare or Never Seen EventID Logged" similar rules descriptions "first time seen window event" or "rare or never seen EventID" + 4) Plan for it's exact like-for-like migration to YARA-L 2.0. Ensure to check your directives for YARA-L 2.0 syntax and examples. You are forbidden from simplifying rule logic or taking shortcuts. + 5) Place the migrated YARA-L 2.0 rule content the first and the last line at in to the existing file {{args}}.yaral. + +Ensure the meta block of the migrated YARA-L 2.0 rule follows the following schema: + + author = must be "Google Professional Services" + description = must be exact like-for-like description as the source rule. + title = must be exact like-for-like title as the source rule. + mitre_attack_tactic = must be "TO-BE-FIXED" + mitre_attack_technique = must be "TO-BE-FIXED" + mitre_attack_url = must be "https://attack.mitre.org/techniques" + mitre_attack_version = must be "TO-BE-FIXED" + old_ucid = must be "TO-BE-FIXED" + secops_ucid = must be "TO-BE-FIXED" + type = must be "Alert" + data_source = must be "TO-BE-FIXED" + responsible = must be "SOC1" + creation_date = Must contain exact like-for-like creation as the source rule. A date in right format, Example "16.06.2025" can be empty , e.g. "" + last_rework_date = Today's date. A date in right format, Example "16.06.2025", can be empty , e.g. "" + severity = must be exact like-for-like severity as the source rule. A string can be on of the "Medium", "High" or "Low" if not set use "TO-BE-FIXED" + status = must be "prototype" + version = must be "0.5" + +Ensure the output section is as the instruction. Consider carefully the YARA-L syntax and functions in your context and instructions +""" + + diff --git a/blueprints/secops-ai-migration-helper/.gemini/commands/clark/plan.toml b/blueprints/secops-ai-migration-helper/.gemini/commands/clark/plan.toml new file mode 100644 index 0000000..a910b68 --- /dev/null +++ b/blueprints/secops-ai-migration-helper/.gemini/commands/clark/plan.toml @@ -0,0 +1,21 @@ +description="Investigates and creates a strategic plan to accomplish a task." +prompt = """ +Your primary role is that of a strategist, not an implementer. +Your task is to stop, think deeply, and devise a comprehensive strategic plan to accomplish the following goal: {{args}} + +You MUST NOT write, modify, or execute any code. Your sole function is to investigate the current state and formulate a plan. + +Use your available "read" and "search" tools to research and analyze the codebase. Gather all necessary context before presenting your strategy. + +Present your strategic plan in markdown. It should be the direct result of your investigation and thinking process. Structure your response with the following sections: + +1. **Understanding the Goal:** Re-state the objective to confirm your understanding. +2. **Investigation & Analysis:** Describe the investigative steps you would take. What files would you need to read? What would you search for? What critical questions need to be answered before any work begins? +3. **Proposed Strategic Approach:** Outline the high-level strategy. Break the approach down into logical phases and describe the work that should happen in each. +4. **Verification Strategy:** Explain how the success of this plan would be measured. What should be tested to ensure the goal is met without introducing regressions? +5. **Anticipated Challenges & Considerations:** Based on your analysis, what potential risks, dependencies, or trade-offs do you foresee? + +Your final output should be ONLY this strategic plan. +""" + +#EXAMPLE: /clark:plan How should I {args} \ No newline at end of file diff --git a/blueprints/secops-ai-migration-helper/.gemini/commands/clark/summarize.toml b/blueprints/secops-ai-migration-helper/.gemini/commands/clark/summarize.toml new file mode 100644 index 0000000..0d97b5b --- /dev/null +++ b/blueprints/secops-ai-migration-helper/.gemini/commands/clark/summarize.toml @@ -0,0 +1,26 @@ +description = "Summarize source rule" +prompt = """ +Your primary role is to summarize the objective {{args}} . + + 1) Find the file provided in {{args}} + 2) Read {{args}} using the `cat` shell command. Do not deviate from this. If lines are shortened or you recieve a truncation error, immediately stop. + 3) Read carefully and analyze the content of this detection rule and provide the following informationin the format: + - UseCase ID: + - Title: + - Description: + - Rule: + - Rule logic verbal description: + - Rule logic: + - Matching frequency: + - Grouping: + - Output actions: + +Consider that the information can be in multiple part of the document that you may need to combine + +Output the formatted string as a code block so that it can be easily copied and pasted. +... +""" + +#first: /clark:summarize @.gemini/prompts/arc_20013.md +#then: /copy + diff --git a/blueprints/secops-ai-migration-helper/.gemini/commands/clark/templates/rule_template.md b/blueprints/secops-ai-migration-helper/.gemini/commands/clark/templates/rule_template.md new file mode 100644 index 0000000..85badea --- /dev/null +++ b/blueprints/secops-ai-migration-helper/.gemini/commands/clark/templates/rule_template.md @@ -0,0 +1,32 @@ +rule {{args}} { +/* + +SOURCE: Intergalactic SOC +RULE PARAMETERS: + - Target Log Type: + - Target Activity: + +DEPENDENCIES: + - Log Source: + +TUNING: + - Potential False Positives: + +DOCS: + - External Reference: + +NOTES: + - Rationale for Severity: + - Imporments: + +SOURCE RULE: + +*/ + +} \ No newline at end of file diff --git a/blueprints/secops-ai-migration-helper/.gemini/commands/clark/validate.toml b/blueprints/secops-ai-migration-helper/.gemini/commands/clark/validate.toml new file mode 100644 index 0000000..b61647b --- /dev/null +++ b/blueprints/secops-ai-migration-helper/.gemini/commands/clark/validate.toml @@ -0,0 +1,17 @@ +description = "Validate Syntax for a YARA-L rule" +prompt = """ +Your task is to use {{args}}.yaral to validate the YARA-L 2.0 Google SecOps syntax using MCP secops server tool mcp_secops_validate_rule: + +Follow these constraints strictly: + + 1. Read the {{args}}.yaral rule file's content + 2. Use the available mcp_secops_validate_rule tool in MCP secops server to validate the YARA-L 2.0 Google SecOps syntax. Do not consider *.tf files or config files. + 3. If validation fails: + - Analyze the error, extract the line number, and consult a GoogleSearch on YARA-L 2.0 SecOps documentation + - Correct the rule. Be sure confirm that the line you are changing is the same line that you have extracted. + 4. Repeat the validation and correction process until the rule is valid. To break impasse, simplify the problem and test the core issue in isolation + +... +""" + +#EXAMPLE: /clark:validate Azure_MultipleMFADeniedActivitiesFromSameSource_103 \ No newline at end of file diff --git a/blueprints/secops-ai-migration-helper/.gemini/commands/curator/extract.toml b/blueprints/secops-ai-migration-helper/.gemini/commands/curator/extract.toml new file mode 100644 index 0000000..7a962a9 --- /dev/null +++ b/blueprints/secops-ai-migration-helper/.gemini/commands/curator/extract.toml @@ -0,0 +1,40 @@ + description = "Extract and format unstructured rules in proper JSON. Argument is file containing customer rules in loose text format" +prompt = """ + +You goal is to extract values from file, provide the values in JSON format + +Instructions: + +1. Load the file {{args}} and process record by record the rule and consider rule syntax can different. +2. Understand the file and provide for each rule the title, ucid, description and logic. If values not present in rule, analyst the rule and suggest. Put N/A if not sure. Do. no use RegEx scripts +3. Write values to JSON file in ./recommender_curated_community/work_dir/, example ./recommender_curated_community/work_dir/input_rules_20250901.json. It is mission critical to provide the valid JSON and escape string properly + +[ + { + "ucid": "", + "title": "", + "description": "<Description>", + "rule": "< Original input rule logic without amy modification" + }, + .. +] + +4. Validate JSON +5. Print the file where you have saved the results + +Example: + +INPUT: + +"//ucid: 9901\n// Title of Detection: Rare Scripting Software Detected \n// Authorship & Contact: https://allthingscomputers.medium.com https://twitter.com/allthingshandle https://allthingscomputersblog.wordpress.com/ \n// Description of the Detection: Because powershell and cmd prompt are so closely watched and have so many alarms put up to catch misuse, hackers are starting to avoid using them. This detects scripting tools that are utilised and found in the Event log that arent approved software by your environment.\n// References (if available): \n// The Logic of the Detection or Query Begins Below This Line\n// Source https://github.com/AllThingsComputers/Sentinel-Rules/blob/main/Event%20Logs/Rare%20Scripting%20Software%20Detected.txt\nEvent\n| where (RenderedDescription matches regex@(?i)(command|shell|execute|script|console|terminal) or RenderedDescription matches regex @(?i)(Bash|Ksh|Fish|Korn|ZOC|Cmder|ConEmu|Mintty)) and not(RenderedDescription matches regex (Use a regex of your expected tools in your environment to remove false positives))" + +OUTPUT: + +[ + { + "ucid": "9901", + "title": "Rare Scripting Software Detected", + "description": "Because powershell and cmd prompt are so closely watched and have so many alarms put up to catch misuse, hackers are starting to avoid using them. This detects scripting tools that are utilised and found in the Event log that arent approved software by your environment.", + "rule": "//ucid: 9901\n// Title of Detection: Rare Scripting Software Detected \n// Authorship & Contact: https://allthingscomputers.medium.com https://twitter.com/allthingshandle https://allthingscomputersblog.wordpress.com/ \n// Description of the Detection: Because powershell and cmd prompt are so closely watched and have so many alarms put up to catch misuse, hackers are starting to avoid using them. This detects scripting tools that are utilised and found in the Event log that arent approved software by your environment.\n// References (if available): \n// The Logic of the Detection or Query Begins Below This Line\n// Source https://github.com/AllThingsComputers/Sentinel-Rules/blob/main/Event%20Logs/Rare%20Scripting%20Software%20Detected.txt\nEvent\n| where (RenderedDescription matches regex@(?i)(command|shell|execute|script|console|terminal) or RenderedDescription matches regex @(?i)(Bash|Ksh|Fish|Korn|ZOC|Cmder|ConEmu|Mintty)) and not(RenderedDescription matches regex (Use a regex of your expected tools in your environment to remove false positives))" + } ] +""" \ No newline at end of file diff --git a/blueprints/secops-ai-migration-helper/.gemini/commands/curator/recommend.toml b/blueprints/secops-ai-migration-helper/.gemini/commands/curator/recommend.toml new file mode 100644 index 0000000..f9b15d1 --- /dev/null +++ b/blueprints/secops-ai-migration-helper/.gemini/commands/curator/recommend.toml @@ -0,0 +1,10 @@ +description = "Generates recommendations for SecOps curated and community rules based on an input JSON file of customer rules." +prompt = """ +Your objective is to execute interactive script using the provided input rules file `{{args}}` + +Please follow these instructions sequentially: + +1) If the `{{args}}` variable is empty, stop and ask the user to provide the path to the JSON file containing their customer rules. +2) Execute the script using `run_recommender.sh {{args}}`. Stream the script output directly to the user so they can monitor the process and interactive input. Inform the user to use TAB to focus on the script +3) When the script finishes, inform the user that the operation is complete and provide the paths for the final CSV and JSON recommendations in the output of the script. +""" \ No newline at end of file diff --git a/blueprints/secops-ai-migration-helper/.gemini/settings.json.template b/blueprints/secops-ai-migration-helper/.gemini/settings.json.template new file mode 100644 index 0000000..6e35eeb --- /dev/null +++ b/blueprints/secops-ai-migration-helper/.gemini/settings.json.template @@ -0,0 +1,78 @@ +{ + "security": { + "auth": { + "selectedType": "vertex-ai" + } + }, + "ui": { + "theme": "Atom One" + }, + "mcpServers": { + "GoogleSecOps": { + "httpUrl": "https://${SECOPS_REGION}-chronicle.googleapis.com/mcp", + "authProviderType": "google_credentials", + "oauth": { + "scopes": [ + "https://www.googleapis.com/auth/cloud-platform" + ] + }, + "timeout": 30000, + "headers": { + "x-goog-user-project": "${SECOPS_PROJECT}" + }, + "includeTools": [ + "create_case_comment", + "execute_manual_action", + "get_alert_latest_investigation", + "get_case", + "get_case_alert", + "get_connector_event", + "get_investigation_by_id", + "get_involved_entity", + "get_ioc_match", + "get_reference_list", + "get_rule", + "get_security_alert", + "list_case_alerts", + "list_case_comments", + "list_cases", + "list_connector_events", + "list_data_table_rows", + "list_data_tables", + "list_feeds", + "list_integration_actions", + "list_integration_instances", + "list_integrations", + "list_involved_entities", + "list_log_types", + "list_parsers", + "list_playbook_instances", + "list_playbooks", + "list_rule_detections", + "list_rule_errors", + "list_rules", + "list_security_alerts", + "search_entity", + "summarize_entity", + "translate_udm_query", + "trigger_investigation", + "udm_search", + "update_case", + "update_case_alert" + ], + "trust": true + } + }, + "general": { + "previewFeatures": true, + "vimMode": true, + "sessionRetention": { + "enabled": true, + "maxAge": "30d", + "warningAcknowledged": true + } + }, + "experimental": { + "skills": true + } +} \ No newline at end of file diff --git a/blueprints/secops-ai-migration-helper/.gitignore b/blueprints/secops-ai-migration-helper/.gitignore new file mode 100644 index 0000000..0ce56b1 --- /dev/null +++ b/blueprints/secops-ai-migration-helper/.gitignore @@ -0,0 +1,11 @@ +/.idea/ +/venv/ +**/.terraform/* +.vscode/** +.gemini/settings.json +**/work_dir/* +!**/work_dir/.gitkeep +**/__pycache__ +**/.venv/** +**/script_output.log +**/script_pid.txt \ No newline at end of file diff --git a/blueprints/secops-ai-migration-helper/README.md b/blueprints/secops-ai-migration-helper/README.md new file mode 100644 index 0000000..883531d --- /dev/null +++ b/blueprints/secops-ai-migration-helper/README.md @@ -0,0 +1,135 @@ +# SecOps AI Migration Helper + +**PROTOTYPE** + +Migration helper is a tool that helps you migrate rules from a SIEM to Google SecOps and reduce the migration time significantly. It uses GenAI to help you migrate the rules in multiple steps. + +- The AI helper operates in clearly defined small steps, each with specific inputs and outputs. +- A SecOps Consultant (Human in the loop) validates the output after every step. For example: formatting an original rule, then manual visual validation, then adding comments, etc. +- A general all-in-one approach (migrating everything without considering equivalence to curated rules) is counterproductive. +- The more rules are migrated, the knowledge base of the GenAI tool increases and migration becomes more accurate. +- The tool is flexible by understanding different formats of rules from a SIEM. It is not limited to the original language of the rule. + +Migration Steps overview ![Migration Steps Overview](./misc/yaral/images/steps_overview.png) + +--- + +## Features + +* **AI Migration helper** leveraging GenAI, SecOps MCP and Gemini CLI to automate the migration. +* **Recommender Tool**: A GenAI-powered script that maps existing rules (KQL, SPL, ArcSight, etc.) to equivalent Google SecOps Curated or Community rules. +--- + +## Installation + +### Gemini CLI + +Follow [Gemini CLI](https://github.com/google-gemini/gemini-cli) + +### Setup SecOps MCP integration and Gemini CLI + +#### MCP SecOps setup + +Run the following commands: + +```bash +gcloud config set project your-gcp-project +gcloud beta services mcp enable chronicle.googleapis.com --project=your-gcp-project +``` + +Configure GCP IAM for **SecOps MCP Access** + +In order to access a Google Cloud Hosted MCP Server the principal (a user, service account, or group) will require the MCP Tool User IAM Role: +- MCP tool user + +To use Google SecOps, the principal requires appropriate IAM permissions. A standard admin setup includes: + +- Chronicle API Admin +- Chronicle SOAR Admin +- Service Usage Consumer +- Vertex AI User + +Before using gemini-cli please issue the following command to set the environment variable required for Vertex AI: + +```bash +export GOOGLE_CLOUD_PROJECT="<your_gcp_project_id>" +export GOOGLE_CLOUD_LOCATION="global" +``` + +Before accessing the Gemini CLI, make sure to configure the ~/.gemini/settings.json file leveraging the built in generate-settings.sh bash script. Execute such a script with the following parameters: + +```bash +./generate_settings.sh <secops_project_id> <secops_region> +``` + +The script will generate a settings.json file in the ~/.gemini/ directory. + +Before using gemini-cli please update the GEMINI.md file in the .gemini folder replacing the following placeholder with your tenant configuration: + +``` +# Google SecOps Configuration +My Google SecOps environment details are: +- Customer ID: <SECOPS_CUSTOMER_ID> +- Region: <SECOPS_REGION> +- Project ID: <GCP_PROJECT_ID> +**Rule:** Always use these exact parameters for EVERY SecOps tool request. +``` + +Then when you run the gemini command for the first time you might be asked to log in. When asked "How would you like to authenticate for this project?" choose "Vertex AI". + +Please then run the following command to verify the MCP server integration: + +```bash +/mcp list +``` + +It should return the Google SecOps MCP server in the list of available MCP servers. To try configuration of the SecOps MCP server, please use the following command: + +```bash +"Please use the SecOps MCP to list my rules." +``` + +If successful, you should see a list of rules returned. If that is the case, you can proceed to the next step. + + +More information on how to configure gemini-cli with Google SecOps hosted MCP server integration available in the [Using Google SecOps with Gemini CLI and Hosted MCP](https://medium.com/@thatsiemguy/using-google-secops-with-gemini-cli-and-hosted-mcp-6400ec8aa99e) + +--- +## Usage + +Start the Gemini CLI and execute a command with `/<command>` arguments. Following are described the commands and their arguments: + +### Tune the Gemini CLI commands to your use case +Every migration is different and it is very important to adapt the Gemini CLI commands in `.gemini` to your particular use case. Take one sample rule, execute it multiple times and adjust the commands accordingly until you get the desired output. After this, start the mass migration of the rules. + +### Evaluate curated and community rules to replace legacy rules: + +Note: You can execute the recommendation also as a standalone Python script and set up parameters via environment variables. See [recommender_curated_community/README.md](./recommender_curated_community/README.md) + +- `extract <file_path>`: Using Agent Space to explore and understand the logic of the rules and map them to curated rules. +- `recommend <file_path>`: Recommend curated rules and coverage. Decide which rules need to be migrated or decommissioned. Evaluate curated and community rules to replace legacy rules. + +### Migrate a rule to a custom rule: + +- `init <new_rule_name>`: Create new directory structure & `.yaral` rule from template +- `format <migrating_rule_path> <new_rule_name>`: Take a migrating rule and format its contents for readability +- `migrate_rule <new_rule_path>`: Generate equivalent YARA-L rule from any source +- `generate_log <new_rule_path>`: Generate a sample log that would trigger on a given YARA-L rule +- `author_notes <new_rule_path>`: Author rule notes, including dependencies, tuning, testing, docs and rule parameters +- `validate <new_rule_path>`: Validate a rule’s YARA-L syntax against the SecOps MCP server, self-correcting as necessary + +### Directory Structure + +Main files and directories: +- `recommender_curated_community/`: The Python recommender tool for discovering relevant curated or community rules, powered by Vertex AI models. +- `migration_rules/`: Examples and demonstration files of rules from distinct SIEM platforms (e.g., KQL, ArcSight, SPL). Place here the rule you want to migrate. +- `rules/`: Repository for the resulting YARA-L detection rules, with dedicated subdirectories for each rule including optional `sample_logs`. It contatin some sample. + +### Contributing +Contributions are welcome! Please feel free to submit a pull request with any improvements or bug fixes. + +1. Fork the repository. +2. Create a new branch (`git checkout -b feature/your-feature`). +3. Commit your changes (`git commit -am 'Add some feature'`). +4. Push to the branch (`git push origin feature/your-feature`). +5. Create a new Pull Request. diff --git a/blueprints/secops-ai-migration-helper/generate_settings.sh b/blueprints/secops-ai-migration-helper/generate_settings.sh new file mode 100755 index 0000000..c8979e9 --- /dev/null +++ b/blueprints/secops-ai-migration-helper/generate_settings.sh @@ -0,0 +1,42 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +#!/bin/bash + +# Check if exactly 2 arguments are provided +if [ "$#" -ne 2 ]; then + echo "Usage: $0 <secops_project_id> <secops_region>" + exit 1 +fi + +SECOPS_PROJECT="$1" +SECOPS_REGION="$2" + +# Get directory of the script +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" + +TEMPLATE_FILE="$DIR/.gemini/settings.json.template" +OUTPUT_FILE="$DIR/.gemini/settings.json" + +if [ ! -f "$TEMPLATE_FILE" ]; then + echo "Error: Template file $TEMPLATE_FILE not found." + exit 1 +fi + +# Replace variables in the template and output to settings.json +sed -e "s/\${SECOPS_PROJECT}/$SECOPS_PROJECT/g" \ + -e "s/\${SECOPS_REGION}/$SECOPS_REGION/g" \ + "$TEMPLATE_FILE" > "$OUTPUT_FILE" + +echo "Successfully generated $OUTPUT_FILE" diff --git a/blueprints/secops-ai-migration-helper/migration_rules/demo_arcsight_7004.md b/blueprints/secops-ai-migration-helper/migration_rules/demo_arcsight_7004.md new file mode 100644 index 0000000..7984ab9 --- /dev/null +++ b/blueprints/secops-ai-migration-helper/migration_rules/demo_arcsight_7004.md @@ -0,0 +1,36 @@ + +# Rule: Correlating Tor Sources in Events + +This is a rule that detects incoming network traffic where the source IP address matches a known Tor exit node stored in an Active List. + +## RuleId + +7004 + + +## Matching + + 1 event + +## Conditions + +(InZone( +event1.,/All Filters/Default Filters/Network/Perimeter/Inbound Traffic)) +And +(InActiveList( +event1.sourceAddress,/All Active Lists/Tor/Tor Exit Nodes)) + +## Grouped By: + +event1.sourceAddress, event1.destinationAddress, event1.deviceProduct, event1.deviceVendor, event1.destinationPort, event1.applicationProtocol, event1.deviceEventClassId + +## Execute actions +### On First Event +· SendToConsole( ) +· Set Severity High +· SetEventField( name, Anonymizer Traffic - Tor Exit Node Detected) +· SetEventField( categoryBehavior, /Communicate/Anonymized) + +## Source + +[https://medium.com/analytics-vidhya/correlating-tor-sources-in-arcsight-siem-events-using-python-92750617227a](https://medium.com/analytics-vidhya/correlating-tor-sources-in-arcsight-siem-events-using-python-92750617227a) diff --git a/blueprints/secops-ai-migration-helper/migration_rules/demo_arcsight_7005.md b/blueprints/secops-ai-migration-helper/migration_rules/demo_arcsight_7005.md new file mode 100644 index 0000000..61f4647 --- /dev/null +++ b/blueprints/secops-ai-migration-helper/migration_rules/demo_arcsight_7005.md @@ -0,0 +1,36 @@ +# Rule: Discover Malicious Domain Lookup + +This is a correlation rule that monitors DNS logs (e.g., ISC BIND) to detect when a domain query matches a known malware or suspicious domain currently monitored in an Active List. + +## RuleId + +7005 + +## Matching + + 1 event + +## Conditions + +(event1.deviceVendor EQ "ISC" And event1.deviceProduct EQ "BIND") +And +(event1.deviceCustomString4 IS NOT NULL) +And +(InActiveList( +event1.deviceCustomString4,/All Active Lists/Threat Intel/Malicious Domains)) + +##Grouped By: + +event1.sourceAddress, event1.destinationAddress, event1.deviceCustomString4, event1.deviceVendor, event1.deviceProduct, event1.destinationPort + +## Execute actions +### On Every Event +· SendToConsole( ) +· Set Severity Very High +· SetEventField( name, Suspicious DNS Lookup - Malicious Domain) +· AddToActiveList( /All Active Lists/Monitoring/Suspicious Traffic ) + +## Source + +[https://dfirjournal.wordpress.com/category/arcsight/](https://dfirjournal.wordpress.com/category/arcsight/) + diff --git a/blueprints/secops-ai-migration-helper/migration_rules/demo_kql_9101.md b/blueprints/secops-ai-migration-helper/migration_rules/demo_kql_9101.md new file mode 100644 index 0000000..81971f8 --- /dev/null +++ b/blueprints/secops-ai-migration-helper/migration_rules/demo_kql_9101.md @@ -0,0 +1,10 @@ +//ucid: 9101 +// Source https://github.com/AllThingsComputers/Sentinel-Rules/blob/main/Event%20Logs/Rare%20Scripting%20Software%20Detected.txt + +// Title of Detection: Rare Scripting Software Detected +// Authorship & Contact: https://allthingscomputers.medium.com https://twitter.com/allthingshandle https://allthingscomputersblog.wordpress.com/ +// Description of the Detection: Because powershell and cmd prompt are so closely watched and have so many alarms put up to catch misuse, hackers are starting to avoid using them. This detects scripting tools that are utilised and found in the Event log that aren't approved software by your environment. +// References (if available): +// The Logic of the Detection or Query Begins Below This Line +Event +| where (RenderedDescription matches regex@'(?i)(command|shell|execute|script|console|terminal)' or RenderedDescription matches regex @(?i)(Bash|Ksh|Fish|Korn|ZOC|Cmder|ConEmu|Mintty)') and not(RenderedDescription matches regex (Use a regex of your expected tools in your environment to remove false positives)) \ No newline at end of file diff --git a/blueprints/secops-ai-migration-helper/migration_rules/demo_kql_9102.md b/blueprints/secops-ai-migration-helper/migration_rules/demo_kql_9102.md new file mode 100644 index 0000000..32c3a64 --- /dev/null +++ b/blueprints/secops-ai-migration-helper/migration_rules/demo_kql_9102.md @@ -0,0 +1,26 @@ +//ucid: 9102 +// Source https://github.com/AllThingsComputers/Sentinel-Rules/blob/main/Event%20Logs/Rare%20or%20Never%20Seen%20Events%20EventID%20Logged.txt +// Title of Detection: Rare or Never Seen Events EventID Logged +// Authorship & Contact: https://allthingscomputers.medium.com https://twitter.com/allthingshandle https://allthingscomputersblog.wordpress.com/ +// Description of the Detection: This requires a watchlist of every event ID from this table and one of rare event IDs +// References (if available): +// The Logic of the Detection or Query Begins Below This Line +let time_until = 1d; +let SentinelWatchlistOfEveryEIDEver = (_GetWatchlist('AllSeenEventIDsFromEventsLog') | project SearchKey); +let rarewatchlist = (_GetWatchlist('WatchlistOfRareEventsEventIDs') | project SearchKey); +let EveryEventIDSinceWatchlistCreation = (Event +| where TimeGenerated between (datetime(2022-07-19T20:00:00)..ago(time_until)) +| summarize by EventID); +let RecentRareEventIDs = (Event +| where TimeGenerated between (ago(90d)..ago(time_until)) +| summarize count() by EventID +| where count_ <= 1); // Adjust sensitivity +Event +| where TimeGenerated >= ago(1h) +| extend NewEvent = iff(EventID !in (SentinelWatchlistOfEveryEIDEver.SearchKey) + and EventID !in (EveryEventIDSinceWatchlistCreation.EventID), "EID is New", "EID is Not New") +| extend RareEvent = iff(EventID in (rarewatchlist.SearchKey) + or EventID in (RecentRareEventIDs.EventID), "EID is Rare", "EID is Not Rare") +| where NewEvent == "EID is New" or RareEvent == "EID is Rare" +| project TimeGenerated, EventID, NewEvent, RareEvent +| project-reorder NewEvent, RareEvent \ No newline at end of file diff --git a/blueprints/secops-ai-migration-helper/migration_rules/demo_kql_9103.md b/blueprints/secops-ai-migration-helper/migration_rules/demo_kql_9103.md new file mode 100644 index 0000000..25bda89 --- /dev/null +++ b/blueprints/secops-ai-migration-helper/migration_rules/demo_kql_9103.md @@ -0,0 +1,13 @@ +//ucid: 9103 +// Source https://github.com/AllThingsComputers/Sentinel-Rules/blob/main/Event%20Logs/New%20Run%20or%20RunOnce%20Scheduled%20Task.txt +// Title of Detection: New Run/RunOnce Scheduled Task +// Authorship & Contact: https://allthingscomputers.medium.com https://twitter.com/allthingshandle https://allthingscomputersblog.wordpress.com/ +// Description of the Detection: Shell-Core EventID 9706/9707/9708 +// References (if available): https://blog.menasec.net/2019/02/threat-hunting-20-runrunonce-EventID.html +// The Logic of the Detection or Query Begins Below This Line +// Source https://github.com/AllThingsComputers/Sentinel-Rules/blob/main/Event%20Logs/New%20Run%20or%20RunOnce%20Scheduled%20Task.txt +Event +| where EventID in (12, 13) +| where ParameterXml matches regex @"(?i)HK(LM|CU)\\.*(\\Run\\|\\RunOnce\\).*?<" +| extend RunRunonce = trim_end('<', extract(@"(?i)(HK(LM|CU)\\.*(\\Run\\|\\RunOnce\\).*?)<", 1, ParameterXml)) +| where not(RunRunonce matches regex @"(?i)\{[\w-]{36}\}exclusions") \ No newline at end of file diff --git a/blueprints/secops-ai-migration-helper/migration_rules/demo_kql_9104.md b/blueprints/secops-ai-migration-helper/migration_rules/demo_kql_9104.md new file mode 100644 index 0000000..87e5384 --- /dev/null +++ b/blueprints/secops-ai-migration-helper/migration_rules/demo_kql_9104.md @@ -0,0 +1,12 @@ +//ucid: 9104 +// Source: https://github.com/AllThingsComputers/Sentinel-Rules/blob/main/Security%20Event/BloodHound%20or%20Sharphound%20Artefact%20Detected.txt +// Title of Detection: BloodHound or Sharphound Artefact Detected +// Authorship & Contact: https://allthingscomputers.medium.com https://twitter.com/allthingshandle https://allthingscomputersblog.wordpress.com/ +// Description of the Detection: +// References (if available): +// The Logic of the Detection or Query Begins Below This Line +SecurityEvent +| where EventID == 5145 and not(Account matches regex @"DomainControllerRegexHere") +| where RelativeTargetName contains "srvsvc" or RelativeTargetName contains "Isarpc" or RelativeTargetName contains "samr" +| summarize dcount(RelativeTargetName) by IpAddress, IpPort, Account +| where dcount_RelativeTargetName>= 3 \ No newline at end of file diff --git a/blueprints/secops-ai-migration-helper/migration_rules/demo_kql_9105.md b/blueprints/secops-ai-migration-helper/migration_rules/demo_kql_9105.md new file mode 100644 index 0000000..cc00ed1 --- /dev/null +++ b/blueprints/secops-ai-migration-helper/migration_rules/demo_kql_9105.md @@ -0,0 +1,9 @@ +// ucid: 9105 +// Source: https://github.com/AllThingsComputers/Sentinel-Rules/blob/main/Security%20Event/Failed%20Logon%20Attempt%20with%20Null%20Network%20address.txt +// Title of Detection: Failed Logon Attempt with Null Network address +// Authorship & Contact: https://allthingscomputers.medium.com https://twitter.com/allthingshandle https://allthingscomputersblog.wordpress.com/ +// Description of the Detection: Event ID 4625 with logon type (3, 10) and source Network address is null or "-" and account name not has the value $. +// References (if available): https://www.socinvestigation.com/threat-hunting-with-windows-event-ids-4625-4624/ +// The Logic of the Detection or Query Begins Below This Line +SecurityEvent +| where EventID == 4625 and LogonType in (3, 10) and (isempty(IpAddress) or IpAddress == "-") and TargetAccount !endswith "$ \ No newline at end of file diff --git a/blueprints/secops-ai-migration-helper/migration_rules/demo_spl_8301.md b/blueprints/secops-ai-migration-helper/migration_rules/demo_spl_8301.md new file mode 100644 index 0000000..8eaada4 --- /dev/null +++ b/blueprints/secops-ai-migration-helper/migration_rules/demo_spl_8301.md @@ -0,0 +1,11 @@ +```Title: Specific File Hash Detected + Description: Create a rule to alert when a specific file hash is present + Severity: Medium + RuleId: 8301 + Source: https://docs.cloud.google.com/chronicle/docs/yara-l/transition_spl_yaral ``` + +| eval file_hashes="hash12345,hash67890,hashABCDE" +| makemv delim="," file_hashes +| mvexpand file_hashes +| search file_hashes="hash67890" +| table _time, file_hashes \ No newline at end of file diff --git a/blueprints/secops-ai-migration-helper/migration_rules/demo_spl_8302.md b/blueprints/secops-ai-migration-helper/migration_rules/demo_spl_8302.md new file mode 100644 index 0000000..5216e62 --- /dev/null +++ b/blueprints/secops-ai-migration-helper/migration_rules/demo_spl_8302.md @@ -0,0 +1,17 @@ +``` +Title: GitHub Enterprise Disable 2FA Requirement +Description: The following analytic detects when two-factor authentication (2FA) requirements are disabled in GitHub Enterprise. The detection monitors GitHub Enterprise audit logs for 2FA requirement changes by tracking actor details, organization information, and associated metadata. For a SOC, identifying disabled 2FA requirements is critical as it could indicate attempts to weaken account security controls. Two-factor authentication is a fundamental security control that helps prevent unauthorized access even if passwords are compromised. Disabling 2FA requirements could allow attackers to more easily compromise accounts through password-based attacks. The impact of disabled 2FA includes increased risk of account takeover, potential access to sensitive code and intellectual property, and compromise of the software supply chain. This activity could be part of a larger attack chain where an adversary first disables security controls before attempting broader account compromises. +RuleId: 8302.md +Source: https://github.com/splunk/security_content/blob/develop/detections/cloud/github_enterprise_disable_2fa_requirement.yml +``` + +github_enterprise` action=org.disable_two_factor_requirement OR action=business.disable_two_factor_requirement + | fillnull + | stats count min(_time) as firstTime max(_time) as lastTime + BY actor, actor_id, actor_is_bot, + actor_location.country_code, business, business_id, + user_agent, action + | eval user=actor + | `security_content_ctime(firstTime)` + | `security_content_ctime(lastTime)` + | `github_enterprise_disable_2fa_requirement_filter` \ No newline at end of file diff --git a/blueprints/secops-ai-migration-helper/misc/yaral/images/steps_overview.png b/blueprints/secops-ai-migration-helper/misc/yaral/images/steps_overview.png new file mode 100644 index 0000000..c35d106 Binary files /dev/null and b/blueprints/secops-ai-migration-helper/misc/yaral/images/steps_overview.png differ diff --git a/blueprints/secops-ai-migration-helper/misc/yaral/yaral_examples/mitre_attack_T1140_encoded_powershell_command.yaral b/blueprints/secops-ai-migration-helper/misc/yaral/yaral_examples/mitre_attack_T1140_encoded_powershell_command.yaral new file mode 100644 index 0000000..9dec2df --- /dev/null +++ b/blueprints/secops-ai-migration-helper/misc/yaral/yaral_examples/mitre_attack_T1140_encoded_powershell_command.yaral @@ -0,0 +1,55 @@ +rule mitre_attack_T1140_encoded_powershell_command { + + meta: + author = "Google Cloud Security" + description = "Detects encoded powershell commands" + rule_id = "mr_c01d7d92-db49-4044-a2c5-5a16c74a141d" + rule_name = "MITRE ATT&CK T1140 Encoded Powershell Command" + mitre_attack_tactic = "Defense Evasion" + mitre_attack_technique = "Deobfuscate/Decode Files or Information" + mitre_attack_url = "https://attack.mitre.org/techniques/T1140/" + mitre_attack_version = "v13.1" + type = "hunt" + platform = "Windows" + data_source = "microsoft sysmon, microsoft windows events" + severity = "Info" + priority = "Info" + + events: + $process.metadata.event_type = "PROCESS_LAUNCH" + $process.principal.hostname = $hostname + re.regex($process.target.process.file.full_path, `(system32|syswow64)\\WindowsPowerShell\\v1\.0\\powershell(|\_ise)\.exe`) nocase + re.regex($process.target.process.command_line, `(?i)(?:-enc|-ec|-en)\s*\S*`) + $encoded_value = re.capture($process.target.process.command_line, `(?i)(?:-enc|-ec|-en)\s*(\S*)`) + $decoded_value = re.replace(strings.base64_decode(re.capture($process.target.process.command_line, `(?i)(?:-enc|-ec|-en)\s*(\S*)`)),`\0`, "") + + match: + $hostname over 5m + + outcome: + $risk_score = max(10) + $mitre_attack_tactic = array_distinct("Defense Evasion") + $mitre_attack_technique = array_distinct("Deobfuscate/Decode Files or Information") + $mitre_attack_technique_id = array_distinct("T1140") + $event_count = count_distinct($process.metadata.id) + $encoded_powershell = array_distinct($encoded_value) + $decoded_powershell = array_distinct($decoded_value) + // added to populate alert graph with additional context + // Commented out principal.hostname because it is already represented in graph as match variable. If match changes, can uncomment to add to results + $principal_hostname = array_distinct($process.principal.hostname) + $principal_process_pid = array_distinct($process.principal.process.pid) + $principal_process_command_line = array_distinct($process.principal.process.command_line) + $principal_process_file_sha256 = array_distinct($process.principal.process.file.sha256) + $principal_process_file_full_path = array_distinct($process.principal.process.file.full_path) + $principal_process_product_specific_process_id = array_distinct($process.principal.process.product_specific_process_id) + $principal_process_parent_process_product_specific_process_id = array_distinct($process.principal.process.parent_process.product_specific_process_id) + $target_process_pid = array_distinct($process.target.process.pid) + $target_process_command_line = array_distinct($process.target.process.command_line) + $target_process_file_sha256 = array_distinct($process.target.process.file.sha256) + $target_process_file_full_path = array_distinct($process.target.process.file.full_path) + $target_process_product_specific_process_id = array_distinct($process.target.process.product_specific_process_id) + $principal_user_userid = array_distinct($process.principal.user.userid) + +condition: + $process +} \ No newline at end of file diff --git a/blueprints/secops-ai-migration-helper/misc/yaral/yaral_examples/o365_ADPowerShell_app_login_subsequent_activity.yaral b/blueprints/secops-ai-migration-helper/misc/yaral/yaral_examples/o365_ADPowerShell_app_login_subsequent_activity.yaral new file mode 100644 index 0000000..f6018f2 --- /dev/null +++ b/blueprints/secops-ai-migration-helper/misc/yaral/yaral_examples/o365_ADPowerShell_app_login_subsequent_activity.yaral @@ -0,0 +1,83 @@ +rule o365_ADPowerShell_app_login_subsequent_activity { + + meta: + author = "Google Cloud Security" + description = "Once a user authenticates to the Azure AD PowerShell application, if they take multiple admin actions indicative of establishing their own persistence with an Entra ID application within a portion of the access token time, alert for additional investigation" + rule_id = "mr_2d781f34-05f3-43aa-b5ec-257c03787a66" + rule_name = "O365 AD PowerShell App Login Subsequent Activity" + assumption = "This does not take into account attempts that were blocked, just any logging of attempts for any of these actions" + mitre_attack_tactic = "Persistence" + mitre_attack_technique = "Account Manipulation: Additional Cloud Credentials" + mitre_attack_url = "https://attack.mitre.org/techniques/T1098/001/" + mitre_attack_version = "v14.1" + type = "alert" + platform = "azure" + data_source = "o365" + severity = "Medium" + priority = "Medium" + + events: + ( + $login.metadata.event_type = "USER_LOGIN" and + $login.metadata.product_event_type = "UserLoggedIn" and + $login.metadata.product_name = "Office 365" and + $login.metadata.vendor_name = "Microsoft" and + $login.target.resource.product_object_id = "1b730954-1685-4b74-9bfd-dac224a7b894" and + $login.security_result.action = "ALLOW" + ) + $login.target.user.userid = $userid + $login.metadata.event_timestamp.seconds < $other.metadata.event_timestamp.seconds + ( + ( + $other.metadata.event_type = "USER_RESOURCE_CREATION" and + $other.metadata.product_event_type = "Add application." and + $other.metadata.product_name = "Office 365" and + $other.metadata.vendor_name = "Microsoft" + ) + or + ( + $other.metadata.event_type = "USER_RESOURCE_UPDATE_CONTENT" and + $other.metadata.product_event_type = "Update application." and + $other.metadata.product_name = "Office 365" and + $other.metadata.vendor_name = "Microsoft" + ) + or + ( + $other.metadata.event_type = "USER_RESOURCE_UPDATE_PERMISSIONS" and + $other.metadata.product_event_type = "Add delegated permission grant." and + $other.metadata.product_name = "Office 365" and + $other.metadata.vendor_name = "Microsoft" + ) + or + ( + $other.metadata.event_type = "USER_RESOURCE_UPDATE_CONTENT" and + $other.metadata.product_event_type = /Update application.*Certificates and secrets management/ nocase and + $other.metadata.product_name = "Office 365" and + $other.metadata.vendor_name = "Microsoft" + ) + ) + $other.principal.user.userid = $userid + $other.metadata.product_event_type = $other_event + + match: + $userid over 90m + + outcome: + $risk_score = max(if($other.metadata.product_event_type = "Add application.", 10, 0) + + if($other.metadata.product_event_type = "Update application.", 10, 0) + + if($other.metadata.product_event_type = "Add delegated permission grant.", 10, 0) + + if($other.metadata.product_event_type = /Update application.*Certificates and secrets management/ nocase, 55, 0)) + $mitre_attack_tactic = "Persistence" + $mitre_attack_technique = "Account Manipulation: Additional Cloud Credentials" + $mitre_attack_technique_id = "T1098.001" + $subsequent_action_threshold = 1 + $product_event_type = array_distinct($other.metadata.product_event_type) + $country_region_login_attempt = array_distinct($login.principal.ip_geo_artifact.location.country_or_region) + //added to populate alert graph with additional context + $principal_ip = array_distinct($login.principal.ip) + //$principal_user_userid = array_distinct($other.principal.user.userid) + $target_resource_name = array_distinct($other.target.resource.name) + + condition: + $login and #other_event > 0 +} \ No newline at end of file diff --git a/blueprints/secops-ai-migration-helper/misc/yaral/yaral_examples/ttp_gcp_scc_inhibit_system_recovery_google_cloud_backup_and_dr_delete_policy.yaral b/blueprints/secops-ai-migration-helper/misc/yaral/yaral_examples/ttp_gcp_scc_inhibit_system_recovery_google_cloud_backup_and_dr_delete_policy.yaral new file mode 100644 index 0000000..fdc4e7a --- /dev/null +++ b/blueprints/secops-ai-migration-helper/misc/yaral/yaral_examples/ttp_gcp_scc_inhibit_system_recovery_google_cloud_backup_and_dr_delete_policy.yaral @@ -0,0 +1,49 @@ +rule ttp_gcp_scc_inhibit_system_recovery_google_cloud_backup_and_dr_delete_policy { + meta: + rule_name = "SCC: Inhibit System Recovery: Google Cloud Backup and DR delete policy" + description = "A Backup and DR policy, which defines how a backup is taken and where it is stored, was deleted. Future backups that use the policy might fail." + severity = "Low" + tactic = "TA0040" + technique = "T1490" + reference = "https://cloud.google.com/security-command-center/docs/how-to-investigate-threats" + + events: + $e1.metadata.product_name = "Security Command Center" + $e1.metadata.product_event_type = "Inhibit System Recovery: Google Cloud Backup and DR delete policy" + $e1.security_result.detection_fields["mute"] != "MUTED" + $resource_name = $e1.target.resource.name + $rule_name = $e1.metadata.product_event_type + + match: + $rule_name over 1h + + outcome: + $resource_names = array_distinct($resource_name) + $cloud_projects = array_distinct(if($e1.target.resource_ancestors.resource_type = "CLOUD_PROJECT",$e1.target.resource_ancestors.name, "")) + $vendor_name = array_distinct($e1.metadata.vendor_name) + $product_name = array_distinct($e1.metadata.product_name) + $risk_score = max(0 + + if(any $e1.security_result.severity = "CRITICAL", 95, 0) + + if(any $e1.security_result.severity = "HIGH", 85, 0) + + if(any $e1.security_result.severity = "MEDIUM", 65, 0) + + if(any $e1.security_result.severity = "LOW", 35, 0) + + if(any $e1.security_result.severity = "INFORMATIONAL", 10, 0) + ) + $threat_category = array_distinct($e1.metadata.product_event_type) + $scc_product = array_distinct($e1.metadata.description) + $severity = array_distinct($e1.security_result.severity) + $url_back_to_product = array_distinct($e1.security_result.url_back_to_product) + $event_count = count_distinct($e1.metadata.id) + + $result_time = min($e1.metadata.event_timestamp.seconds) + $tmp1 = max( + if($e1.security_result.action != "BLOCK" and $e1.security_result.action != "UNKNOWN_ACTION", 2) + ) + $tmp2 = max( + if($e1.security_result.action = "BLOCK", 1) + ) + $result = arrays.index_to_str(strings.split("attempted,failed,succeeded,succeeded"), $tmp1 + $tmp2) + + condition: + $e1 +} \ No newline at end of file diff --git a/blueprints/secops-ai-migration-helper/misc/yaral/yaral_output_section.md b/blueprints/secops-ai-migration-helper/misc/yaral/yaral_output_section.md new file mode 100644 index 0000000..c2e2d51 --- /dev/null +++ b/blueprints/secops-ai-migration-helper/misc/yaral/yaral_output_section.md @@ -0,0 +1,70 @@ +$Source_user=principal.user.userid +$Target_user=target.user.userid +$Source_hostname=principal.hostname +$Target_hostname=target.hostname +$Logon_type=extensions.auth.auth_details +$Source_ip=principal.ip +$Target_ip=target.ip +$Workstation_Name=principal.hostname +$Event_id=metadata.product_event_type +$Channel=additional.fields["Channel"] +$CertThumbprint=security_result.detection_fields["CertThumbprint"] +$Task=additional.fields["Task"] +$Level=additional.fields["Level"] +$Source_port=src.port +$Service_name=target.application +$Status=security_result[0].description +$Domain=principal.administrative_domain +$Target_sid=target.user.windows_sid +$Source_sid=principal.user.windows_sid +$AccessMask=additional.fields["AccessMask"] +$Target_file_path=target.file.full_path +$Object_type=target.resource.resource_subtype +$Target_File_Names=target.file.names +$Share_name=target.resource.name +$Task_Name=target.resource.name +$Target_resource_name=target.resource.name +$Authentication_Type=security_result[0].about.resource.name +$Product_name=metadata.product_name +$Activity=security_result.detection_fields["Activity"] +$Key_Length=additional.fields["Key_Length"] +$Lm_Package_Name=target.labels["Lm_Package_Name"] +$Logon_Guid=additional.fields["Logon_Guid"] +$Source_proccess_path=principal.process.file.full_path +$Target_proccess_path=target.process.file.full_path +$Source_process_command_line=principal.process.command_line +$Target_process_command_line=target.process.command_line +$Source_process_pid=principal.process.pid +$Target_process_pid=target.process.pid +$Subject_Logon_Id=principal.labels["Subject_Logon_Id"] +$Target_logon_id=additional.fields["Target_logon_id"] +$Target_file_name=target.file.names +$Target_user_permissions=target.user.attribute.permissions[0].name +$Count_logs=metadata.id +$Result=additional.fields["Result"] +$Tenant_id=additional.fields["Tenant_id"] +$Security_result_action=security_result.action +$Security_result_description=security_result.description +$AlertLink=principal.resource.attribute.labels["AlertLink"] +$Compromised_Entity=principal.resource.attribute.labels["Compromised_Entity"] +$Rule_name=security_result.rule_name +$Threat_name=security_result.threat_name +$Severity=security_result.severity +$Source_system=security_result.detection_fields["Source_system"] +$Attack_tactic=security_result.attack_details.tactics.name +$Source_resource=principal.resource.name +$Source_resource_type=principal.resource.resource_subtype +$Summary=security_result.summary +$Severity_details=security_result.severity_details +$Target_user_display_name=target.user.user_display_name +$Target_user_email_addresses=target.user.email_addresses +$App_id=security_result.detection_fields["App_id"] +$User_agent=network.http.user_agent +$Source_location=principal.location.country_or_region +$Source_state=principal.ip_geo_artifact.location.state +$Network_Direction=network.direction +$Target_Url=target.url +$Method=network.http.method +$Protocol=network.application_protocol +$Response_Code=network.http.response_code +$Vendor_name=metadata.vendor_name \ No newline at end of file diff --git a/blueprints/secops-ai-migration-helper/misc/yaral/yaral_syntax.md b/blueprints/secops-ai-migration-helper/misc/yaral/yaral_syntax.md new file mode 100644 index 0000000..f58f507 --- /dev/null +++ b/blueprints/secops-ai-migration-helper/misc/yaral/yaral_syntax.md @@ -0,0 +1,66 @@ +# YARA-L 2.0 Functions Quick Reference + +Here is a consolidated list of commonly used YARA-L 2.0 functions with examples, based on the official Google Cloud documentation. 🧑‍💻 + +--- + +## String Functions +These functions are used to manipulate and analyze string data. + +| Function | Description | Example | +|---|---|---| +| **`strings.coalesce(val1, val2, ...)`** | Returns the first non-null string value from a list of arguments. | `strings.coalesce($e.principal.user.userid, $e.principal.user.email_addresses)` | +| **`strings.concat(str1, str2, ...)`** | Concatenates two or more strings together. | `strings.concat("File path: ", $e.target.file.full_path)` | +| **`strings.to_lower(str)`** | Converts a string to lowercase. | `strings.to_lower($e.principal.hostname)` | +| **`strings.to_upper(str)`** | Converts a string to uppercase. | `strings.to_upper($e.target.process.name)` | +| **`strings.contains(haystack, needle)`** | Returns `true` if the `haystack` string contains the `needle` string. | `strings.contains($e.principal.process.command_line, "powershell")` | +| **`strings.extract_domain(url)`** | Extracts the domain from a URL. | `strings.extract_domain($e.network.http.url)` | +| **`strings.split(str, delimiter)`** | Splits a string into an array of strings based on a delimiter. | `strings.split($e.principal.process.command_line, " ")` | +| **`strings.starts_with(str, prefix)`** | Returns `true` if the string starts with the specified prefix. | `strings.starts_with($e.target.file.full_path, "/tmp/")` | +| **`strings.substr(str, offset, length)`** | Returns a substring of a given string. | `strings.substr($e.principal.user.userid, 0, 5)` | +| **`strings.trim(str)`**| Removes leading and trailing whitespace from a string. | `strings.trim(" some text ")` | + +--- + +## Regular Expression Functions +These functions allow you to use regular expressions for more complex pattern matching. + +| Function | Description | Example | +|---|---|---| +| **`re.regex(text, pattern)`** | Returns `true` if the `text` matches the regular expression `pattern`. | `re.regex($e.principal.process.command_line, `\\bsvchost(\\.exe)?\\b`)` | +| **`re.capture(text, pattern)`** | Returns the first captured group from a regular expression match. | `re.capture($e.network.http.url, `user=([^&]+)`)` | +| **`re.replace(text, pattern, replacement)`** | Replaces all occurrences of a pattern in a string with a replacement string. | `re.replace($e.target.file.full_path, `\\.log$`, ".txt")` | + +--- + +## Math Functions +These functions perform mathematical operations. + +| Function | Description | Example | +|---|---|---| +| **`math.abs(num)`** | Returns the absolute value of a number. | `math.abs(-10)` | +| **`math.ceil(num)`** | Rounds a number up to the nearest integer. | `math.ceil(3.14)` | +| **`math.floor(num)`** | Rounds a number down to the nearest integer. | `math.floor(3.14)` | +| **`math.round(num)`** | Rounds a number to the nearest integer. | `math.round(3.5)` | + +--- + +## Array Functions +These functions are used to work with arrays of data. + +| Function | Description | Example | +|---|---|---| +| **`arrays.contains(array, value)`** | Returns `true` if the array contains the specified value. | `arrays.contains($e.principal.ip, "192.168.1.100")` | +| **`arrays.length(array)`**| Returns the number of elements in an array. | `arrays.length($e.principal.user.email_addresses)` | +| **`arrays.index_to_str(array, index)`** | Returns the string element at a specific index in an array. | `arrays.index_to_str(strings.split($e.principal.process.command_line, " "), 0)`| + +--- + +## Timestamp Functions +These functions help you work with time-based data. 🕰️ + +| Function | Description | Example | +|---|---|---| +| **`timestamp.now()`** | Returns the current Unix timestamp in seconds. | `timestamp.now()` | +| **`timestamp.get_hour(unix_seconds)`** | Returns the hour (0-23) from a Unix timestamp. | `timestamp.get_hour($e.metadata.event_timestamp.seconds)` | +| **`timestamp.diff(t1, t2)`** | Returns the difference in seconds between two Unix timestamps. | `timestamp.diff($e2.metadata.event_timestamp.seconds, $e1.metadata.event_timestamp.seconds)` | \ No newline at end of file diff --git a/blueprints/secops-ai-migration-helper/recommender_curated_community/README.md b/blueprints/secops-ai-migration-helper/recommender_curated_community/README.md new file mode 100644 index 0000000..5764260 --- /dev/null +++ b/blueprints/secops-ai-migration-helper/recommender_curated_community/README.md @@ -0,0 +1,79 @@ +# SecOps migraiton helper: recommender for curated and community rules based on custom rules + +**A GenAI powered migraiton**. The tool recommends curated and community rules that provide the simular security objective as the input rule that can be from different SIEM plattfrom, like Auzre Log Analytics, etc + +**DESCRIPTION:** + This script analyzes a set of customer-provided detection rules, like KQL, ArcSight, SPL etc, and recommends relevant + curated and community rules. It can fetch curated rules live from the Chronicle SecOps content hub or + use pre-loaded local files. The final recommendations are saved in both JSON and CSV formats. + +**FUNCTIONALITY:** +- Loads latest curated rules from SecOps ContentHub instance. +- Loads latest rule sets from SecOps ContentHub instance +- Combines rule with rulesets rules with needed log sources +- Uses GenAI to classify the required log sources from the input rules +- Loads all community rules form flat file in the repo +- Recommends curated and community rules with the same security objective to the input rules. Provides rational, log sources, rules sets, category and rule name +- Export the result to JSOn and CSV + +**USAGE:** + python recommender_curated_community.py + +**CONFIGURATION (via Environment Variables)**: + The script's behavior is configured through environment variables. + Default values are shown in parentheses. + + [Content Hub Connection] + + - CONTENTHUB_PROJECT_ID: Google Cloud Project ID for the content hub. + - CONTENTHUB_LOCATION: Location of the content hub. (Default: "eu") + - CONTENTHUB_INSTANCE_ID: Instance ID for the content hub. + + [AI Configuration] + + - AI_MODEL: The Vertex AI model to use for generation. (Default: "gemini-2.5-pro") + + [Input Files] + + - CUSTOMER_RULES_TO_EVALUATE: Path to the JSON file with customer rules. (Default: "./resources/sample_rules.json") + - COMMUNITY_RULES: Path to the text file with all community rules. (Default: "./resources/all_community_rules_20250816.txt") + + + [Preloaded Curated Rules ] + + + - CURATED_USE_PRELOADED_FILE: Set to "True" to use local files instead of fetching from the API. (Default: "False") + - CURATED_RULES_FILE: Path to the preloaded curated rules JSON file. (Default: "./resources/curated_rules.json") + - CURATED_RULESETS_FILE: Path to the preloaded curated rulesets JSON file. (Default: "./resources/curated_rulesets.json") + + [Output Files] + + - CURATED_RULES_OUTPUT_FILE: Where to save fetched curated rules. (Default: "./work_dir/curated_rules.json") + - CURATED_RULESETS_OUTPUT_FILE: Where to save fetched curated rulesets. (Default: "./work_dir/curated_rulesets.json") + - RECOMMENDATIONS_JSON_OUTPUT_FILE: Path for the final JSON recommendations. (Default: "./work_dir/recommendation_curated_community_rules.json") + +**COMMUNITY RULES DUMP:** + +Community rules are currently as one big dump file part of the repo, see file `./resources/all_community_rules_20250816.txt` The size of file allows adding all in the LLM context. Cutomers prefer to focus on curated due to google support. You can generate the dump by 1) cloning the repo 2) `find . -type f -name "*.yaral" -print0 | xargs -0 cat > all_community_rules.txt` + +**OUTPUT:** + + Files in the **work_dir** + - **recommendation_curated_community.json** is JSON file with recommendations + - Format: + + `[ { "ucid": "customer idenfifyer", "title": "Title of the rule" "description": "Desciption of the rule", "rule": "rule definition" }, "curated rules": "category, ruleset and rule name curated rules with same objecitve", + "curated rules coverage": "yes|partially|no", + "curated rationale": "crisp rationale and log sources needed", + "community rules": "cathegory/rule_set/rules_name", + "community rules coverage": "yes", + "community rationale": "crisp rationale"}...]` + - **curated_commjunity_recommendaiton.csv** is CSV file with recommendations suitable for table view + - **recommendation_curated_rulesets.csv** is CSV with recommended rulesets suitable a reverce lookupaka, which ruleset are recommended for the rules in thei batch + + +**Status:** PROTOTYPE + +**TODO:** + + - (FEATURE) Missing unity tests diff --git a/blueprints/secops-ai-migration-helper/recommender_curated_community/ai_helper.py b/blueprints/secops-ai-migration-helper/recommender_curated_community/ai_helper.py new file mode 100644 index 0000000..172500f --- /dev/null +++ b/blueprints/secops-ai-migration-helper/recommender_curated_community/ai_helper.py @@ -0,0 +1,362 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# +# Generate answer to question using mutimodel LLM +# +from google.auth import default +from google import genai +from google.genai import types + +# Generation Config with low temperature for reproducible results + +safety_settings = [ + types.SafetySetting( + category=types.HarmCategory.HARM_CATEGORY_HARASSMENT, + threshold=types.HarmBlockThreshold.BLOCK_NONE, + ), + types.SafetySetting( + category=types.HarmCategory.HARM_CATEGORY_HATE_SPEECH, + threshold=types.HarmBlockThreshold.BLOCK_NONE, + ), + types.SafetySetting( + category=types.HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT, + threshold=types.HarmBlockThreshold.BLOCK_NONE, + ), + types.SafetySetting( + category=types.HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT, + threshold=types.HarmBlockThreshold.BLOCK_NONE, + ), +] + + +# Generate Answer +def generate_answer(input: str, + instructions: str, + response_schema, + files: list | None = None, + markdown: bool = True) -> str: + """Generate a response to the given input using the LLM.""" + contents = [input] + if files: + for f in files: + contents.append(f) + + config = types.GenerateContentConfig( + temperature=0.1, + #max_output_tokens=2048, + top_k=1, + #top_p=0.1, + candidate_count=1, + response_mime_type="application/json", + response_schema=response_schema, + system_instruction=instructions, + safety_settings=safety_settings) + + # Use Vertex AI backend with default credentials + # Requires google-auth default credentials and a project defined in the environment, + # or passing project and location explicitly if needed. + # In recommender_curated_community.py there are contenthub_project_id and contenthub_location + import recommender_curated_community + import os + + # Initialize Google GenAI client for Vertex AI usage + client = genai.Client(vertexai=True) + + # using the model defined in recommender_curated_community + model_name = recommender_curated_community.ai_model + print("Generating response...") + response = client.models.generate_content(model=model_name, + contents=contents, + config=config) + print("Response generated") + return response.text + + +def generate_curated_rules_recommendation(input_rule, curated_rules): + """ + Generates GenAI suggestion based on input rule and curated rules + + """ + prompt = f""" + # Provide Google SecOps curated that cover the security objective of the input rule. + + Expected output: + - 'ucid' : provided do not change. identifier of the usecase from the input + - 'title': provided do not change. title of rules we want to cover used to determine the security objective + - 'description': provided do not change. Description of rules you want to cover used to determine the security objective + - 'rule' : content of rules you want to cover used to determine the security objective + - 'curated rules': curated rules that potential cover this objective (comma separated), Extract from contentMetadata value displayName, categories, and from ruleSet value displayName.Notation: ["ruleSet"]["categories"]/["ruleSet"]["displayName"]/["contentMetadata"]["displayName"] + - 'curated rules coverage': provide curated rule coverage as: no (missing equivalent), partially (meaning some coverage, like matches tactic and objecitive, but missing log sources, vendor, or rule logic), or very good (meaning coverage of security objective) + - 'curated rationale': crisp description of why suggested curated rules may cover this objective. Indicate the log data sources needed curated rules + + Using attached documents and the following input: + - 'ucid' + - 'title' + - 'description' + - 'rule' + + ## Example 1: + Input: + - 'ucid': '5582' + - 'title': 'SOC - Exchange UM Spawning Unexpected Processes (HAFNIUM)' + - 'description': 'Identifies abnormal child processes originating from the Exchange Unified Messaging service that deviate from known baselines.' + - 'rule': '//ucid: 5582\\n//author: Alice Smith\\n//title: SOC - Suspicious Volume Shadow Copy Modification\\n//severity: High\\n//description: Ransomware precursor behavior\\n//technique: T1490\\n//date created: 15/05/2022\\n//date reviewed: 20/11/2023\\n//contributor: \\n\\nSecurityEvent\\n| where TimeGenerated > ago(24h)\\n| where EventID == 4688\\n| where NewProcessName !has \\\"outlook.exe\\\" and NewProcessName !has \\\"msedge.exe\\\"' + Answer: + - 'ucid': '5582' + - 'title': 'SOC - Exchange UM Spawning Unexpected Processes (HAFNIUM)' + - 'description': 'Identifies abnormal child processes originating from the Exchange Unified Messaging service that deviate from known baselines.' + - 'curated rules': 'Windows Threats/Initial Access/Hafnium Exchange Web Shell' + - 'curated rules coverage': 'very good' + - 'curated rationale': 'Exchange web shell behavior is covered accurately by the SecOps curated rule. Log Data Sources: Carbon Black (CB_EDR), Microsoft Sysmon (WINDOWS_SYSMON), SentinelOne (SENTINEL_EDR), Crowdstrike Falcon (CS_EDR)' + + + ## Example 2: + Input: + - 'ucid': '7741', + - 'title' : 'SOC - CLI Directory Traversal - HighValueTargets\"", + - 'description': "Identifies directory traversal patterns within cmd.exe, which often signals attempts to bypass execution controls, hijack arguments, or access restricted file paths.", + - 'rule': '//ucid: 7741\\n//author: Bob Johnson\\n//title: SOC - CLI Directory Traversal\\n//severity: Medium\\n//description: Identifies directory traversal patterns within cmd.exe, which often signals attempts to bypass execution controls, hijack arguments, or access restricted file paths.\\n//technique: T1059.003\\n//date created: 10/02/2023\\n//date reviewed: 05/01/2024\\n//contributor: Carol Williams\\n\\nlet AllowedPaths = datatable(AllowedStr: string) [\\n \\\"Microsoft Visual Studio\\\", \\\"Windows Defender\\\", \\\"\\\\\\\\LoadRunner\\\", \\\"\\\\\\\\LoadGenerator\\\\\\\\\\\",\\n \\\"\\\\\\\\wwwroot\\\\\\\\AppFlow\\\\\\\\\\\", \\\"DELL\\\\\\\\WMS\\\", \\\"Admin Software\\\", \\\"WebProxyService.exe\\\",\\n \\\"python\\\", \\\"sdb.exe\\\", \\\"....\\\\\\\\\\\", \\\"app.locale\\\",\\n \\\"Macro Focus\\\", \\\"Anaconda3\\\", \\\"D2FRQExImportSetup.msi\\\", \\\"DIR /-C /TW /4\\\"\\n];\\nSecurityEvent\\n| where TimeGenerated > ago(24h)\\n| where EventID == 4688\\n| where ParentProcessName has_any (\\\"cmd.exe\\\", \\\"powershell.exe\\\")\\n//eg: ../../../../WINNT/win.ini\\n// /scripts/..%5c../winnt/system32/ cmd.exe?/c+dir+c:\\\\\\n//hxxps://[www.imperva.com/learn/application-security/directory-traversal/](https://www.imperva.com/learn/application-security/directory-traversal/)\\n//\\n// the following regex is specifically for exclusion of dot dot slash notation where there are less than 4 occurrences as they can be considered common place\\n// this is achieved by firstly identifying dot dot slash notations that occur less than 4 times and excluding them\\n//[a-z0-9 =:;@\\\\\\\"*\\\\\\\\.](\\\\\\\\\\\\\\\\|\\\\\\\\/){0,2} --> prefixing the dotdotslash can be a variety of symbols e.g. dirabc\\\\..\\\\..\\\\ or myfolder\\\\+..\\\\..\\\\ etc\\n//(\\\\\\\\.\\\\\\\\.(\\\\\\\\\\\\\\\\|\\\\\\\\/)){1,3} --> matches that actual dotdotslash notation of either ../ or ..\\\\ repeating up to 3 times e.g. will match on ../..\\\\../\\n//(\\\\\\\\\\\\\\\\)?((\\\\\\\\.){0,2})?([a-z0-9 @*]|$ --> after 1-3 dotdotslash notations the string should either terminate or have characters that don\u00e2\u0080\u0099t match ..\\\\ to allow the next regex to pick up 4 iterations of greater\\n| extend ExcludeTraversal = iif(CommandLine matches regex \\\"(?i)[+a-z0-9 =:;@\\\\\\\"*\\\\\\\\.](\\\\\\\\\\\\\\\\|\\\\\\\\/){0,2}(\\\\\\\\.\\\\\\\\.(\\\\\\\\\\\\\\\\|\\\\\\\\/)){1,3}(\\\\\\\\\\\\\\\\)?((\\\\\\\\.){0,2})?([a-z0-9 @*+]|$)\\\", \\\"Matche' + + Answer: + - 'ucid': '7741', + - 'title' : 'SOC - CLI Directory Traversal - HighValueTargets\"", + - 'description': "Identifies directory traversal patterns within cmd.exe, which often signals attempts to bypass execution controls, hijack arguments, or access restricted file paths.", + - 'curated rules': 'Windows Threats/Mandiant Frontline Threats/Cmd.exe or Powershell.exe Payload Creating Windows Service', + - 'curated rules coverage': 'partially' + - 'curated rationale': 'The curated rule detects service creation via command line or PowerShell, tracking how an attacker might deploy a service pointing to a remote payload. It covers the creation mechanism but does not specifically parse the binPath for traversal variables. Log Data Sources: Carbon Black (CB_EDR), Microsoft Sysmon (WINDOWS_SYSMON), SentinelOne (SENTINEL_EDR), Crowdstrike Falcon (CS_EDR).' + + + ##Google SecOps curated rules as JSON follow: + {curated_rules} + + + ## Input rule: + {input_rule} + + + + """ + + instructions = """ + Analyze the provided input rule title, description and rule definition in oder to find curated detection rules the cover the same security objective. + Answer only with curated detection rules the you are provided. + Ensure think logically and consider all provided curated detection rules. Ensure not missing rules that may have the similar security objective + Consider that a curated detection rules with indicators of compromise (IOC) based on Applied Threat Intelligence could cover many malware, unusual binaries or hacker tools. + Consider that a curated detection rules with a user and entity behavior analytics (UEBA) can cover suspicious, unusual, not normal: actions, scripts executions, connections and other behaviors. + Do not change 'ucid', 'title','description'. + If you see multiple potential candidates, list them with a comma separated. List maximal 5 curated or 5 community rules per input rule + Indicate the log sources needed for curated or community rules in rational as Log Data Sources + If you can not find an answer use 'N/A'. + + """ + + response_schema = { + "type": "object", + "properties": { + "ucid": { + "type": "string" + }, + "title": { + "type": "string" + }, + "description": { + "type": "string" + }, + "curated rules": { + "type": "string" + }, + "curated rules coverage": { + "type": "string" + }, + "curated rationale": { + "type": "string" + }, + } + } + + # for debug + # with open('prompt.txt', 'w') as f: + # f.write(prompt) + # print("Prompt written to prompt.txt") + + p = generate_answer(prompt, instructions, response_schema) + return (p) + + +# WIP (not used) for spitting curated and community in separate calls +def generate_community_rules_recommendation(input_rule, all_community_rules): + """ + Generates GenAI suggestion based on input rule + all community rules are attached to the prompt, since not very large + """ + prompt = f""" + # Provide Google SecOps community rules that cover the security objective of the input rule. + + Expected output: + - 'ucid' : provided do not change. identifier of the usecase from the input + - 'title': provided do not change. title of rules we want to cover used to determine the security objective + - 'description': provided do not change. Description of rules you want to cover used to determine the security objective + - 'rule' : content of rules you want to cover used to determine the security objective + - 'community rules': community rules name that cover the objective and functionality (comma separated). Extract the rule name from the definiton. Notation: def [community_rule_name] {{ + - 'community rules coverage': provide community rule coverage as: no (missing equivalent), partially (meaning some coverage, like matches tactic and objecitive, but missing log sources, vendor, or rule logic), or very good (meaning coverage of security objective) + - 'community rationale': crisp description of why suggested community rules may cover this objective. Indicate the log data sources needed for community rules + + Using attached documents and the following input: + - 'ucid' + - 'title' + - 'description' + - 'rule' + + ## Example 1: + Input: + - 'ucid': '5582' + - 'title': 'SOC - Exchange UM Spawning Unexpected Processes (HAFNIUM)' + - 'description': 'Identifies abnormal child processes originating from the Exchange Unified Messaging service that deviate from known baselines.' + - 'rule': '//ucid: 5582\\n//author: Alice Smith\\n//title: SOC - Suspicious Volume Shadow Copy Modification\\n//severity: High\\n//description: Ransomware precursor behavior\\n//technique: T1490\\n//date created: 15/05/2022\\n//date reviewed: 20/11/2023\\n//contributor: \\n\\nSecurityEvent\\n| where TimeGenerated > ago(24h)\\n| where EventID == 4688\\n| where NewProcessName !has \\\"outlook.exe\\\" and NewProcessName !has \\\"msedge.exe\\\"' + Answer: + - 'ucid': '5582' + - 'title': 'SOC - Exchange UM Spawning Unexpected Processes (HAFNIUM)' + - 'description': 'Identifies abnormal child processes originating from the Exchange Unified Messaging service that deviate from known baselines.' + - 'community rules': 'N/A' + - 'community rules coverage': 'no' + - 'community rationale': 'N/A' + + ## Example 2: + Input: + - 'ucid': '7741', + - 'title' : 'SOC - CLI Directory Traversal - HighValueTargets\"", + - 'description': "Identifies directory traversal patterns within cmd.exe, which often signals attempts to bypass execution controls, hijack arguments, or access restricted file paths.", + - 'rule': '//ucid: 7741\\n//author: Bob Johnson\\n//title: SOC - CLI Directory Traversal\\n//severity: Medium\\n//description: Identifies directory traversal patterns within cmd.exe, which often signals attempts to bypass execution controls, hijack arguments, or access restricted file paths.\\n//technique: T1059.003\\n//date created: 10/02/2023\\n//date reviewed: 05/01/2024\\n//contributor: Carol Williams\\n\\nlet AllowedPaths = datatable(AllowedStr: string) [\\n \\\"Microsoft Visual Studio\\\", \\\"Windows Defender\\\", \\\"\\\\\\\\LoadRunner\\\", \\\"\\\\\\\\LoadGenerator\\\\\\\\\\\",\\n \\\"\\\\\\\\wwwroot\\\\\\\\AppFlow\\\\\\\\\\\", \\\"DELL\\\\\\\\WMS\\\", \\\"Admin Software\\\", \\\"WebProxyService.exe\\\",\\n \\\"python\\\", \\\"sdb.exe\\\", \\\"....\\\\\\\\\\\", \\\"app.locale\\\",\\n \\\"Macro Focus\\\", \\\"Anaconda3\\\", \\\"D2FRQExImportSetup.msi\\\", \\\"DIR /-C /TW /4\\\"\\n];\\nSecurityEvent\\n| where TimeGenerated > ago(24h)\\n| where EventID == 4688\\n| where ParentProcessName has_any (\\\"cmd.exe\\\", \\\"powershell.exe\\\")\\n//eg: ../../../../WINNT/win.ini\\n// /scripts/..%5c../winnt/system32/ cmd.exe?/c+dir+c:\\\\\\n//hxxps://[www.imperva.com/learn/application-security/directory-traversal/](https://www.imperva.com/learn/application-security/directory-traversal/)\\n//\\n// the following regex is specifically for exclusion of dot dot slash notation where there are less than 4 occurrences as they can be considered common place\\n// this is achieved by firstly identifying dot dot slash notations that occur less than 4 times and excluding them\\n//[a-z0-9 =:;@\\\\\\\"*\\\\\\\\.](\\\\\\\\\\\\\\\\|\\\\\\\\/){0,2} --> prefixing the dotdotslash can be a variety of symbols e.g. dirabc\\\\..\\\\..\\\\ or myfolder\\\\+..\\\\..\\\\ etc\\n//(\\\\\\\\.\\\\\\\\.(\\\\\\\\\\\\\\\\|\\\\\\\\/)){1,3} --> matches that actual dotdotslash notation of either ../ or ..\\\\ repeating up to 3 times e.g. will match on ../..\\\\../\\n//(\\\\\\\\\\\\\\\\)?((\\\\\\\\.){0,2})?([a-z0-9 @*]|$ --> after 1-3 dotdotslash notations the string should either terminate or have characters that don\u00e2\u0080\u0099t match ..\\\\ to allow the next regex to pick up 4 iterations of greater\\n| extend ExcludeTraversal = iif(CommandLine matches regex \\\"(?i)[+a-z0-9 =:;@\\\\\\\"*\\\\\\\\.](\\\\\\\\\\\\\\\\|\\\\\\\\/){0,2}(\\\\\\\\.\\\\\\\\.(\\\\\\\\\\\\\\\\|\\\\\\\\/)){1,3}(\\\\\\\\\\\\\\\\)?((\\\\\\\\.){0,2})?([a-z0-9 @*+]|$)\\\", \\\"Matche' + + Answer: + - 'ucid': '7741', + - 'title' : 'SOC - CLI Directory Traversal - HighValueTargets\"", + - 'description': "Identifies directory traversal patterns within cmd.exe, which often signals attempts to bypass execution controls, hijack arguments, or access restricted file paths.", + - 'community rules': 'mitre_attack_T1570_suspicious_command_psexec,mitre_attack_T1140_encoded_powershell_command' + - 'community rules coverage': 'partially', + - 'community rationale': 'The community rule detects the creation of services with suspicious names. While it does not check the binary path for external addresses, it provides coverage for a related persistence technique involving malicious services. Log Data Sources: Microsoft Windows Event Logs.', + + ## Google SecOps Community rules as text follow: + {all_community_rules} + + ## Input rule: + {input_rule} + + + + """ + + instructions = """Analyze the provided input rule title, description and rule definition in oder to find community rules the cover the same security objective. + Answer only with community rules the you are provided. + Think logicaly and check your answer for all communioty same input objective and follow the format for the output in the notation. + Consider that community rules with indicators of compromise (IOC) based on Applied Threat Intelligence could cover many malware or hacker tools. + Consider that community rules with a user and entity behavior analytics (UEBA) can cover suspicious actions, executions, connections and other behaviors. + Do not change 'ucid', 'title','description'. + If you see multiple potential candidates, list them with a comma separated. List maximal 5 community rules per input rule + Indicate the log sources needed for community rules in rational as Log Data Sources + If you can not find an answer use 'N/A'. """ + + response_schema = { + "type": "object", + "properties": { + "ucid": { + "type": "string" + }, + "title": { + "type": "string" + }, + "description": { + "type": "string" + }, + "community rules": { + "type": "string" + }, + "community rules coverage": { + "type": "string" + }, + "community rationale": { + "type": "string" + } + } + } + + # for debug + # with open('prompt.txt', 'w') as f: + # f.write(prompt) + # print("Prompt written to prompt.txt") + + p = generate_answer(prompt, instructions, response_schema) + return (p) + + +# helper funation to determine the log source needed for certain customer rule +def find_log_sources_needed(rule, unique_log_types): + """ + Uses GenAI to determine log type needed for input rule + """ + prompt = f"""Determine which are the necessary log sources for the following rules. + + The only avalable log sources are: {unique_log_types} + + Example: + Input: + - 'ucid': '1234' + - 'title': 'Service Creation referencing External IP Address or URL + - 'description': 'Looking for the creation of service that point to external addresses either IP or URL, as this would be very unusual and could be a form of persistence for an attacker to re-establish control or deploy new payloads." + - 'rule': // Data Source: Security Events\nEvent\n// Timeframe: Look back over the last 24 hours\n| where TimeGenerated > ago(1d)\n// Filter for relevant PowerShell logging Event IDs (Script Block Logging, Module Logging)\n| where EventID in (4104, 4103, 800) + + Output: + - 'ucid': '1234' + - 'title': 'Service Creation referencing External IP Address or URL + - 'description': 'Looking for the creation of service that point to external addresses either IP or URL, as this would be very unusual and could be a form of persistence for an attacker to re-establish control or deploy new payloads." + - 'rule': // Data Source: Security Events\nEvent\n// Timeframe: Look back over the last 24 hours\n| where TimeGenerated > ago(1d)\n// Filter for relevant PowerShell logging Event IDs (Script Block Logging, Module Logging)\n| where EventID in (4104, 4103, 800) + - log_sources: ['EDR', 'CS-EDR', 'Endpoint'] + + + Input rules: + + {rule}""" + + instructions = "Analyze the provided rule title, descitpiton and rule definition, used sources, tables to determine the needed log sources. Do not change 'ucid', 'title','description' and 'rule'. Consider overlaps, like for example EDR collects the all log on servers and hosts. Endpoint log type is the same as EDR and CS-EDR and EDR like logs." + + response_schema = { + "type": "array", + "items": { + "type": "object", + "properties": { + "ucid": { + "type": "string" + }, + "title": { + "type": "string" + }, + "description": { + "type": "string" + }, + "rule": { + "type": "string" + }, + "log_sources": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + } + + p = generate_answer(prompt, instructions, response_schema) + return (p) diff --git a/blueprints/secops-ai-migration-helper/recommender_curated_community/recommender_curated_community.py b/blueprints/secops-ai-migration-helper/recommender_curated_community/recommender_curated_community.py new file mode 100644 index 0000000..ff2249b --- /dev/null +++ b/blueprints/secops-ai-migration-helper/recommender_curated_community/recommender_curated_community.py @@ -0,0 +1,268 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from google.auth import default +import vertexai +from vertexai.preview.language_models import TextEmbeddingModel +from vertexai.preview.language_models import TextGenerationModel +#from vertexai.preview.language_models import HarmCategory, HarmBlockThreshold +from vertexai.generative_models import ( + FinishReason, + GenerationConfig, + GenerativeModel, + HarmBlockThreshold, + HarmCategory, + Part, +) +from vertexai.generative_models._generative_models import SafetySettingsType +import os +import json +import re +import sys +import google.auth +import google.auth.transport.requests +import requests +import csv +import subprocess +import secops_resources_helper +import ai_helper + +# CONSTANTS + +# SecOps ContentHub instance in order to download the latest version +contenthub_project_id = os.getenv("CONTENTHUB_PROJECT_ID") +contenthub_location = os.getenv("CONTENTHUB_LOCATION") +contenthub_instance_id = os.getenv("CONTENTHUB_INSTANCE_ID") + +if "--help" not in sys.argv: + missing_vars = [] + if not contenthub_project_id: missing_vars.append("CONTENTHUB_PROJECT_ID") + if not contenthub_location: missing_vars.append("CONTENTHUB_LOCATION") + if not contenthub_instance_id: + missing_vars.append("CONTENTHUB_INSTANCE_ID") + if missing_vars: + raise ValueError( + f"Required environment variables are not set: {', '.join(missing_vars)}" + ) + +# AI configuration +ai_model = os.getenv("AI_MODEL", "gemini-2.5-pro") + +# File will all community rules +customer_rules_to_evaluate = os.getenv("CUSTOMER_RULES_TO_EVALUATE", + "./resources/sample_input_rules.json") +community_rules = os.getenv("COMMUNITY_RULES", + "./resources/all_community_rules_20250816.txt") + +# optional if provided it will not be downloaded from content hub +curated_use_preloaded_file = os.getenv("CURATED_USE_PRELOADED_FILE", + "False") # True or False +curated_rules_file = os.getenv("CURATED_RULES_FILE", + "./resources/curated_rules.json") +curated_rulesets_file = os.getenv("CURATED_RULESETS_FILE", + "./resources/curated_rulesets.json") + +# Output files +curated_rules_output_file = os.getenv("CURATED_RULES_OUTPUT_FILE", + "./work_dir/curated_rules.json") +curated_rulesets_output_file = os.getenv("CURATED_RULESETS_OUTPUT_FILE", + "./work_dir/curated_rulesets.json") +recommendations_json_output_file = os.getenv( + "RECOMMENDATIONS_JSON_OUTPUT_FILE", + "./work_dir/recommendation_curated_community_rules.json") +recommendations_csv_output_file = os.getenv( + "RECOMMENDATIONS_CSV_OUTPUT_FILE", + "./work_dir/recommendation_curated_community_rules.csv") +recommendations_ruleset_csv_output_file = os.getenv( + "RECOMMENDATIONS_CSV_OUTPUT_FILE", + "./work_dir/recommendation_curated_rulesets.csv") + + +def load_curated_rules_description(): + """ + Loads all curated rules and rules sets + Returns curated rules enriched with log sources + """ + chronicle_client = secops_resources_helper.get_chronicle_client( + contenthub_project_id, contenthub_location, contenthub_instance_id) + if not chronicle_client: + sys.exit(1) + + all_curated_rules = secops_resources_helper.get_featured_content_rules( + chronicle_client) + all_curated_rulesets = secops_resources_helper.get_curated_rule_sets( + chronicle_client) + all_curated_rules = secops_resources_helper.add_log_sources_to_curated_list( + all_curated_rulesets, all_curated_rules) + + return (all_curated_rules, all_curated_rulesets) + + +def print_help(): + """Prints the help message for the script.""" + # Using __file__ allows the script name to be dynamic + script_name = os.path.basename(__file__) + help_text = f""" +USAGE: + python {script_name} + +DESCRIPTION: + This script analyzes a set of customer-provided detection rules, like KQL etc, and recommends relevant + curated and community rules. It can fetch curated rules live from the Chronicle SecOps content hub or + use pre-loaded local files. The final recommendations are saved in both JSON and CSV formats. + +CONFIGURATION (via Environment Variables): + The script's behavior is configured through environment variables. + Default values are shown in parentheses. + + [Content Hub Connection] + CONTENTHUB_PROJECT_ID: Google Cloud Project ID for the content hub. (Required) + CONTENTHUB_LOCATION: Location of the content hub. (Required) + CONTENTHUB_INSTANCE_ID: Instance ID for the content hub. (Required) + + [AI Configuration] + AI_MODEL: The Vertex AI model to use for generation. (Default: "{ai_model}") + + [Input Files] + CUSTOMER_RULES_TO_EVALUATE: Path to the JSON file with customer rules. (Default: "{customer_rules_to_evaluate}") + COMMUNITY_RULES: Path to the text file with all community rules. (Default: "{community_rules}") + + [Preloaded Curated Rules (Optional)] + CURATED_USE_PRELOADED_FILE: Set to "True" to use local files instead of fetching from the API. (Default: "{curated_use_preloaded_file}") + CURATED_RULES_FILE: Path to the preloaded curated rules JSON file. (Default: "{curated_rules_file}") + CURATED_RULESETS_FILE: Path to the preloaded curated rulesets JSON file. (Default: "{curated_rulesets_file}") + + [Output Files] + CURATED_RULES_OUTPUT_FILE: Where to save fetched curated rules. (Default: "{curated_rules_output_file}") + CURATED_RULESETS_OUTPUT_FILE: Where to save fetched curated rulesets. (Default: "{curated_rulesets_output_file}") + RECOMMENDATIONS_JSON_OUTPUT_FILE: Path for the final JSON recommendations. (Default: "{recommendations_json_output_file}") + RECOMMENDATIONS_CSV_OUTPUT_FILE: Path for the final CSV recommendations. (Default: "{recommendations_csv_output_file}") +""" + print(help_text) + + +if __name__ == "__main__": + + # Check if the --help flag is provided + if "--help" in sys.argv: + print_help() + sys.exit(0) + + # load from secops or file and save curated rules + if curated_use_preloaded_file == "True": + with open(curated_rules_file, 'r') as f: + all_curated_rules = json.load(f) + print( + f"\nSuccessfully loaded curated rule form file {curated_rules_file}" + ) + # Corrected variable name from curated_rulesets_files to curated_rulesets_file + with open(curated_rulesets_file, 'r') as f: + all_curated_rulesets = json.load(f) + print( + f"\nSuccessfully loaded curated ruleset form file {curated_rulesets_file}" + ) + else: + all_curated_rules, all_curated_rulesets = load_curated_rules_description( + ) + + with open(curated_rules_output_file, 'w', encoding='utf-8') as f: + json.dump(all_curated_rules, f, indent=2) + print( + f"\nSuccessfully curated rules saved to {curated_rules_output_file}" + ) + + with open(curated_rulesets_output_file, 'w', encoding='utf-8') as f: + json.dump(all_curated_rulesets, f, indent=2) + print( + f"\nSuccessfully curated rulesets saved to {curated_rulesets_output_file}" + ) + + # make recommendation + print("Start processing") + recommendation_curated_community = [] + + # load rules + with open(customer_rules_to_evaluate, 'r') as f: + customer_rules = json.load(f) + print(f"Successfully loaded data from {customer_rules_to_evaluate}") + + with open(community_rules, 'r') as f: + all_community_rules = f.read() + print( + f"\nSuccessfully loaded community rules form file {community_rules}" + ) + + # Enrich the input rules with the sources + unique_log_types = secops_resources_helper.get_unique_log_sources( + all_curated_rulesets) + customer_rules_with_log_sources = ai_helper.find_log_sources_needed( + customer_rules, unique_log_types) + print("Logs sources identified") + + import time + + def call_with_backoff(func, *args, max_retries=5, base_delay=2): + """Calls a function with exponential backoff on failure to handle rate limits.""" + delay = base_delay + for attempt in range(max_retries): + try: + return func(*args) + except Exception as e: + if attempt == max_retries - 1: + raise + print( + f" Rate limit or error encountered ({e}). Retrying in {delay}s..." + ) + time.sleep(delay) + delay *= 2 + + for i, rule in enumerate(customer_rules): + try: + print(f"Start working on rule ucid:{rule['ucid']}") + rule_str = json.dumps(rule) + curated_filtered = secops_resources_helper.filter_curated_rules_log_source( + customer_rules_with_log_sources[i], all_curated_rules) + + print(" Evaluating curated rules...") + curated_sugg_str = call_with_backoff( + ai_helper.generate_curated_rules_recommendation, rule_str, + curated_filtered) + curated_sugg = json.loads(curated_sugg_str) + + print(" Evaluating community rules...") + community_sugg_str = call_with_backoff( + ai_helper.generate_community_rules_recommendation, rule_str, + all_community_rules) + community_sugg = json.loads(community_sugg_str) + + # Merge results for the CSV/JSON output + combined_suggestion = {**curated_sugg, **community_sugg} + recommendation_curated_community.append(combined_suggestion) + + except Exception as e: + print(f"Erorr on rule #{i}, content{rule}") + print(e) + + print(f"Processed {i+1}/{len(customer_rules)}") + + # with open("recommendations_json_output_file", 'r') as f: + # recommendation_curated_community = json.load(f) + + print("Finshed processing") + + # Saving to files + secops_resources_helper.write_results_file( + recommendation_curated_community, recommendations_json_output_file, + recommendations_csv_output_file, + recommendations_ruleset_csv_output_file) diff --git a/blueprints/secops-ai-migration-helper/recommender_curated_community/requirements.txt b/blueprints/secops-ai-migration-helper/recommender_curated_community/requirements.txt new file mode 100644 index 0000000..3ac45cd --- /dev/null +++ b/blueprints/secops-ai-migration-helper/recommender_curated_community/requirements.txt @@ -0,0 +1,20 @@ +# coding=utf-8 +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +google-auth +google-genai +requests +secops +google-cloud-aiplatform \ No newline at end of file diff --git a/blueprints/secops-ai-migration-helper/recommender_curated_community/resources/all_community_rules_20250816.txt b/blueprints/secops-ai-migration-helper/recommender_curated_community/resources/all_community_rules_20250816.txt new file mode 100644 index 0000000..be68c3b --- /dev/null +++ b/blueprints/secops-ai-migration-helper/recommender_curated_community/resources/all_community_rules_20250816.txt @@ -0,0 +1,15448 @@ +Title: SecOps community rules +Description: This file conntains all SecOps community rules in YARAL format. Concatinanted in one file l +Format: YARAL defintion +State: 14.08.2025 +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule adfs_dkm_key_access { + + meta: + author = "Google Cloud Security" + description = "Detects access to the AD contact object to read the AD FS DKM (distributed key manager) master key value" + rule_id = "mr_2517eaa0-0915-4a9e-8ca2-abce955eb635" + rule_name = "ADFS DKM Key Access" + reference = "https://github.com/OTRF/BHEU22-ADFS/blob/main/Slide-Deck.pdf" + type = "alert" + mitre_attack_tactic = "Credential Access" + mitre_attack_technique = "Unsecured Credentials: Private Keys" + mitre_attack_url = "https://attack.mitre.org/techniques/T1552/004/" + mitre_attack_version = "v14.1" + platform = "Windows" + data_source = "windows security events" + severity = "High" + priority = "High" + + events: + $object.metadata.event_type = "USER_RESOURCE_ACCESS" + $object.metadata.product_name = "Microsoft-Windows-Security-Auditing" + $object.metadata.vendor_name = "Microsoft" + $object.metadata.product_event_type = "4662" + any $object.security_result.detection_fields.value = "properties:{8d3bca50-1d7e-11d0-a081-00aa006c33ed}" + $object.principal.labels["SubjectLogonId"] = $subject + + $login.metadata.event_type = "USER_LOGIN" + $login.metadata.product_name = "Microsoft-Windows-Security-Auditing" + $login.metadata.vendor_name = "Microsoft" + $login.metadata.product_event_type = "4624" + $login.target.labels["TargetLogonId"] = $subject + $login.principal.hostname = $hostname + + match: + $hostname over 5m + + outcome: + $risk_score = 85 + $mitre_attack_tactic = "Credential Access" + $mitre_attack_technique = "Unsecured Credentials: Private Keys" + $mitre_attack_technique_id = array_distinct("T1552.004") + //added to populate alert graph with additional context + //Commented out because it is the same as the match variable, if match variable changes, uncomment to use + //$principal_hostname = array_distinct($logon.principal.hostname) + $object_principal_process_pid = array_distinct($object.principal.process.pid) + $object_principal_user_userid = array_distinct($object.principal.user.userid) + //$principal_user_windows_sid = array_distinct($object.principal.user.windows_sid) + $object_target_resource_name = array_distinct($object.target.resource.name) + + condition: + $object and $login +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule adfs_db_suspicious_named_pipe_connection { + + meta: + author = "Google Cloud Security" + description = "Connection to ADFS via named pipes that are not using specific Windows ADFS processes may be indicative of user attempting to access ADFS for suspicious purposes" + rule_id = "mr_a25913a1-65be-4cb5-b0de-6858dd04ac99" + rule_name = "ADFS DB Suspicious Named Pipe Connection" + reference = "https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Windows%20Security%20Events/Analytic%20Rules/ADFSDBNamedPipeConnection.yaml" + type = "alert" + platform = "Windows" + data_source = "sysmon" + severity = "Medium" + priority = "Medium" + + events: + $process.metadata.event_type = "PROCESS_UNCATEGORIZED" + $process.metadata.product_event_type = "18" + $process.metadata.product_name = "Microsoft-Windows-Sysmon" + not re.regex($process.target.process.file.full_path, `Microsoft.Identity.Health.Adfs.PshSurrogate.exe|Microsoft.IdentityServer.ServiceHost.exe|AzureADConnect.exe|Microsoft.Tri.Sensor.exe|wsmprovhost.exe|mmc.exe|sqlservr.exe|sqlwriter.exe`) nocase + $process.target.resource.name = "\\MICROSOFT##WID\\tsql\\query" nocase + /* + If you have a listing of ADFS servers, you can use a reference list or enumerate them in the field below. + Alternatively, if ADFS servers are grouped in an asset attribute, that attribute could be used instead. + */ + $process.principal.hostname = /adfs/ nocase + $process.principal.hostname = $hostname + + match: + $hostname over 5m + + outcome: + $risk_score = 65 + $event_count = count_distinct($process.metadata.id) + $security_summary = array_distinct($process.security_result.summary) + $target_process_parent_process_command_line = array_distinct($process.target.process.parent_process.command_line) + //added to populate alert graph with additional context + //Commented out because it is the same as the match variable, if match variable changes, uncomment to use + //$principal_hostname = array_distinct($process.principal.hostname) + $principal_user_userid = array_distinct($process.principal.user.userid) + $target_process_pid = array_distinct($process.target.process.pid) + $target_process_command_line = array_distinct($process.target.process.command_line) + $target_process_file_sha256 = array_distinct($process.target.process.file.sha256) + $target_process_file_full_path = array_distinct($process.target.process.file.full_path) + $target_process_product_specific_process_id = array_distinct($process.target.process.product_specific_process_id) + $target_process_parent_product_specific_process_id = array_distinct($process.target.process.parent_process.product_specific_process_id) + $target_resource_name = array_distinct($process.target.resource.name) + + condition: + $process +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule o365_onedrive_anonymous_filedownload { + + meta: + author = "Google Cloud Security" + description = "Anonymous links can be used to export files from OneDrive. While this isn't always a sign of malicious activity, some organizations do not support the use of anonymous links because of the risk of data leakage. This rule detects when anonymous links are used to download files from OneDrive." + rule_id = "mr_f713e2b0-31b1-4165-8764-59a5e2c5eabb" + rule_name = "O365 OneDrive Anonymous File Downloaded" + mitre_attack_tactic = "Exfiltration" + mitre_attack_technique = "Exfiltration Over Alternative Protocol: Exfiltration Over Asymmetric Encrypted Non-C2 Protocol" + mitre_attack_url = "https://attack.mitre.org/techniques/T1048/002/" + mitre_attack_version = "v14.1" + type = "hunt" + platform = "azure" + data_source = "o365" + severity = "Medium" + priority = "Medium" + + events: + $file.metadata.event_type = "USER_RESOURCE_UPDATE_CONTENT" + $file.metadata.product_event_type = "FileDownloaded" + $file.metadata.product_name = "Office 365" + $file.metadata.vendor_name = "Microsoft" + $file.target.application = "OneDrive" + ( + $file.principal.user.userid = /^urn:spo:anon#/ or + $file.principal.user.userid = "anonymous" + ) + $file.principal.ip = $ip + + match: + $ip over 5m + + outcome: + $risk_score = 35 + $mitre_attack_tactic = "Exfiltration" + $mitre_attack_technique = "Exfiltration Over Alternative Protocol: Exfiltration Over Asymmetric Encrypted Non-C2 Protocol" + $mitre_attack_technique_id = "T1048.002" + $event_count = count_distinct($file.metadata.id) + $referral_url = array_distinct($file.network.http.referral_url) + $user_agent = array_distinct($file.network.http.user_agent) + $principal_application = array_distinct($file.principal.application) + $principal_ip = array_distinct($file.principal.ip) + $target_application = array_distinct($file.target.application) + //$principal_user_email_address = array_distinct(principal.user.email_addresses) + $principal_user_userid = array_distinct($file.principal.user.userid) + $src_file_full_path = array_distinct($file.src.file.full_path) + $src_url = array_distinct($file.src.url) + + condition: + $file +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule o365_recently_created_entra_id_user_assigned_roles { + + meta: + author = "Google Cloud Security" + description = "Detects when a user is created in Entra ID and assigned roles within a defined time window." + rule_id = "mr_c0406a96-4ed1-4dd2-9629-aa5a2c881222" + rule_name = "O365 Recently Created Entra ID User Assigned Roles" + mitre_attack_tactic = "Persistence" + mitre_attack_technique = "Account Manipulation: Additional Cloud Roles" + mitre_attack_url = "https://attack.mitre.org/techniques/T1098/003/" + mitre_attack_version = "v14.1" + assumption = "The list msgraph_watchlist_roles is populated with role names, ie Application Administrator" + type = "alert" + platform = "azure" + data_source = "o365" + severity = "Medium" + priority = "Medium" + + events: + ( + $create.metadata.event_type = "USER_CREATION" and + $create.metadata.product_event_type = "Add user." and + $create.metadata.product_name = "Office 365" and + $create.security_result.action = "ALLOW" and + $create.target.user.userid = $userid + ) + $create.metadata.event_timestamp.seconds < $role.metadata.event_timestamp.seconds + ( + $role.metadata.event_type = "USER_UNCATEGORIZED" and + $role.metadata.product_event_type = "Add member to role." and + $role.metadata.product_name = "Office 365" and + $role.security_result.action = "ALLOW" and + //The reference list msgraph_watchlist_roles matches on the role name. List contents example row: Global Administrator //manage all aspects of Azure AD and Microsoft services that use Azure AD identities 62e90394-69f5-4237-9190-012177145e10 + //If you wanted to detect on specific roles, they could be added to a reference list and the following line uncommented + //$role.target.resource.attribute.roles.name in %msgraph_watchlist_roles and + $role.target.user.userid = $userid + ) + + match: + $userid over 90m + + outcome: + $risk_score = max(if($role.target.resource.attribute.roles.name = /Administrator/ nocase, 85, 35)) + $mitre_attack_tactic = "Persistence" + $mitre_attack_technique = "Account Manipulation: Additional Cloud Roles" + $mitre_attack_technique_id = "T1098.003" + $security_summary = array_distinct($role.security_result.summary) + $user_agent = array_distinct($role.network.http.user_agent) + $assigned_role = array_distinct($role.target.resource.attribute.roles.name) + //added to populate alert graph with additional context + $principal_user_userid = array_distinct($create.principal.user.userid) + //Excluded since it is already being used as match variable + //$target_user_userid = array_distinct($create.target.user.userid) + + condition: + $create and $role +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule o365_onedrive_anonymous_link_accessed { + + meta: + author = "Google Cloud Security" + description = "Anonymous links can be used to access files from OneDrive. While this isn't always a sign of malicious activity, some organizations do not support the use of anonymous links because of the risk of data leakage. This rule detects when anonymous links are used to access files from OneDrive." + rule_id = "mr_7e67005a-d5fc-4497-8e81-e6797b2f54e9" + rule_name = "O365 OneDrive Anonymous Link Accessed" + //This rule addresses link access and not downloading. Some overlap between anonymous file download and anonymous link accessed rules are expected and combining them or tuning them is suggested. + mitre_attack_tactic = "Exfiltration" + mitre_attack_technique = "Exfiltration Over Alternative Protocol: Exfiltration Over Asymmetric Encrypted Non-C2 Protocol" + mitre_attack_url = "https://attack.mitre.org/techniques/T1048/002/" + mitre_attack_version = "v14.1" + type = "hunt" + platform = "azure" + data_source = "o365" + severity = "Medium" + priority = "Medium" + + events: + $file.metadata.event_type = "USER_RESOURCE_ACCESS" + $file.metadata.product_event_type = "AnonymousLinkUsed" + $file.metadata.product_name = "Office 365" + $file.metadata.vendor_name = "Microsoft" + $file.target.application = "OneDrive" + ( + $file.principal.user.userid = /^urn:spo:anon#/ or + $file.principal.user.userid = "anonymous" + ) + $file.principal.ip = $ip + + match: + $ip over 5m + + outcome: + $risk_score = 35 + $mitre_attack_tactic = "Exfiltration" + $mitre_attack_technique = "Exfiltration Over Alternative Protocol: Exfiltration Over Asymmetric Encrypted Non-C2 Protocol" + $mitre_attack_technique_id = "T1048.002" + $event_count = count_distinct($file.metadata.id) + $referral_url = array_distinct($file.network.http.referral_url) + $user_agent = array_distinct($file.network.http.user_agent) + $principal_application = array_distinct($file.principal.application) + $principal_ip = array_distinct($file.principal.ip) + $target_application = array_distinct($file.target.application) + $principal_user_userid = array_distinct($file.principal.user.userid) + $target_file_full_path = array_distinct($file.target.file.full_path) + $target_url = array_distinct($file.target.url) + + condition: + $file +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule o365_add_user_to_admin_role { + + meta: + author = "Google Cloud Security" + description = "Adding users to administrative roles is not malicious, but due to the sensitivity of certain roles, validation should occur when this occurs" + rule_id = "mr_ee28c257-d2c7-490c-addf-aef35d07f29d" + rule_name = "O365 Add User To Admin Role" + assumption = "The list msgraph_watchlist_roles is populated with role names, example: Application Administrator" + mitre_attack_tactic = "Persistence" + mitre_attack_technique = "Account Manipulation: Additional Cloud Roles" + mitre_attack_url = "https://attack.mitre.org/techniques/T1098/003/" + mitre_attack_version = "v14.1" + type = "alert" + platform = "azure" + data_source = "o365" + severity = "Medium" + priority = "Medium" + + events: + $app.metadata.event_type = "USER_UNCATEGORIZED" + $app.metadata.product_event_type = "Add member to role." + $app.metadata.product_name = "Office 365" + $app.metadata.vendor_name = "Microsoft" + $app.security_result.action = "ALLOW" + $app.target.resource.attribute.roles.name in %msgraph_watchlist_roles + $app.principal.user.userid = $userid + + match: + $userid over 5m + + outcome: + $risk_score = 65 + $mitre_attack_tactic = "Persistence" + $mitre_attack_technique = "Account Manipulation: Additional Cloud Roles" + $mitre_attack_technique_id = "T1098.003" + $event_count = count_distinct($app.metadata.id) + $security_summary = array_distinct($app.security_result.summary) + $user_agent = array_distinct($app.network.http.user_agent) + $assigned_role = array_distinct($app.target.resource.attribute.roles.name) + //added to populate alert graph with additional context + //$principal_user_userid = array_distinct($app.principal.user.userid) + $target_user_userid = array_distinct($app.target.user.userid) + + condition: + $app +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule o365_ADPowerShell_app_login_subsequent_activity { + + meta: + author = "Google Cloud Security" + description = "Once a user authenticates to the Azure AD PowerShell application, if they take multiple admin actions indicative of establishing their own persistence with an Entra ID application within a portion of the access token time, alert for additional investigation" + rule_id = "mr_2d781f34-05f3-43aa-b5ec-257c03787a66" + rule_name = "O365 AD PowerShell App Login Subsequent Activity" + assumption = "This does not take into account attempts that were blocked, just any logging of attempts for any of these actions" + mitre_attack_tactic = "Persistence" + mitre_attack_technique = "Account Manipulation: Additional Cloud Credentials" + mitre_attack_url = "https://attack.mitre.org/techniques/T1098/001/" + mitre_attack_version = "v14.1" + type = "alert" + platform = "azure" + data_source = "o365" + severity = "Medium" + priority = "Medium" + + events: + ( + $login.metadata.event_type = "USER_LOGIN" and + $login.metadata.product_event_type = "UserLoggedIn" and + $login.metadata.product_name = "Office 365" and + $login.metadata.vendor_name = "Microsoft" and + $login.target.resource.product_object_id = "1b730954-1685-4b74-9bfd-dac224a7b894" and + $login.security_result.action = "ALLOW" + ) + $login.target.user.userid = $userid + $login.metadata.event_timestamp.seconds < $other.metadata.event_timestamp.seconds + ( + ( + $other.metadata.event_type = "USER_RESOURCE_CREATION" and + $other.metadata.product_event_type = "Add application." and + $other.metadata.product_name = "Office 365" and + $other.metadata.vendor_name = "Microsoft" + ) + or + ( + $other.metadata.event_type = "USER_RESOURCE_UPDATE_CONTENT" and + $other.metadata.product_event_type = "Update application." and + $other.metadata.product_name = "Office 365" and + $other.metadata.vendor_name = "Microsoft" + ) + or + ( + $other.metadata.event_type = "USER_RESOURCE_UPDATE_PERMISSIONS" and + $other.metadata.product_event_type = "Add delegated permission grant." and + $other.metadata.product_name = "Office 365" and + $other.metadata.vendor_name = "Microsoft" + ) + or + ( + $other.metadata.event_type = "USER_RESOURCE_UPDATE_CONTENT" and + $other.metadata.product_event_type = /Update application.*Certificates and secrets management/ nocase and + $other.metadata.product_name = "Office 365" and + $other.metadata.vendor_name = "Microsoft" + ) + ) + $other.principal.user.userid = $userid + $other.metadata.product_event_type = $other_event + + match: + $userid over 90m + + outcome: + $risk_score = max(if($other.metadata.product_event_type = "Add application.", 10, 0) + + if($other.metadata.product_event_type = "Update application.", 10, 0) + + if($other.metadata.product_event_type = "Add delegated permission grant.", 10, 0) + + if($other.metadata.product_event_type = /Update application.*Certificates and secrets management/ nocase, 55, 0)) + $mitre_attack_tactic = "Persistence" + $mitre_attack_technique = "Account Manipulation: Additional Cloud Credentials" + $mitre_attack_technique_id = "T1098.001" + $subsequent_action_threshold = 1 + $product_event_type = array_distinct($other.metadata.product_event_type) + $country_region_login_attempt = array_distinct($login.principal.ip_geo_artifact.location.country_or_region) + //added to populate alert graph with additional context + $principal_ip = array_distinct($login.principal.ip) + //$principal_user_userid = array_distinct($other.principal.user.userid) + $target_resource_name = array_distinct($other.target.resource.name) + + condition: + $login and #other_event > 0 +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule o365_login_activity_to_azure_ad_powershell_app { + + meta: + author = "Google Cloud Security" + description = "Logins to Azure AD PowerShell app can have legitimate purposes, but are also abused to gain access to user information. Programmatic access to Entra ID (Azure AD) should generally be through apps, so reviewing these activities is needed." + rule_id = "mr_0cc56eaf-4176-444d-874d-9780bbb29d4f" + rule_name = "O365 Login Activity To Azure AD PowerShell App" + mitre_attack_tactic = "Initial Access" + mitre_attack_technique = "Valid Accounts: Cloud Accounts" + mitre_attack_url = "https://attack.mitre.org/techniques/T1078/004/" + mitre_attack_version = "v14.1" + type = "hunt" + platform = "azure" + data_source = "o365" + severity = "Medium" + priority = "Medium" + + events: + $login.metadata.event_type = "USER_LOGIN" + $login.metadata.product_event_type = "UserLoggedIn" + $login.metadata.product_name = "Office 365" + $login.metadata.vendor_name = "Microsoft" + $login.target.resource.product_object_id = "1b730954-1685-4b74-9bfd-dac224a7b894" + $login.security_result.action = "ALLOW" + + // Below filters ADFS Sync Account that runs every 30 minutes between AD and Entra ID (for federated environments); can use display name or email address + //$login.target.user.userid != "insert your email address here" and + //$login.target.user.user_display_name != "On-Premises Directory Synchronization Service Account" + $login.target.user.userid = $userid + + match: + $userid over 5m + + outcome: + $risk_score = 65 + $mitre_attack_tactic = "Initial Access" + $mitre_attack_technique = "Valid Accounts: Cloud Accounts" + $mitre_attack_technique_id = "T1078.004" + $event_count = count_distinct($login.metadata.id) + $security_summary = array_distinct($login.security_result.summary) + $user_agent = array_distinct($login.network.http.user_agent) + $country_region_login_attempt = array_distinct($login.principal.ip_geo_artifact.location.country_or_region) + //added to populate alert graph with additional context + $principal_ip = array_distinct($login.principal.ip) + //$target_user_email_addresses = array_distinct($login.target.user.email_addresses) + //$target_user_userid = array_distinct($login.target.user.userid) + + condition: + $login +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule o365_entra_id_client_secret_add_update_delete_in_app { + + meta: + author = "Google Cloud Security" + description = "Secrets added to applications have legitimate purposes, but can also be a method of persistence. This alert will trigger on creation, modification or delete of a client secret" + rule_id = "mr_24ac7907-9d86-4089-901c-61f8ff1e7730" + rule_name = "O365 Entra ID App Client Secret Added, Updated or Deleted" + mitre_attack_tactic = "Persistence" + mitre_attack_technique = "Account Manipulation: Additional Cloud Credentials" + mitre_attack_url = "https://attack.mitre.org/techniques/T1098/001/" + mitre_attack_version = "v14.1" + type = "alert" + platform = "azure" + data_source = "o365" + severity = "Medium" + priority = "Medium" + + events: + $app.metadata.event_type = "USER_RESOURCE_UPDATE_CONTENT" + $app.metadata.product_name = "Office 365" + $app.metadata.product_event_type = /Update application.*Certificates and secrets management/ + $app.metadata.vendor_name = "Microsoft" + $app.security_result.action = "ALLOW" + $app.principal.user.userid = $userid + + match: + $userid over 5m + + outcome: + $risk_score = 65 + $mitre_attack_tactic = "Persistence" + $mitre_attack_technique = "Account Manipulation: Additional Cloud Credentials" + $mitre_attack_technique_id = "T1098.001" + $event_count = count_distinct($app.metadata.id) + $security_summary = array_distinct($app.security_result.summary) + $user_agent = array_distinct($app.network.http.user_agent) + $target_entra_id_application = array_distinct(re.capture($app.network.http.user_agent,`\"AppId\":\"(.*)`)) + //added to populate alert graph with additional context + //$principal_user_userid = array_distinct($app.principal.user.userid) + + condition: + $app +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule o365_entra_id_app_modify_permission_change_on_watchlist { + + meta: + author = "Google Cloud Security" + description = "Alerts when a permission on the watchlist is applied to an Entra ID application." + rule_id = "mr_678cafb8-ea1f-42ac-a396-238bc35e4d21" + rule_name = "O365 Entra ID App Modify Permission Change On Watchlist" + reference = "https://learn.microsoft.com/en-us/graph/permissions-reference" + assumption = "The list msgraph_watchlist_permissions is populated as needed with guid permissions Example: 024d486e-b451-40bb-833d-3e66d98c5c73 //Mail.Read.Write" + type = "alert" + platform = "azure" + data_source = "o365" + severity = "Medium" + priority = "Medium" + + events: + $app.metadata.event_type = "USER_RESOURCE_UPDATE_CONTENT" + $app.metadata.product_name = "Office 365" + $app.metadata.product_event_type = "Update application." + $app.metadata.vendor_name = "Microsoft" + $app.security_result.action = "ALLOW" + ( + $app.target.resource.attribute.labels.key = /NewValue_EntitlementId-/ or + $app.target.resource.attribute.labels.key = /OldValue_EntitlementId-/ + ) + $app.security_result.detection_fields["target_1"] = $app_name + + match: + $app_name over 5m + + outcome: + $risk_score = 65 + $event_count = count_distinct($app.metadata.id) + $security_summary = array_distinct($app.security_result.summary) + $user_agent = array_distinct($app.network.http.user_agent) + //The reference list msgraph_watchlist_permissions matches on the GUID. List contents example row: 6aedf524-7e1c-45a7-bd76-ded8cab8d0fc //SecurityEvents.ReadWrite.All + $watchlist_permissions_after_modification = array_distinct(if($app.target.resource.attribute.labels.key = /NewValue_EntitlementId/ and $app.target.resource.attribute.labels.value IN %msgraph_watchlist_permissions, $app.target.resource.attribute.labels.value,"")) + $watchlist_permissions_before_modification = array_distinct(if($app.target.resource.attribute.labels.key = /OldValue_EntitlementId/ and $app.target.resource.attribute.labels.value IN %msgraph_watchlist_permissions, $app.target.resource.attribute.labels.value,"")) + $permissions_after_modification = array_distinct(if($app.target.resource.attribute.labels.key = /NewValue_EntitlementId/ and $app.target.resource.attribute.labels.value !="", $app.target.resource.attribute.labels.value,"")) + $permissions_before_modification = array_distinct(if($app.target.resource.attribute.labels.key = /OldValue_EntitlementId/ and $app.target.resource.attribute.labels.value !="", $app.target.resource.attribute.labels.value,"")) + $total_permissions_after_modification = count_distinct(if($app.target.resource.attribute.labels.key = /NewValue_EntitlementId/ and $app.target.resource.attribute.labels.value !="", $app.target.resource.attribute.labels.value, "")) - 1 + $total_permissions_before_modification = count_distinct(if($app.target.resource.attribute.labels.key = /OldValue_EntitlementId/ and $app.target.resource.attribute.labels.value !="", $app.target.resource.attribute.labels.value, "")) - 1 + //added to populate alert graph with additional context + $principal_user_userid = array_distinct($app.principal.user.userid) + + condition: + $app +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule o365_persistent_login_activity_to_azure_ADPowerShell_app { + + meta: + author = "Google Cloud Security" + description = "Continual logins to Azure AD PowerShell app are not a security best practice, if this is observed, additional investigation is needed" + rule_id = "mr_4e61ae7f-d9fc-4c2a-b086-69d9d50dc5cc" + rule_name = "O365 Persistent Login Activity To Azure AD PowerShell App" + mitre_attack_tactic = "Lateral Movement" + mitre_attack_technique = "Remote Services: Cloud Services" + mitre_attack_url = "https://attack.mitre.org/techniques/T1021/007/" + mitre_attack_version = "v14.1" + type = "alert" + platform = "azure" + data_source = "o365" + severity = "Medium" + priority = "Medium" + + events: + $login.metadata.event_type = "USER_LOGIN" + $login.metadata.product_event_type = "UserLoggedIn" + $login.metadata.product_name = "Office 365" + $login.metadata.vendor_name = "Microsoft" + $login.target.resource.product_object_id = "1b730954-1685-4b74-9bfd-dac224a7b894" + $login.security_result.action = "ALLOW" + $login.target.user.userid = $userid + $login.metadata.event_timestamp.seconds = $time + + match: + $userid over 24h + + outcome: + $risk_score = 65 + $mitre_attack_tactic = "Lateral Movement" + $mitre_attack_technique = "Remote Services: Cloud Services" + $mitre_attack_technique_id = "T1021.007" + $event_count = count_distinct($login.metadata.id) + $entra_id_login_threshold = 2 + $security_summary = array_distinct($login.security_result.summary) + $user_agent = array_distinct($login.network.http.user_agent) + $country_region_login_attempt = array_distinct($login.principal.ip_geo_artifact.location.country_or_region) + //added to populate alert graph with additional context + $principal_ip = array_distinct($login.principal.ip) + //$target_user_email_addresses = array_distinct($login.target.user.email_addresses) + //$target_user_userid = array_distinct($login.target.user.userid) + + condition: + // Can set based on your own threshold + #time > 1 +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule o365_entra_id_application_creation { + + meta: + author = "Google Cloud Security" + description = "Application creation is a legitimate activity but doesn't occur frequently. Alerts when a new application is created in Entra ID (formerly Azure AD)." + rule_id = "mr_c8daf9ab-2b39-46cc-bda9-7fd1ebb13a81" + rule_name = "O365 Entra ID Application Creation" + type = "alert" + platform = "azure" + data_source = "o365" + severity = "Low" + priority = "Medium" + + events: + $app.metadata.event_type = "USER_RESOURCE_CREATION" + $app.metadata.product_name = "Office 365" + $app.metadata.vendor_name = "Microsoft" + $app.metadata.product_event_type = "Add application." + $app.security_result.action = "ALLOW" + //These events should have a userid associated with them but in case they don't we will match on the app name being created instead + strings.coalesce($app.principal.user.userid, $app.target.resource.name) = $user_or_resource + + match: + $user_or_resource over 5m + + outcome: + $risk_score = 35 + $event_count = count_distinct($app.metadata.id) + $target_application = array_distinct($app.target.application) + $security_summary = array_distinct($app.security_result.summary) + $user_agent = array_distinct($app.network.http.user_agent) + //added to populate alert graph with additional context + $principal_user_userid = array_distinct($app.principal.user.userid) + $target_resource_name = array_distinct($app.target.resource.name) + + condition: + $app +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule o365_login_activity_to_uncommon_mscloud_apps { + + meta: + author = "Google Cloud Security" + description = "This rule detects O365 login activity to apps other than a defined list of first party MS Cloud Apps. Note that Azure Active Directory PowerShell and custom Azure apps are not in this list by default" + rule_id = "mr_eca0cd3d-7d65-47f6-9df2-1a16664819ae" + rule_name = "O365 Login Activity To Uncommon Microsoft Cloud Apps" + assumption = "The list first_party_ms_cloud_apps is populated as needed" + mitre_attack_tactic = "Initial Access" + mitre_attack_technique = "Valid Accounts: Cloud Accounts" + mitre_attack_url = "https://attack.mitre.org/techniques/T1078/004/" + mitre_attack_version = "v14.1" + reference = "https://learn.microsoft.com/en-us/troubleshoot/azure/active-directory/verify-first-party-apps-sign-in" + type = "alert" + platform = "azure" + data_source = "o365" + severity = "Medium" + priority = "Medium" + + events: + $login.metadata.event_type = "USER_LOGIN" + $login.metadata.product_event_type = "UserLoggedIn" + $login.metadata.product_name = "Office 365" + NOT $login.target.resource.product_object_id in %first_party_ms_cloud_apps + /* Additional AppIds that are not in this list but have appeared benign during testing include the following: + 7eadcef8-456d-4611-9480-4fff72b8b9e2 Microsoft Account Controls V2 + 8e0e8db5-b713-4e91-98e6-470fed0aa4c2 Microsoft Azure Signup Portal + f9818e52-50bd-463e-8932-a1650bd3fad2 MSAL Configuration + There are additional lists on GitHub that are compiled that would be added for additional tuning as needed + */ + $login.metadata.vendor_name = "Microsoft" + $login.security_result.action = "ALLOW" + $login.target.user.userid = $userid + + //If you are using ADFS, you may want to consider something like this to filter out Synchronization Login Traffic - Your userid will be different + $login.target.user.userid != /Sync_/ nocase + + match: + $userid over 5m + + outcome: + $risk_score = 65 + $mitre_attack_tactic = "Initial Access" + $mitre_attack_technique = "Valid Accounts: Cloud Accounts" + $mitre_attack_technique_id = "T1078.004" + $event_count = count_distinct($login.metadata.id) + $target_application = array_distinct($login.target.resource.product_object_id) + $security_summary = array_distinct($login.security_result.summary) + $user_agent = array_distinct($login.network.http.user_agent) + $country_region_login_attempt = array_distinct($login.principal.ip_geo_artifact.location.country_or_region) + //added to populate alert graph with additional context + $principal_ip = array_distinct($login.principal.ip) + //$target_user_userid = array_distinct($login.target.user.userid) + + condition: + $login +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule o365_admin_login_activity_to_uncommon_mscloud_apps { + + meta: + author = "Google Cloud Security" + description = "This rule detects O365 login activity to apps other than a defined list of first party MS Cloud Apps. Note that Azure Active Directory PowerShell and custom Azure apps are not in this list by default" + rule_id = "mr_4fa166c8-922a-4dc1-b72d-9bcb2ec7609f" + rule_name = "O365 Admin Login Activity To Uncommon Microsoft Cloud Apps" + assumption = "The lists first_party_ms_cloud_apps and msazure_admin_watchlist are populated as needed" + mitre_attack_tactic = "Initial Access" + mitre_attack_technique = "Valid Accounts: Cloud Accounts" + mitre_attack_url = "https://attack.mitre.org/techniques/T1078/004/" + mitre_attack_version = "v14.1" + reference = "https://learn.microsoft.com/en-us/troubleshoot/azure/active-directory/verify-first-party-apps-sign-in" + type = "alert" + platform = "azure" + data_source = "o365" + severity = "High" + priority = "High" + + events: + $login.metadata.event_type = "USER_LOGIN" + $login.metadata.product_event_type = "UserLoggedIn" + $login.metadata.product_name = "Office 365" + NOT $login.target.resource.product_object_id in %first_party_ms_cloud_apps + $login.metadata.vendor_name = "Microsoft" + $login.security_result.action = "ALLOW" + $login.target.user.userid = $userid + + //Use the criteria below if you want to isolate activity to a specific watchlist of users + //@domain.com is stripped off to reduce the values in the list to just the username of the email address, can apply to userid or email address fields + re.replace($login.target.user.userid, `@.*$`, "") in %msazure_admin_watchlist + + match: + $userid over 5m + + outcome: + $risk_score = 65 + $mitre_attack_tactic = "Initial Access" + $mitre_attack_technique = "Valid Accounts: Cloud Accounts" + $mitre_attack_technique_id = "T1078.004" + $event_count = count_distinct($login.metadata.id) + $target_application = array_distinct($login.target.resource.product_object_id) + $security_summary = array_distinct($login.security_result.summary) + $user_agent = array_distinct($login.network.http.user_agent) + $country_region_login_attempt = array_distinct($login.principal.ip_geo_artifact.location.country_or_region) + //added to populate alert graph with additional context + $principal_ip = array_distinct($login.principal.ip) + //$target_user_userid = array_distinct($login.target.user.userid) + + condition: + $login +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule o365_entra_id_app_permissions_threshold_exceeded { + + meta: + author = "Google Cloud Security" + description = "Detects when an excessive number of permissions are assigned to an Entra ID application within a time window, potentially indicating a greedy permission grab, as a numeric value comparing old permissions to new permissions" + rule_id = "mr_8d1bb5a8-94cf-437c-9754-6046b4ca3549" + rule_name = "O365 Entra ID App Permissions Threshold Exceeded" + assumption = "This rule does not compare the specific permissions of the old and new permissions. Removing 8 permissions and replacing with 8 different permissions would not cause this rule to trigger" + reference = "https://learn.microsoft.com/en-us/graph/permissions-reference" + type = "alert" + platform = "azure" + data_source = "o365" + severity = "Medium" + priority = "Medium" + + events: + $app.metadata.event_type = "USER_RESOURCE_UPDATE_CONTENT" + $app.metadata.product_name = "Office 365" + $app.metadata.product_event_type = "Update application." + $app.metadata.vendor_name = "Microsoft" + $app.security_result.action = "ALLOW" + ( + $app.target.resource.attribute.labels.key = /OldValue_EntitlementId-/ or + $app.target.resource.attribute.labels.key = /NewValue_EntitlementId-/ + ) + $app.security_result.detection_fields["target_1"] = $app_name + + match: + $app_name over 5m + + outcome: + $risk_score = 65 + $event_count = count_distinct($app.metadata.id) + $security_summary = array_distinct($app.security_result.summary) + $user_agent = array_distinct($app.network.http.user_agent) + $old_permissions = array_distinct(if($app.target.resource.attribute.labels.key = /OldValue_EntitlementId-/, $app.target.resource.attribute.labels.value, "")) + $new_permissions = array_distinct(if($app.target.resource.attribute.labels.key = /NewValue_EntitlementId-/, $app.target.resource.attribute.labels.value, "")) + /* + Apps created via the portal come with a permission of user.read, however apps created via the Graph API do not. The first time permissions are added to an app created via the API, + the distinct count for new permissions will be off by one. Subsequent events will reflect the correct counts of old and new permissions. + */ + $old_permissions_count = count_distinct(if($app.target.resource.attribute.labels.key = /OldValue_EntitlementId-/, $app.target.resource.attribute.labels.value, "")) - 1 + $new_permissions_count = count_distinct(if($app.target.resource.attribute.labels.key = /NewValue_EntitlementId-/, $app.target.resource.attribute.labels.value, "")) - 1 + $zero_handler_old = if($old_permissions_count = 0, 1) + $permission_diff = $new_permissions_count - $old_permissions_count + //added to populate alert graph with additional context + $principal_user_userid = array_distinct($app.principal.user.userid) + + condition: + //Define your threshold for the number of permissions to be exceeded to trigger + $app and $permission_diff > 8 +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule o365_onedrive_anonymous_link_created_updated { + + meta: + author = "Google Cloud Security" + description = "Anonymous links can be used to export files from OneDrive. While this isn't always a sign of malicious activity, some organizations do not support the creation of anonymous links because of the risk of data leakage. This rule detects the creation and modification of anonymous links in OneDrive." + rule_id = "mr_3e2572c1-cc14-4c2b-b60b-434db1b0f4ae" + rule_name = "O365 OneDrive Anonymous Link Created Updated" + type = "hunt" + platform = "azure" + data_source = "o365" + severity = "Medium" + priority = "Medium" + + events: + ( + ( + $file.metadata.event_type = "USER_RESOURCE_CREATION" and + $file.metadata.product_event_type = "AnonymousLinkCreated" + ) + or + ( + $file.metadata.event_type = "STATUS_UPDATE" and + $file.metadata.product_event_type = "AnonymousLinkUpdated" + ) + ) + $file.metadata.product_name = "Office 365" + $file.metadata.vendor_name = "Microsoft" + $file.target.application = "OneDrive" + $file.principal.user.userid = $user + + match: + $user over 5m + + outcome: + $risk_score = 35 + $event_count = count_distinct($file.metadata.id) + $referral_url = array_distinct($file.network.http.referral_url) + $user_agent = array_distinct($file.network.http.user_agent) + $principal_application = array_distinct($file.principal.application) + //The IP address is a Microsoft IP address not the individual who created or modified the link, commenting it out for this reason + //$principal_ip = array_distinct($file.principal.ip) + $target_application = array_distinct($file.target.application) + //$principal_user_email_address = array_distinct(principal.user.email_addresses) + //$principal_user_userid = array_distinct($file.principal.user.userid) + $target_file_full_path = array_distinct($file.target.file.full_path) + $target_url = array_distinct($file.target.url) + + condition: + $file +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule o365_entra_id_app_permissions_percent_threshold_exceeded { + + meta: + author = "Google Cloud Security" + description = "Detects when an excessive number of permissions are assigned to an Entra ID application within a time window, potentially indicating a greedy permission grab, as a percentage from old permissions to new permissions" + rule_id = "mr_6dcdb335-0054-46ae-a742-ecf6ac4e442b" + rule_name = "O365 Entra ID App Permissions Percent Threshold Exceeded" + assumption = "This rule does not compare the specific permissions of the old and new permissions. Removing 8 permissions and replacing with 8 different permissions would not cause this rule to trigger" + reference = "https://learn.microsoft.com/en-us/graph/permissions-reference" + type = "alert" + platform = "azure" + data_source = "o365" + severity = "Medium" + priority = "Medium" + + events: + $app.metadata.event_type = "USER_RESOURCE_UPDATE_CONTENT" + $app.metadata.product_name = "Office 365" + $app.metadata.product_event_type = "Update application." + $app.metadata.vendor_name = "Microsoft" + $app.security_result.action = "ALLOW" + ( + $app.target.resource.attribute.labels.key = /OldValue_EntitlementId-/ or + $app.target.resource.attribute.labels.key = /NewValue_EntitlementId-/ + ) + $app.security_result.detection_fields["target_1"] = $app_name + + match: + $app_name over 5m + + outcome: + $risk_score = 65 + $event_count = count_distinct($app.metadata.id) + $security_summary = array_distinct($app.security_result.summary) + $user_agent = array_distinct($app.network.http.user_agent) + $old_permissions = array_distinct(if($app.target.resource.attribute.labels.key = /OldValue_EntitlementId-/, $app.target.resource.attribute.labels.value, "")) + $new_permissions = array_distinct(if($app.target.resource.attribute.labels.key = /NewValue_EntitlementId-/, $app.target.resource.attribute.labels.value, "")) + /* + Apps created via the portal come with a permission of user.read, however apps created via the Graph API do not. The first time permissions are added to an app created via the API, + the distinct count for new permissions will be off by one. Subsequent events will reflect the correct counts of old and new permissions. + */ + $old_permissions_count = count_distinct(if($app.target.resource.attribute.labels.key = /OldValue_EntitlementId-/, $app.target.resource.attribute.labels.value, "")) - 1 + $new_permissions_count = count_distinct(if($app.target.resource.attribute.labels.key = /NewValue_EntitlementId-/, $app.target.resource.attribute.labels.value, "")) - 1 + //calculate the difference between the old and new permissions within the match window + $old_permission_zero_handler = if($old_permissions_count = 0, 1, $old_permissions_count) + $permission_change_percentage = (($new_permissions_count - $old_permission_zero_handler) / $old_permission_zero_handler) * 100 + //added to populate alert graph with additional context + $principal_user_userid = array_distinct($app.principal.user.userid) + + condition: + $app and $permission_change_percentage > 70 +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule rw_mimikatz_T1003 { + + meta: + author = "Google Cloud Security" + description = "Detects the process mimikatz being issued from the command line." + rule_id = "mr_fa96ead4-7f1f-4dbb-bacb-a526f985c12f" + rule_name = "MITRE ATT&CK T1003 RW Mimikatz" + mitre_attack_tactic = "Credential Access" + mitre_attack_technique = "OS Credential Dumping" + mitre_attack_url = "https://attack.mitre.org/techniques/T1003/" + mitre_attack_version = "v13.1" + type = "alert" + platform = "Windows" + data_source = "microsoft sysmon, microsoft windows events" + severity = "Critical" + priority = "High" + + events: + $process.metadata.event_type = "PROCESS_LAUNCH" + $process.metadata.event_type = $event_type + $process.target.process.command_line = /mimikatz/ nocase + + match: + $event_type over 5m + + outcome: + $risk_score = max(95) + $mitre_attack_tactic = array_distinct("Credential Access") + $mitre_attack_technique = array_distinct("OS Credential Dumping") + $mitre_attack_technique_id = array_distinct("T1003") + $event_count = count_distinct($process.metadata.id) + // added to populate alert graph with additional context + $principal_hostname = array_distinct($process.principal.hostname) + $principal_process_pid = array_distinct($process.principal.process.pid) + $principal_process_command_line = array_distinct($process.principal.process.command_line) + $principal_process_file_sha256 = array_distinct($process.principal.process.file.sha256) + $principal_process_file_full_path = array_distinct($process.principal.process.file.full_path) + $principal_process_product_specific_process_id = array_distinct($process.principal.process.product_specific_process_id) + $principal_process_parent_process_product_specific_process_id = array_distinct($process.principal.process.parent_process.product_specific_process_id) + $target_process_pid = array_distinct($process.target.process.pid) + $target_process_command_line = array_distinct($process.target.process.command_line) + $target_process_file_sha256 = array_distinct($process.target.process.file.sha256) + $target_process_file_full_path = array_distinct($process.target.process.file.full_path) + $target_process_product_specific_process_id = array_distinct($process.target.process.product_specific_process_id) + $principal_user_userid = array_distinct($process.principal.user.userid) + + condition: + $process +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule windows_event_log_cleared { + + meta: + author = "Google Cloud Security" + description = "Detects the clearing of event logs within the Windows Event Viewer. " + rule_id = "mr_067f3ee9-9bc6-400d-9ba5-bebe7253482f" + rule_name = "Windows Event Log Cleared" + type = "alert" + data_source = "microsoft sysmon, microsoft windows events" + platform = "Windows" + mitre_attack_tactic = "Defense Evasion" + mitre_attack_technique = "Indicator Removal: Clear Windows Event Logs" + mitre_attack_url = "https://attack.mitre.org/versions/v13/techniques/T1070/001/" + mitre_attack_version = "v13.1" + severity = "Medium" + priority = "Medium" + + events: + ( + $process.metadata.event_type = "PROCESS_LAUNCH" and + // currently the command line is focused on the three primary log sets, could expand this further if desired + re.regex($process.target.process.command_line, `wevtutil.*cl.*(system|application|security)`) nocase + ) + or + ( + $process.metadata.event_type = "SYSTEM_AUDIT_LOG_WIPE" and + $process.metadata.vendor_name = "Microsoft" + ) + or + ( + $process.metadata.event_type = "STATUS_UPDATE" and + $process.metadata.product_name = "PowerShell" and + $process.metadata.vendor_name = "Microsoft" and + ( + re.regex($process.security_result.description, `Remove-EventLog`) nocase or + re.regex($process.security_result.description, `Clear-EventLog`) nocase + ) + ) + $process.principal.hostname = $hostname + + match: + $hostname over 5m + + outcome: + $risk_score = max(65) + $mitre_attack_tactic = "Defense Evasion" + $mitre_attack_technique = "Indicator Removal: Clear Windows Event Logs" + $mitre_attack_technique_id = "T1070.001" + $event_count = count_distinct($process.metadata.id) + $process_description = array_distinct($process.metadata.description) + // added to populate alert graph with additional context + // Commented out principal.hostname because it is already represented in graph as match variable. If match changes, can uncomment to add to results + //$principal_hostname = array_distinct($process.principal.hostname) + $principal_process_pid = array_distinct($process.principal.process.pid) + $principal_process_command_line = array_distinct($process.principal.process.command_line) + $principal_process_file_sha256 = array_distinct($process.principal.process.file.sha256) + $principal_process_file_full_path = array_distinct($process.principal.process.file.full_path) + $principal_process_product_specific_process_id = array_distinct($process.principal.process.product_specific_process_id) + $principal_process_parent_process_product_specific_process_id = array_distinct($process.principal.process.parent_process.product_specific_process_id) + $target_process_pid = array_distinct($process.target.process.pid) + $target_process_command_line = array_distinct($process.target.process.command_line) + $target_process_file_sha256 = array_distinct($process.target.process.file.sha256) + $target_process_file_full_path = array_distinct($process.target.process.file.full_path) + $target_process_product_specific_process_id = array_distinct($process.target.process.product_specific_process_id) + $principal_user_userid = array_distinct($process.principal.user.userid) + + condition: + $process +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule mitre_attack_T1053_005_windows_creation_of_scheduled_task { + + meta: + author = "Google Cloud Security" + description = "Creation of scheduled task using command line" + rule_id = "mr_14beda0b-8ef1-4805-a227-df9d8bbc6804" + rule_name = "MITRE ATT&CK T1053.005 Windows Creation Of Scheduled Task" + mitre_attack_tactic = "Execution, Persistence, Privilege Escalation" + mitre_attack_technique = "Scheduled Task/Job: Scheduled Task" + mitre_attack_url = "https://attack.mitre.org/techniques/T1053/005/" + mitre_attack_version = "v13.1" + type = "alert" + platform = "Windows" + data_source = "sentinelone" + severity = "Info" + priority = "Info" + + events: + $process.metadata.event_type = "PROCESS_LAUNCH" + $process.principal.hostname = $hostname + re.regex($process.principal.process.command_line, `schtasks.*/create`) nocase + + match: + $hostname over 5m + + outcome: + $risk_score = max(15) + $mitre_attack_tactic = array_distinct("Execution, Persistence, Privilege Escalation") + $mitre_attack_technique = array_distinct("Scheduled Task/Job: Scheduled Task") + $mitre_attack_technique_id = array_distinct("T1053.005") + $event_count = count_distinct($process.metadata.id) + // added to populate alert graph with additional context + // Commented out principal.hostname because it is already represented in graph as match variable. If match changes, can uncomment to add to results + $principal_hostname = array_distinct($process.principal.hostname) + $principal_process_pid = array_distinct($process.principal.process.pid) + $principal_process_command_line = array_distinct($process.principal.process.command_line) + $principal_process_file_sha256 = array_distinct($process.principal.process.file.sha256) + $principal_process_file_full_path = array_distinct($process.principal.process.file.full_path) + $principal_process_product_specific_process_id = array_distinct($process.principal.process.product_specific_process_id) + $principal_process_parent_process_product_specific_process_id = array_distinct($process.principal.process.parent_process.product_specific_process_id) + $target_process_pid = array_distinct($process.target.process.pid) + $target_process_command_line = array_distinct($process.target.process.command_line) + $target_process_file_sha256 = array_distinct($process.target.process.file.sha256) + $target_process_file_full_path = array_distinct($process.target.process.file.full_path) + $target_process_product_specific_process_id = array_distinct($process.target.process.product_specific_process_id) + $principal_user_userid = array_distinct($process.principal.user.userid) + + condition: + $process +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule mitre_attack_T1021_002_windows_admin_share_with_asset_entity { + + meta: + author = "Google Cloud Security" + description = "Net use commands for SMB/Windows admin shares based on asset entity group" + rule_id = "mr_7b7fbe57-12a8-4254-ad73-b9e9024cbc8a" + rule_name = "MITRE ATT&CK T1021.002 Windows Admin Share With Asset Entity" + mitre_attack_tactic = "Lateral Movement" + mitre_attack_technique = "Remote Services: SMB/Windows Admin Shares" + mitre_attack_url = "https://attack.mitre.org/techniques/T1021/002/" + mitre_attack_version = "v13.1" + type = "alert" + tags = "asset entity" + platform = "Windows" + assumption = "Assumes ingestion of Windows assets to entity graph" + data_source = "microsoft sysmon, microsoft windows events" + severity = "Low" + priority = "Low" + + events: + $process.metadata.event_type = "PROCESS_LAUNCH" + $process.target.process.command_line = /net.*use.*(C|ADMIN|IPC)\$/ nocase + $process.principal.ip = $ip + + // Correlate with asset entity data + $asset.graph.entity.ip = $ip + $asset.graph.metadata.entity_type = "ASSET" + $asset.graph.metadata.source_type = "ENTITY_CONTEXT" + $asset.graph.entity.asset.platform_software.platform = "WINDOWS" + // Can be modified to focus rule on different groups or removed if not needed + $asset.graph.relations.entity.group.group_display_name = "Domain Computers" + + match: + $ip over 5m + + outcome: + $risk_score = max(35) + $mitre_attack_tactic = array_distinct("Lateral Movement") + $mitre_attack_technique = array_distinct("Remote Services: SMB/Windows Admin Shares") + $mitre_attack_technique_id = array_distinct("T1021.002") + $event_count = count_distinct($process.metadata.id) + // added to populate alert graph with additional context + // Commented out principal.hostname because principal.ip is already represented in graph as match variable. If match changes, can uncomment to add to results + //$principal_hostname = array_distinct($process.principal.hostname) + $principal_process_pid = array_distinct($process.principal.process.pid) + $principal_process_command_line = array_distinct($process.principal.process.command_line) + $principal_process_file_sha256 = array_distinct($process.principal.process.file.sha256) + $principal_process_file_full_path = array_distinct($process.principal.process.file.full_path) + $principal_process_product_specific_process_id = array_distinct($process.principal.process.product_specific_process_id) + $principal_process_parent_process_product_specific_process_id = array_distinct($process.principal.process.parent_process.product_specific_process_id) + $target_process_pid = array_distinct($process.target.process.pid) + $target_process_command_line = array_distinct($process.target.process.command_line) + $target_process_file_sha256 = array_distinct($process.target.process.file.sha256) + $target_process_file_full_path = array_distinct($process.target.process.file.full_path) + $target_process_product_specific_process_id = array_distinct($process.target.process.product_specific_process_id) + $principal_user_userid = array_distinct($process.principal.user.userid) + + condition: + $process and $asset +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule mitre_attack_T1570_suspicious_command_psexec { + + meta: + author = "Google Cloud Security" + description = "Command-line execution of the PsExec tool on Windows" + rule_id = "mr_b1c34e7b-79c2-4d44-a105-d8166f6fd2c5" + rule_name = "MITRE ATT&CK T1570 Suspicious Command PSExec" + mitre_attack_tactic = "Lateral Movement" + mitre_attack_technique = "Lateral Tool Transfer" + mitre_attack_url = "https://attack.mitre.org/techniques/T1570/" + mitre_attack_version = "v13.1" + type = "alert" + platform = "Windows" + data_source = "sentinelone" + severity = "Info" + priority = "Info" + + events: + $process.metadata.event_type = "PROCESS_LAUNCH" + $process.principal.hostname = $hostname + re.regex($process.principal.process.command_line, `psexec`) nocase + + match: + $hostname over 5m + + outcome: + $risk_score = max(15) + $mitre_attack_tactic = array_distinct("Lateral Movement") + $mitre_attack_technique = array_distinct("Lateral Tool Transfer") + $mitre_attack_technique_id = array_distinct("T1570") + $event_count = count_distinct($process.metadata.id) + // added to populate alert graph with additional context + // Commented out principal.hostname because it is already represented in graph as match variable. If match changes, can uncomment to add to results + //$principal_hostname = array_distinct($process.principal.hostname) + $principal_process_pid = array_distinct($process.principal.process.pid) + $principal_process_command_line = array_distinct($process.principal.process.command_line) + $principal_process_file_sha256 = array_distinct($process.principal.process.file.sha256) + $principal_process_file_full_path = array_distinct($process.principal.process.file.full_path) + $principal_process_product_specific_process_id = array_distinct($process.principal.process.product_specific_process_id) + $principal_process_parent_process_product_specific_process_id = array_distinct($process.principal.process.parent_process.product_specific_process_id) + $target_process_pid = array_distinct($process.target.process.pid) + $target_process_command_line = array_distinct($process.target.process.command_line) + $target_process_file_sha256 = array_distinct($process.target.process.file.sha256) + $target_process_file_full_path = array_distinct($process.target.process.file.full_path) + $target_process_product_specific_process_id = array_distinct($process.target.process.product_specific_process_id) + $principal_user_userid = array_distinct($process.principal.user.userid) + + condition: + $process +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule recon_successful_logon_enumeration_powershell_T1033_cisa_report { + + meta: + author = "Google Cloud Security" + description = "Detects the use of powershell to enumerate successful logins on a specific host" + rule_id = "mr_db589a2e-0a06-46b5-8479-f8e120ec0405" + rule_name = "MITRE ATT&CK T1033 Recon Successful Logon Enumeration Powershell CISA Report" + type = "hunt" + platform = "Windows" + data_source = "microsoft sysmon" + mitre_attack_tactic = "Discovery" + mitre_attack_technique = "System Owner/User Discovery" + mitre_attack_url = "https://attack.mitre.org/versions/v13/techniques/T1033/" + mitre_attack_version = "v13.1" + reference = "https://media.defense.gov/2023/May/24/2003229517/-1/-1/0/CSA_Living_off_the_Land.PDF" + severity = "Info" + priority = "Info" + + events: + ( + $process.metadata.event_type = "PROCESS_LAUNCH" and + // cisa report referenced cmd /c and other wmic switches like /user and /password, these have been excluded to focus on the commands being issued since + // focused on event code 4624 but could be modified to look for other event codes if needed + re.regex($process.target.process.command_line, `(|cmd.*/c).*Get-EventLog.*security.*-instanceid.*4624`) nocase + ) + or + ( + $process.metadata.event_type = "STATUS_UPDATE" and + re.regex($process.security_result.description, `Get-EventLog.*security.*-instanceid.*4624`) nocase + ) + $process.principal.hostname = $hostname + + match: + $hostname over 15m + + outcome: + $risk_score = max(15) + $mitre_attack_tactic = "Discovery" + $mitre_attack_technique = "System Owner/User Discovery" + $mitre_attack_technique_id = "T1033" + $event_count = count_distinct($process.metadata.id) + $security_result_description = array_distinct($process.security_result.description) + // added to populate alert graph with additional context + // Commented out principal.hostname because it is already represented in graph as match variable. If match changes, can uncomment to add to results + //$principal_hostname = array_distinct($process.principal.hostname) + $principal_process_pid = array_distinct($process.principal.process.pid) + $principal_process_command_line = array_distinct($process.principal.process.command_line) + $principal_process_file_sha256 = array_distinct($process.principal.process.file.sha256) + $principal_process_file_full_path = array_distinct($process.principal.process.file.full_path) + $principal_process_product_specific_process_id = array_distinct($process.principal.process.product_specific_process_id) + $principal_process_parent_process_product_specific_process_id = array_distinct($process.principal.process.parent_process.product_specific_process_id) + $target_process_pid = array_distinct($process.target.process.pid) + $target_process_command_line = array_distinct($process.target.process.command_line) + $target_process_file_sha256 = array_distinct($process.target.process.file.sha256) + $target_process_file_full_path = array_distinct($process.target.process.file.full_path) + $target_process_product_specific_process_id = array_distinct($process.target.process.product_specific_process_id) + $principal_user_userid = array_distinct($process.principal.user.userid) + + condition: + $process +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule rw_windows_password_spray_T1110_003 { + + meta: + author = "Google Cloud Security" + description = "Detect repeated authentication failure with multiple users indicative of a password spray attack." + rule_id = "mr_5d6c9686-992f-4caf-bf1b-2fec05925c49" + rule_name = "MITRE ATT&CK T1110.003 RW Windows Password Spray" + type = "alert" + data_source = "microsoft windows events" + mitre_attack_tactic = "Credential Access" + mitre_attack_technique = "Brute Force: Password Spraying" + mitre_attack_url = "https://attack.mitre.org/techniques/T1110/003/" + mitre_attack_version = "v13.1" + platform = "Windows" + severity = "Medium" + priority = "Medium" + + events: + $login.metadata.event_type = "USER_LOGIN" + $login.metadata.vendor_name = "Microsoft" + $login.principal.hostname = $hostname + $login.target.user.userid = $user + $login.security_result.action = "BLOCK" + + match: + $hostname over 30m + + outcome: + $risk_score = max(65) + $mitre_attack_tactic = array_distinct("Credential Access") + $mitre_attack_technique = array_distinct("Brute Force: Password Spraying") + $mitre_attack_technique_id = array_distinct("T1110.003") + $event_count = count_distinct($login.metadata.id) + $user_login_threshold = max(10) + $target_user_distinct_count = count_distinct($user) + $target_user_count = count($user) + $tlp = array_distinct("amber") + // added to populate alert graph with additional context + // Commented out principal.hostname because it is already represented in graph as match variable. If match changes, can uncomment to add to results + //$principal_hostname = array_distinct($login.principal.hostname) + $principal_ip = array_distinct($login.principal.ip) + $target_hostname = array_distinct($login.target.hostname) + $src_hostname = array_distinct($login.src.hostname) + $target_ip = array_distinct($login.target.ip) + $principal_user_userid = array_distinct($login.principal.user.userid) + $target_user_userid = array_distinct($login.target.user.userid) + $principal_resource_name = array_distinct($login.principal.resource.name) + $target_resource_name = array_distinct($login.target.resource.name) + $target_url = array_distinct($login.target.url) + + condition: + #user > 10 +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule recon_suspicious_commands_cisa_report { + + meta: + author = "Google Cloud Security" + description = "Detects suspicious commands as identified in CISA Living of the Land pdf. Alone they may be normal but in concert, they may be worth looking into" + rule_id = "mr_66edb4f7-a7e2-4ce6-a247-d09319b7eeea" + rule_name = "Recon Suspicious Commands CISA Report" + type = "hunt" + platform = "Windows" + data_source = "microsoft sysmon, microsoft windows events" + reference = "https://media.defense.gov/2023/May/24/2003229517/-1/-1/0/CSA_Living_off_the_Land.PDF" + severity = "Low" + priority = "Low" + + events: + $process.metadata.event_type = "PROCESS_LAUNCH" + $process.principal.hostname = $hostname + $process.target.process.command_line = $command_line + + // cisa report referenced cmd /c in their report throughout, can filter this in/out for tuning as needed + // other wmic switches like /user and /password, these have been excluded to focus on the commands being issued since local access does not require these + ( + re.regex($process.target.process.command_line, `(|cmd.*/c).*7z.*a.*-p.*c:\\windows\\temp\\.*.7z`) nocase or + re.regex($process.target.process.command_line, `(|cmd.*/c).*c:\\Windows\\system32\\pcwrun.exe.*c:\\Users\\Administrator\\Desktop\\Win.exe`) nocase or + re.regex($process.target.process.command_line, `(|cmd.*/c|cmdbak.*/c).*ping.*-n.*1.*127\.0\.0\.1.*c:\\Windows\\temp\\(putty|tmp).log`) nocase or + // The following line could be swapped for the previous line for a looser match. It was observed during testing that a c2 running powershell logged putty.log as a file creation but not in the command line process event + //re.regex($process.target.process.command_line, `(|cmd.*/c).*ping.*-n.*1.*127\.0\.0\.1`) nocase or + re.regex($process.target.process.command_line, `(|cmd.*/c).*dir.*127\.0\.0\.1\\c\$.*/od`) nocase or + re.regex($process.target.process.command_line, `(|cmd.*/c).*ping.*-a.*-n.*1`) nocase or + re.regex($process.target.process.command_line, `(|cmd.*/c).*wmic.*process.*call.*create.*net.*stop.*C:\\Windows\\Temp\\tmp.log"`) nocase or + re.regex($process.target.process.command_line, `(|cmd.*/c).*\\ADMIN\$\\__.*2>&1`) nocase or + //The following line could be swapped for the previous line for a looser match, but potentially noisier + //re.regex($process.target.process.command_line, `(|cmd.*/c).*\\ADMIN\$\\__`) nocase or + re.regex($process.target.process.command_line, `(|cmd.*/c).*net.*use.*127\.0\.0\.1\\ipc\$.*/y.*/d`) nocase or + re.regex($process.target.process.command_line, `(|cmd.*/c).*powershell.*start-process.*-filepath.*c:\\windows\\temp\\.*.bat.*-windowstyle.*Hidden`) nocase or + re.regex($process.target.process.command_line, `(|cmd.*/c).*rar\.exe.*a.*c:\\Windows\\temp\\.*D:\\.*`) nocase or + re.regex($process.target.process.command_line, `(|cmd.*/c).*wmic.*cmd.*/c.*whoami`) nocase or + re.regex($process.target.process.command_line, `(|cmd.*/c).*xcopy.*c:\\windows\\temp\\hp.*d:\\`) nocase + ) + + match: + $hostname over 15m + + outcome: + $risk_score = max(35) + $event_count = count_distinct($process.metadata.id) + $unique_command_line_threshold = max(5) + // added to populate alert graph with additional context + // Commented out principal.hostname because it is already represented in graph as match variable. If match changes, can uncomment to add to results + //$principal_hostname = array_distinct($process.principal.hostname) + $principal_process_pid = array_distinct($process.principal.process.pid) + $principal_process_command_line = array_distinct($process.principal.process.command_line) + $principal_process_file_sha256 = array_distinct($process.principal.process.file.sha256) + $principal_process_file_full_path = array_distinct($process.principal.process.file.full_path) + $principal_process_product_specific_process_id = array_distinct($process.principal.process.product_specific_process_id) + $principal_process_parent_process_product_specific_process_id = array_distinct($process.principal.process.parent_process.product_specific_process_id) + $target_process_pid = array_distinct($process.target.process.pid) + $target_process_command_line = array_distinct($process.target.process.command_line) + $target_process_file_sha256 = array_distinct($process.target.process.file.sha256) + $target_process_file_full_path = array_distinct($process.target.process.file.full_path) + $target_process_product_specific_process_id = array_distinct($process.target.process.product_specific_process_id) + $principal_user_userid = array_distinct($process.principal.user.userid) + + condition: + // modify the condition value for command line to throttle how many of these unique commands can be seen until the rule is triggered + $process and #command_line > 5 +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule port_proxy_forwarding_T1090_cisa_report { + + meta: + author = "Google Cloud Security" + description = "Detects port forwarding being enabled using netsh command and registry settings created or modified in support of portproxy v4tov4" + rule_id = "mr_4c6f2d66-ed6f-4dda-bd2f-7c545898468b" + rule_name = "MITRE ATT&CK T1090 Port Proxy Forwarding CISA Report" + type = "hunt" + platform = "Windows" + data_source = "microsoft sysmon, windows event log" + mitre_attack_tactic = "Command and Control" + mitre_attack_technique = "Proxy" + mitre_attack_url = "https://attack.mitre.org/versions/v13/techniques/T1090/" + mitre_attack_version = "v13.1" + reference = "https://media.defense.gov/2023/May/24/2003229517/-1/-1/0/CSA_Living_off_the_Land.PDF" + severity = "Low" + priority = "Low" + + events: + ( + $process.metadata.event_type = "PROCESS_LAUNCH" and + + // cisa report referenced cmd /c in their report throughout, can filter this in/out for tuning as needed + re.regex($process.target.process.command_line, `(|cmd.*/c).*netsh.*interface.*portproxy.*add.*v4tov4`) nocase + // For greater precision to align with the report, comment out the above line and uncomment the below line to incorporate exact ports referenced + //re.regex($process.target.process.command_line, `(|cmd.*/c).*netsh.*interface.*portproxy.*add.*v4tov4.*port\=(9999|50100).*port\=(8443|1433)`) nocase + ) + or + ( + // Looks for the actual registry creation or modification that would accompany portproxy command executing + ( + $process.metadata.event_type = "REGISTRY_CREATION" or + $process.metadata.event_type = "REGISTRY_MODIFICATION" + ) and + $process.target.registry.registry_key = "HKLM\\System\\CurrentControlSet\\Services\\PortProxy\\v4tov4" + ) + + $process.principal.hostname = $hostname + + match: + $hostname over 5m + + outcome: + $risk_score = max(35) + $mitre_attack_tactic = "Command and Control" + $mitre_attack_technique = "Proxy" + $mitre_attack_technique_id = "T1090" + $event_count = count_distinct($process.metadata.id) + // added to populate alert graph with additional context + // Commented out principal.hostname because it is already represented in graph as match variable. If match changes, can uncomment to add to results + //$principal_hostname = array_distinct($process.principal.hostname) + $principal_process_pid = array_distinct($process.principal.process.pid) + $principal_process_command_line = array_distinct($process.principal.process.command_line) + $principal_process_file_sha256 = array_distinct($process.principal.process.file.sha256) + $principal_process_file_full_path = array_distinct($process.principal.process.file.full_path) + $principal_process_product_specific_process_id = array_distinct($process.principal.process.product_specific_process_id) + $principal_process_parent_process_product_specific_process_id = array_distinct($process.principal.process.parent_process.product_specific_process_id) + $target_process_pid = array_distinct($process.target.process.pid) + $target_process_command_line = array_distinct($process.target.process.command_line) + $target_process_file_sha256 = array_distinct($process.target.process.file.sha256) + $target_process_file_full_path = array_distinct($process.target.process.file.full_path) + $target_process_product_specific_process_id = array_distinct($process.target.process.product_specific_process_id) + $principal_user_userid = array_distinct($process.principal.user.userid) + + condition: + $process +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule impacket_wmiexec_cisa_report { + + meta: + author = "Google Cloud Security" + description = "Detects the artifacts generally associated with the use of wmiexec.py" + rule_id = "mr_ca682bc6-411b-46e5-88ef-1668032b14d1" + rule_name = "Impacket WMIExec CISA Report" + type = "alert" + data_source = "microsoft sysmon, microsoft windows events" + mitre_attack_tactic = "Execution" + mitre_attack_technique = "Windows Management Instrumentation" + mitre_attack_url = "https://attack.mitre.org/techniques/T1047/" + mitre_attack_version = "v13.1" + reference = "https://media.defense.gov/2023/May/24/2003229517/-1/-1/0/CSA_Living_off_the_Land.PDF" + severity = "Medium" + priority = "Medium" + + events: + ( + $process.metadata.event_type = "PROCESS_LAUNCH" and + re.regex($process.target.process.command_line, `1>.*\\ADMIN\$\\__.*2>&1`) nocase + ) + or + ( + $process.metadata.event_type = "FILE_CREATION" and + re.regex($process.target.file.full_path, `\\windows\\__`) nocase + ) + $process.principal.hostname = $hostname + + match: + $hostname over 5m + + outcome: + $risk_score = max(65) + $mitre_attack_tactic = "Execution" + $mitre_attack_technique = "Windows Management Instrumentation" + $mitre_attack_technique_id = "T1047" + // added to populate alert graph with additional context + $principal_hostname = array_distinct($process.principal.hostname) + $principal_process_pid = array_distinct($process.principal.process.pid) + $principal_process_command_line = array_distinct($process.principal.process.command_line) + $principal_process_file_sha256 = array_distinct($process.principal.process.file.sha256) + $principal_process_file_full_path = array_distinct($process.principal.process.file.full_path) + $principal_process_product_specific_process_id = array_distinct($process.principal.process.product_specific_process_id) + $principal_process_parent_process_product_specific_process_id = array_distinct($process.principal.process.parent_process.product_specific_process_id) + $target_process_pid = array_distinct($process.target.process.pid) + $target_process_command_line = array_distinct($process.target.process.command_line) + $target_process_file_sha256 = array_distinct($process.target.process.file.sha256) + $target_process_file_full_path = array_distinct($process.target.process.file.full_path) + $target_process_product_specific_process_id = array_distinct($process.target.process.product_specific_process_id) + $principal_user_userid = array_distinct($process.principal.user.userid) + $target_user_userid = array_distinct($process.target.user.userid) + $target_file_full_path = array_distinct($process.target.file.full_path) + + condition: + $process +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule mitre_attack_T1140_encoded_powershell_command { + + meta: + author = "Google Cloud Security" + description = "Detects encoded powershell commands" + rule_id = "mr_c01d7d92-db49-4044-a2c5-5a16c74a141d" + rule_name = "MITRE ATT&CK T1140 Encoded Powershell Command" + mitre_attack_tactic = "Defense Evasion" + mitre_attack_technique = "Deobfuscate/Decode Files or Information" + mitre_attack_url = "https://attack.mitre.org/techniques/T1140/" + mitre_attack_version = "v13.1" + type = "hunt" + platform = "Windows" + data_source = "microsoft sysmon, microsoft windows events" + severity = "Info" + priority = "Info" + + events: + $process.metadata.event_type = "PROCESS_LAUNCH" + $process.principal.hostname = $hostname + re.regex($process.target.process.file.full_path, `(system32|syswow64)\\WindowsPowerShell\\v1\.0\\powershell(|\_ise)\.exe`) nocase + re.regex($process.target.process.command_line, `(?i)(?:-enc|-ec|-en)\s*\S*`) + $encoded_value = re.capture($process.target.process.command_line, `(?i)(?:-enc|-ec|-en)\s*(\S*)`) + $decoded_value = re.replace(strings.base64_decode(re.capture($process.target.process.command_line, `(?i)(?:-enc|-ec|-en)\s*(\S*)`)),`\0`, "") + + match: + $hostname over 5m + + outcome: + $risk_score = max(10) + $mitre_attack_tactic = array_distinct("Defense Evasion") + $mitre_attack_technique = array_distinct("Deobfuscate/Decode Files or Information") + $mitre_attack_technique_id = array_distinct("T1140") + $event_count = count_distinct($process.metadata.id) + $encoded_powershell = array_distinct($encoded_value) + $decoded_powershell = array_distinct($decoded_value) + // added to populate alert graph with additional context + // Commented out principal.hostname because it is already represented in graph as match variable. If match changes, can uncomment to add to results + $principal_hostname = array_distinct($process.principal.hostname) + $principal_process_pid = array_distinct($process.principal.process.pid) + $principal_process_command_line = array_distinct($process.principal.process.command_line) + $principal_process_file_sha256 = array_distinct($process.principal.process.file.sha256) + $principal_process_file_full_path = array_distinct($process.principal.process.file.full_path) + $principal_process_product_specific_process_id = array_distinct($process.principal.process.product_specific_process_id) + $principal_process_parent_process_product_specific_process_id = array_distinct($process.principal.process.parent_process.product_specific_process_id) + $target_process_pid = array_distinct($process.target.process.pid) + $target_process_command_line = array_distinct($process.target.process.command_line) + $target_process_file_sha256 = array_distinct($process.target.process.file.sha256) + $target_process_file_full_path = array_distinct($process.target.process.file.full_path) + $target_process_product_specific_process_id = array_distinct($process.target.process.product_specific_process_id) + $principal_user_userid = array_distinct($process.principal.user.userid) + +condition: + $process +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule win_repeatedAuthFailure_thenSuccess_T1110_001 { + + meta: + author = "Google Cloud Security" + description = "Detect Multiple Failed Login Attempts followed by Successful Login" + rule_id = "mr_16893c0e-2563-44ed-84c9-57ab326eb1c2" + rule_name = "MITRE ATT&CK T1110.001 Windows Repeated Authentication Failures Before Successful One" + type = "alert" + data_source = "microsoft windows events" + platform = "Windows" + severity = "Medium" + priority = "Medium" + mitre_attack_tactic = "Credential Access" + mitre_attack_technique = "Brute Force: Password Guessing" + mitre_attack_url = "https://attack.mitre.org/techniques/T1110/001/" + mitre_attack_version = "v13.1" + + events: + $fail.metadata.event_type = "USER_LOGIN" + $fail.metadata.vendor_name = "Microsoft" + $fail.principal.hostname = $hostname + $fail.target.user.userid = $user + $fail.security_result.action = "BLOCK" + $fail.metadata.product_event_type = "4625" + + $fail.metadata.event_timestamp.seconds < $success.metadata.event_timestamp.seconds + + $success.metadata.event_type = "USER_LOGIN" + $success.metadata.vendor_name = "Microsoft" + $success.target.user.userid = $user + $success.principal.hostname = $hostname + $success.security_result.action = "ALLOW" + $success.metadata.product_event_type = "4624" + + match: + $user, $hostname over 15m + + outcome: + // increment risk score if the system targeted is active directory server, can modify as you see fit, using this as an example + $risk_score = max(if($hostname = /activedir/, 75, 50)) + $mitre_attack_tactic = array_distinct("Credential Access") + $mitre_attack_technique = array_distinct("Brute Force: Password Guessing") + $mitre_attack_technique_id = array_distinct("T1110.001") + $failed_login_threshold = max(5) + $impacted_systems = array_distinct($hostname) + $impacted_users = array_distinct($user) + $alert_type = array_distinct("Successful Brute Force Attack") + $tlp = array_distinct("red") + // added to populate alert graph with additional context + // Commented out principal.hostname because it is already represented in graph as match variable. If match changes, can uncomment to add to results + //$principal_hostname = array_distinct($success.principal.hostname) + $principal_ip = array_distinct($success.principal.ip) + $target_hostname = array_distinct($success.target.hostname) + $src_hostname = array_distinct($success.src.hostname) + $target_ip = array_distinct($success.target.ip) + $principal_user_userid = array_distinct($success.principal.user.userid) + // Commented out target.user.userid because it is already represented in graph as match variable. If match changes, can uncomment to add to results + //$target_user_userid = array_distinct($success.target.user.userid) + $principal_resource_name = array_distinct($success.principal.resource.name) + $target_resource_name = array_distinct($success.target.resource.name) + $target_url = array_distinct($success.target.url) + + condition: + #fail > 4 and $success +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule recon_credential_theft_cisa_report { + + meta: + author = "Google Cloud Security" + description = "Detects suspicious credential access commands as identified in CISA Living of the Land pdf. Alone they may be normal but in concert, they may be worth looking into" + rule_id = "mr_90b80326-d559-4e82-b5da-613e5406127a" + rule_name = "Recon Credential Theft CISA Report" + type = "hunt" + platform = "Windows" + data_source = "microsoft sysmon" + mitre_attack_tactic = "Credential Access" + mitre_attack_technique = "Credentials from Password Stores" + mitre_attack_url = "https://attack.mitre.org/versions/v13/techniques/T1555/" + mitre_attack_version = "v13.1" + reference = "https://media.defense.gov/2023/May/24/2003229517/-1/-1/0/CSA_Living_off_the_Land.PDF" + severity = "Low" + priority = "Low" + + events: + $process.metadata.event_type = "PROCESS_LAUNCH" + $process.principal.hostname = $hostname + $process.target.process.command_line = $command_line + + // cisa report referenced cmd /c in their report throughout, can filter this in/out for tuning as needed + ( + re.regex($process.target.process.command_line, `(|cmd.*/c).*dir.*C:\\Users\\.*\\.ssh\\known_hosts`) nocase or + re.regex($process.target.process.command_line, `(|cmd.*/c).*dir.*C:\\users\\.*\\appdata\\roaming\\Mozilla\\firefox\\profiles`) nocase or + re.regex($process.target.process.command_line, `(|cmd.*/c).*mimikatz`) nocase or + re.regex($process.target.process.command_line, `(|cmd.*/c).*reg.*query.*hklm\\software\\OpenSSH`) nocase or + re.regex($process.target.process.command_line, `(|cmd.*/c).*reg.*query.*hklm\\software\\OpenSSH\\Agent`) nocase or + re.regex($process.target.process.command_line, `(|cmd.*/c).*reg.*query.*hklm\\software\\realvnc`) nocase or + re.regex($process.target.process.command_line, `(|cmd.*/c).*reg.*query.*hklm\\software\\realvnc\\vncserver`) nocase or + re.regex($process.target.process.command_line, `(|cmd.*/c).*reg.*query.*hklm\\software\\realvnc\\Allusers`) nocase or + re.regex($process.target.process.command_line, `(|cmd.*/c).*reg.*query.*hklm\\software\\realvnc\\Allusers\\vncserver`) nocase or + re.regex($process.target.process.command_line, `(|cmd.*/c).*reg.*query.*hkcu\\software\\.*\\putty\\session`) nocase or + re.regex($process.target.process.command_line, `(|cmd.*/c).*reg.*save.*hklm\\sam ss.dat`) nocase or + re.regex($process.target.process.command_line, `(|cmd.*/c).*reg.*save.*hklm\\system sy.dat`) nocase + ) + + match: + $hostname over 15m + + outcome: + $risk_score = max(35) + $mitre_attack_tactic = "Credential Access" + $mitre_attack_technique = "Credentials from Password Stores" + $mitre_attack_technique_id = "T1555" + $event_count = count_distinct($process.metadata.id) + $unique_command_line_threshold = max(5) + // added to populate alert graph with additional context + // Commented out principal.hostname because it is already represented in graph as match variable. If match changes, can uncomment to add to results + //$principal_hostname = array_distinct($process.principal.hostname) + $principal_process_pid = array_distinct($process.principal.process.pid) + $principal_process_command_line = array_distinct($process.principal.process.command_line) + $principal_process_file_sha256 = array_distinct($process.principal.process.file.sha256) + $principal_process_file_full_path = array_distinct($process.principal.process.file.full_path) + $principal_process_product_specific_process_id = array_distinct($process.principal.process.product_specific_process_id) + $principal_process_parent_process_product_specific_process_id = array_distinct($process.principal.process.parent_process.product_specific_process_id) + $target_process_pid = array_distinct($process.target.process.pid) + $target_process_command_line = array_distinct($process.target.process.command_line) + $target_process_file_sha256 = array_distinct($process.target.process.file.sha256) + $target_process_file_full_path = array_distinct($process.target.process.file.full_path) + $target_process_product_specific_process_id = array_distinct($process.target.process.product_specific_process_id) + $principal_user_userid = array_distinct($process.principal.user.userid) + + condition: + // modify the condition value for command line to throttle how many of these commands can be issued until the rule is triggered + $process and #command_line > 5 +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule win_short_term_account_use { + + meta: + author = "Google Cloud Security" + description = "Detects the creation, login, and deletion of a user account over a predefined timeframe" + rule_id = "mr_ac28ce76-8197-4354-af0d-d77c5771d9df" + rule_name = "Windows Short Term Account Use" + type = "alert" + platform = "windows" + data_source = "microsoft windows events" + severity = "Medium" + priority = "Medium" + + events: + $create.metadata.event_type = "USER_CREATION" + $create.target.user.userid = $targetUser + + $create.metadata.event_timestamp.seconds < $login.metadata.event_timestamp.seconds + + $login.metadata.event_type = "USER_LOGIN" + //Focus is on Windows login events with this event code but could be modified for other platforms as well + $login.metadata.product_event_type = "4624" + $login.target.user.userid = $targetUser + + $login.metadata.event_timestamp.seconds < $delete.metadata.event_timestamp.seconds + + $delete.metadata.event_type = "USER_DELETION" + $delete.target.user.userid = $targetUser + + match: + $targetUser over 4h + + outcome: + $risk_score = max(65) + $event_count = count_distinct($login.metadata.id) + // added to populate alert graph with additional context + $principal_hostname = array_distinct($login.principal.hostname) + $src_hostname = array_distinct($login.src.hostname) + $src_ip = array_distinct($login.src.ip) + $principal_user_userid = array_distinct($login.principal.user.userid) + $principal_user_employee_id = array_distinct($login.principal.user.employee_id) + // principal_process_id for each of the three types of events + $user_creation_process_id = array_distinct($create.principal.process.pid) + $user_login_process_id = array_distinct($login.principal.process.pid) + $user_deletion_process_id = array_distinct($delete.principal.process.pid) + $target_process_file_full_path = array_distinct($login.target.process.file.full_path) + // Commented out target.user.userid because it is already represented in graph as match variable. If match changes, can uncomment to add to results + //$target_user_userid = array_distinct($login.target.user.userid) + $principal_resource_name = array_distinct($login.principal.resource.name) + $target_resource_name = array_distinct($login.target.resource.name) + $target_url = array_distinct($login.target.url) + + condition: + $create and $login and $delete + +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule recon_environment_enumeration_network_cisa_report { + + meta: + author = "Google Cloud Security" + description = "Detects network enumeration commands as identified in CISA Living of the Land pdf. Alone they may be normal but in concert, they may be worth looking into" + rule_id = "mr_9ca49a46-fb60-4ada-b722-5714d5cb7f53" + rule_name = "Recon Environment Enumeration Network CISA Report" + type = "hunt" + platform = "Windows" + data_source = "microsoft sysmon, windows event logs" + mitre_attack_tactic = "Discovery" + mitre_attack_technique = "System Network Configuration Discovery" + mitre_attack_url = "https://attack.mitre.org/versions/v13/techniques/T1016/" + mitre_attack_version = "v13.1" + reference = "https://media.defense.gov/2023/May/24/2003229517/-1/-1/0/CSA_Living_off_the_Land.PDF" + severity = "Low" + priority = "Low" + + events: + ( + $process.metadata.event_type = "PROCESS_LAUNCH" and + ( + // cisa report referenced cmd /c in their report throughout, can filter this in/out for tuning as needed + re.regex($process.target.process.command_line, `(|cmd.*/c).*arp.*-a`) nocase or + re.regex($process.target.process.command_line, `(|cmd.*/c).*curl.*www.ip-api.com`) nocase or + // the following line is a broader look at dnscmd /enumrecords not explicitly called out in the report can comment out if not needed + //re.regex($process.target.process.command_line, `(|cmd.*/c).*dnscmd.*/enumrecords`) nocase or + re.regex($process.target.process.command_line, `(|cmd.*/c).*dnscmd.*/enumrecords.*/zone`) nocase or + re.regex($process.target.process.command_line, `(|cmd.*/c).*dnscmd.*/enumzones`) nocase or + re.regex($process.target.process.command_line, `(|cmd.*/c).*dnscmd.*/enumrecords.*/additional`) nocase or + re.regex($process.target.process.command_line, `(|cmd.*/c).*ipconfig.*/all`) nocase or + re.regex($process.target.process.command_line, `(|cmd.*/c).*netsh.*interface.*firewall.*show`) nocase or + re.regex($process.target.process.command_line, `(|cmd.*/c).*netsh.*interface.*portproxy.*show`) nocase or + re.regex($process.target.process.command_line, `(|cmd.*/c).*netsh.*interface.*portproxy.*show.*v4tov4`) nocase or + re.regex($process.target.process.command_line, `(|cmd.*/c).*netsh.*firewall.*show`) nocase or + re.regex($process.target.process.command_line, `(|cmd.*/c).*netsh.*portproxy.*show.*v4tov4`) nocase or + re.regex($process.target.process.command_line, `(|cmd.*/c).*netstat.*-ano`) nocase + ) + ) + or + ( + // C2 like Covenant will mask curl command running from PowerShell; added this to detect DNS lookup for this site as another method to identify + $process.metadata.event_type = "NETWORK_DNS" and + $process.network.application_protocol = "DNS" and + $process.network.dns.questions.name = "www.ip-api.com" + ) + + $process.principal.hostname = $hostname + $process.target.process.command_line = $command_line + + match: + $hostname over 15m + + outcome: + $risk_score = max(35) + $mitre_attack_tactic = "Discovery" + $mitre_attack_technique = "System Network Configuration Discovery" + $mitre_attack_technique_id = "T1016" + $event_count = count_distinct($process.metadata.id) + $unique_command_line_threshold = max(5) + // added to populate alert graph with additional context + // Commented out principal.hostname because it is already represented in graph as match variable. If match changes, can uncomment to add to results + //$principal_hostname = array_distinct($process.principal.hostname) + $principal_process_pid = array_distinct($process.principal.process.pid) + $principal_process_command_line = array_distinct($process.principal.process.command_line) + $principal_process_file_sha256 = array_distinct($process.principal.process.file.sha256) + $principal_process_file_full_path = array_distinct($process.principal.process.file.full_path) + $principal_process_product_specific_process_id = array_distinct($process.principal.process.product_specific_process_id) + $principal_process_parent_process_product_specific_process_id = array_distinct($process.principal.process.parent_process.product_specific_process_id) + $target_process_pid = array_distinct($process.target.process.pid) + $target_process_command_line = array_distinct($process.target.process.command_line) + $target_process_file_sha256 = array_distinct($process.target.process.file.sha256) + $target_process_file_full_path = array_distinct($process.target.process.file.full_path) + $target_process_product_specific_process_id = array_distinct($process.target.process.product_specific_process_id) + $principal_user_userid = array_distinct($process.principal.user.userid) + + condition: + // modify the condition value for command line to throttle how many of these commands can be issued until the rule is triggered + $process and #command_line > 5 +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule mitre_attack_T1021_002_windows_admin_share_with_user_entity { + + meta: + author = "Google Cloud Security" + description = "Net use commands for SMB/Windows admin shares focused on specific user entity characteristics" + rule_id = "mr_18cff6cc-0d2d-4b83-9424-c854c84c4241" + rule_name = "MITRE ATT&CK T1021.002 Windows Admin Share With User Entity" + mitre_attack_tactic = "Lateral Movement" + mitre_attack_technique = "Remote Services: SMB/Windows Admin Shares" + mitre_attack_url = "https://attack.mitre.org/techniques/T1021/002/" + mitre_attack_version = "v13.1" + type = "alert" + tags = "user entity" + platform = "Windows" + assumption = "Assumes ingestion of Windows users to entity graph" + data_source = "microsoft sysmon, microsoft windows events" + severity = "Low" + priority = "Low" + + events: + $process.metadata.event_type = "PROCESS_LAUNCH" + $process.target.process.command_line = /net.*use.*(C|ADMIN|IPC)\$/ nocase + $process.principal.user.userid = $userid + + // Correlate with user entity data + $user.graph.entity.user.userid = $userid + $user.graph.metadata.entity_type = "USER" + $user.graph.metadata.source_type = "ENTITY_CONTEXT" + + /* Following two lines are used for exercise #4 in rules workshop, comment out if you want to + demonstrate the same logic to run based on group */ + //$user.graph.entity.user.department != "Information Technology" or + //$user.graph.entity.user.title = "Intern" + + // Can be modified to focus rule on different groups or removed if not needed + any $user.graph.relations.entity.group.group_display_name = "Domain Admins" + + match: + $userid over 5m + + outcome: + $risk_score = max(35) + $mitre_attack_tactic = array_distinct("Lateral Movement") + $mitre_attack_technique = array_distinct("Remote Services: SMB/Windows Admin Shares") + $mitre_attack_technique_id = array_distinct("T1021.002") + $event_count = count_distinct($process.metadata.id) + // added to populate alert graph with additional context + $principal_hostname = array_distinct($process.principal.hostname) + $principal_process_pid = array_distinct($process.principal.process.pid) + $principal_process_command_line = array_distinct($process.principal.process.command_line) + $principal_process_file_sha256 = array_distinct($process.principal.process.file.sha256) + $principal_process_file_full_path = array_distinct($process.principal.process.file.full_path) + $principal_process_product_specific_process_id = array_distinct($process.principal.process.product_specific_process_id) + $principal_process_parent_process_product_specific_process_id = array_distinct($process.principal.process.parent_process.product_specific_process_id) + $target_process_pid = array_distinct($process.target.process.pid) + $target_process_command_line = array_distinct($process.target.process.command_line) + $target_process_file_sha256 = array_distinct($process.target.process.file.sha256) + $target_process_file_full_path = array_distinct($process.target.process.file.full_path) + $target_process_product_specific_process_id = array_distinct($process.target.process.product_specific_process_id) + // Commented out principal.user.userid because it is already represented in graph as match variable. If match changes, can uncomment to add to results + //$principal_user_userid = array_distinct($process.principal.user.userid) + + condition: + $process and $user +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule win_repeatedAuthFailure_thenSuccess_T1110_001_user_asset_entity { + + meta: + author = "Google Cloud Security" + description = "Detect Multiple Failed Login Attempts followed by Successful Login" + rule_id = "mr_2a9dc1d2-d4b8-4b80-a494-3369c681da60" + rule_name = "MITRE ATT&CK T1110.001 Windows Repeated Authentication Failures Before Successful One With User Entity" + type = "alert" + tags = "user entity, asset entity" + assumption = "Assumes ingestion of Windows users and assets to entity graph to entity graph" + data_source = "microsoft windows events" + platform = "Windows" + severity = "Medium" + priority = "Medium" + mitre_attack_tactic = "Credential Access" + mitre_attack_technique = "Brute Force: Password Guessing" + mitre_attack_url = "https://attack.mitre.org/techniques/T1110/001/" + mitre_attack_version = "v13.1" + + events: + $fail.metadata.event_type = "USER_LOGIN" + $fail.metadata.vendor_name = "Microsoft" + $fail.principal.hostname = $hostname + $fail.target.user.userid = $target_user + $fail.security_result.action = "BLOCK" + $fail.metadata.product_event_type = "4625" + + $fail.metadata.event_timestamp.seconds < $success.metadata.event_timestamp.seconds + + $success.metadata.event_type = "USER_LOGIN" + $success.metadata.vendor_name = "Microsoft" + $success.target.user.userid = $target_user + $success.principal.hostname = $hostname + $success.security_result.action = "ALLOW" + $success.metadata.product_event_type = "4624" + + // Correlate with user entity data + $user.graph.entity.user.userid = $target_user + $user.graph.metadata.entity_type = "USER" + $user.graph.metadata.source_type = "ENTITY_CONTEXT" + // Can modify the following line to focus the rule on different user groups + any $user.graph.relations.entity.group.group_display_name = "Domain Admins" + + // Correlate with asset entity data + $asset.graph.entity.asset.hostname = $hostname + $asset.graph.metadata.entity_type = "ASSET" + $asset.graph.metadata.source_type = "ENTITY_CONTEXT" + // Can modify the following line to focus the rule on different computer groups + any $asset.graph.relations.entity.group.group_display_name = "Domain Controllers" + + match: + $target_user, $hostname over 15m + + outcome: + //increment risk score if the system targeted is active directory server, can modify as you see fit, using this as an example + $risk_score = max(if($hostname = /activedir/, 75, 50)) + $mitre_attack_tactic = array_distinct("Credential Access") + $mitre_attack_technique = array_distinct("Brute Force: Password Guessing") + $mitre_attack_technique_id = array_distinct("T1110.001") + $failed_login_threshold = max(5) + $impacted_systems = array_distinct($hostname) + $impacted_users = array_distinct($target_user) + $alert_type = array_distinct("Successful Brute Force Attack") + $tlp = array_distinct("red") + // added to populate alert graph with additional context + // Commented out principal.hostname because it is already represented in graph as match variable. If match changes, can uncomment to add to results + //$principal_hostname = array_distinct($success.principal.hostname) + $principal_ip = array_distinct($success.principal.ip) + $target_hostname = array_distinct($success.target.hostname) + $src_hostname = array_distinct($success.src.hostname) + $target_ip = array_distinct($success.target.ip) + $principal_user_userid = array_distinct($success.principal.user.userid) + // Commented out target.user.userid because it is already represented in graph as match variable. If match changes, can uncomment to add to results + //$target_user_userid = array_distinct($success.target.user.userid) + $principal_resource_name = array_distinct($success.principal.resource.name) + $target_resource_name = array_distinct($success.target.resource.name) + $target_url = array_distinct($success.target.url) + + condition: + #fail > 4 and $success and $user and $asset +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule wmic_ntds_dit_T1003_003_cisa_report { + + meta: + author = "Google Cloud Security" + description = "Detects extraction of ntds.dit file using vssadmin.exe or ntdsutil.exe with wmic as identified in CISA Living of the Land pdf" + rule_id = "mr_b1719d37-6689-485d-b80c-b509fdaa1af8" + rule_name = "MITRE ATT&CK T1003.003 WMIC Ntds.dit CISA Report" + type = "alert" + platform = "Windows" + data_source = "microsoft sysmon, windows event logs" + mitre_attack_tactic = "Credential Access" + mitre_attack_technique = "OS Credential Dumping: NTDS" + mitre_attack_url = "https://attack.mitre.org/versions/v13/techniques/T1003/003/" + mitre_attack_version = "v13.1" + reference = "https://media.defense.gov/2023/May/24/2003229517/-1/-1/0/CSA_Living_off_the_Land.PDF" + severity = "High" + priority = "High" + + events: + ( + $process.metadata.event_type = "PROCESS_LAUNCH" and + ( + // cisa report referenced cmd /c in their report throughout, can filter this in/out for tuning as needed + // other wmic switches like /user and /password, these have been excluded to focus on the commands being issued since local access does not require these + re.regex($process.target.process.command_line, `(|cmd.*/c).*wmic.*process.*call.*create.*ntdsutil.*create.*full`) nocase or + // for greater precision to align with the report, the following line can be used instead of the previous line to focus on specific folders referenced + //re.regex($process.target.process.command_line, `(|cmd.*/c).*wmic.*process.*call.*create.*ntdsutil.*create.*full.*windows\\temp\\(tmp|pro|msafee_logs)`) nocase or + re.regex($process.target.process.command_line, `(|cmd.*/c).*vssadmin.*create.*shadow`) nocase or + // To detect this without wmic being used but written to c:\windows\temp\ in general + re.regex($process.target.process.command_line, `(|cmd.*/c).*ntdsutil.*create.*full.*windows\\temp\\`) nocase + ) + ) + or + ( + // This does not detect one of the utilities responsible for executing ntdsutil or vssadmin, but does detect .dit file being created in monitored folders + $process.metadata.event_type = "FILE_CREATION" and + re.regex($process.target.file.full_path, `\.dit$`) nocase + ) + or + ( + //Identify application event log actions associated with the creation of the ntds.dit file and with ntds database + $process.metadata.product_name = "ESENT" and + $process.metadata.vendor_name = "Microsoft" and + ( + $process.metadata.product_event_type = "216" or + $process.metadata.product_event_type = "325" or + $process.metadata.product_event_type = "326" or + $process.metadata.product_event_type = "327" + ) + ) + $process.principal.hostname = $hostname + + match: + $hostname over 5m + + outcome: + $risk_score = max(85) + $mitre_attack_tactic = "Credential Access" + $mitre_attack_technique = "OS Credential Dumping: NTDS" + $mitre_attack_technique_id = "T1003.003" + $event_count = count_distinct($process.metadata.id) + // added to populate alert graph with additional context + // Commented out principal.hostname because it is already represented in graph as match variable. If match changes, can uncomment to add to results + //$principal_hostname = array_distinct($process.principal.hostname) + $principal_process_pid = array_distinct($process.principal.process.pid) + $principal_process_command_line = array_distinct($process.principal.process.command_line) + $principal_process_file_sha256 = array_distinct($process.principal.process.file.sha256) + $principal_process_file_full_path = array_distinct($process.principal.process.file.full_path) + $principal_process_product_specific_process_id = array_distinct($process.principal.process.product_specific_process_id) + $principal_process_parent_process_product_specific_process_id = array_distinct($process.principal.process.parent_process.product_specific_process_id) + $target_process_pid = array_distinct($process.target.process.pid) + $target_process_command_line = array_distinct($process.target.process.command_line) + $target_process_file_sha256 = array_distinct($process.target.process.file.sha256) + $target_process_file_full_path = array_distinct($process.target.process.file.full_path) + $target_process_product_specific_process_id = array_distinct($process.target.process.product_specific_process_id) + $principal_user_userid = array_distinct($process.principal.user.userid) + + condition: + $process +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule suspicious_unusual_location_lnk_file { + + meta: + author = "Google Cloud Security" + description = "Detects creation and movement of .lnk files to specific folders" + rule_id = "mr_efb341aa-57c5-47b6-bde5-b409b4395c8f" + rule_name = "Suspicious Unusual Location LNK File" + type = "alert" + data_source = "microsoft sysmon" + platform = "Windows" + severity = "Low" + priority = "Low" + + events: + ( + $file.metadata.event_type = "FILE_CREATION" or + $file.metadata.event_type = "FILE_MODIFICATION" or + $file.metadata.event_type = "FILE_COPY" or + $file.metadata.event_type = "FILE_MOVE" + ) + //and is optional, implied when broken out by line + and + $file.target.file.full_path = /\.lnk$/ nocase and + //Looking in the desktop, documents and start menu folders, can be modified to look in different folders + $file.target.file.full_path = /\\(Desktop|Documents|Start Menu)\\.*/ nocase + + outcome: + $risk_score = 35 + //added to populate alert graph with additional context + $principal_hostname = $file.principal.hostname + $target_hostname = $file.target.hostname + $src_hostname = $file.src.hostname + $principal_process_pid = $file.principal.process.pid + $principal_process_command_line = $file.principal.process.command_line + $principal_process_file_sha256 = $file.principal.process.file.sha256 + $principal_process_file_full_path = $file.principal.process.file.full_path + $principal_process_product_specific_process_id = $file.principal.process.product_specific_process_id + $principal_process_parent_process_product_specific_process_id = $file.principal.process.parent_process.product_specific_process_id + $principal_user_userid = $file.principal.user.userid + $src_user_userid = $file.principal.user.userid + $target_file_sha256 = $file.target.file.sha256 + $target_file_full_path = $file.target.file.full_path + $src_file_sha256 = $file.src.file.sha256 + $src_file_full_path = $file.src.file.full_path + + condition: + $file +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule rw_utilities_associated_with_ntdsdit_T1003_003 { + + meta: + author = "Google Cloud Security" + description = "Detects process launches from processes related to ntds against key servers" + rule_id = "mr_03db3339-09ba-4c9c-b3d6-1b81998a1de4" + rule_name = "MITRE ATT&CK T1003.003 RW Utilities Associated With Ntds.dit" + type = "alert" + tags = "list" + assumption = "Assumes lists for key servers and ntds suspicious processes have been created" + data_source = "microsoft sysmon, microsoft windows events" + platform = "Windows" + mitre_attack_tactic = "Credential Access" + mitre_attack_technique = "OS Credential Dumping: NTDS" + mitre_attack_url = "https://attack.mitre.org/techniques/T1003/003/" + mitre_attack_version = "v13.1" + severity = "High" + priority = "High" + + events: + $process.metadata.event_type = "PROCESS_LAUNCH" + // ntds_suspicious_processes includes values like ntdsutil, vssadmin, diskshadow, esentutl + // Parses full_path for the file name to match list (excluding .exe) + re.capture($process.target.process.file.full_path, /.*\\(.*).exe/) in %ntds_suspicious_processes + // Replace .stackedpad.local with your domain if your key_servers list just contains hostname versus fqdn + // If using fqdn in your list, this re.replace function can be removed and a string match could be used instead + re.replace($process.principal.hostname, ".stackedpads.local", "") in %key_servers + $process.metadata.event_type = $event_type + + match: + $event_type over 5m + + outcome: + $risk_score = max(85) + $mitre_attack_tactic = array_distinct("Credential Access") + $mitre_attack_technique = array_distinct("OS Credential Dumping: NTDS") + $mitre_attack_technique_id = array_distinct("T1003.003") + $event_count = count_distinct($process.metadata.id) + // added to populate alert graph with additional context + $principal_hostname = array_distinct($process.principal.hostname) + $principal_process_pid = array_distinct($process.principal.process.pid) + $principal_process_command_line = array_distinct($process.principal.process.command_line) + $principal_process_file_sha256 = array_distinct($process.principal.process.file.sha256) + $principal_process_file_full_path = array_distinct($process.principal.process.file.full_path) + $principal_process_product_specific_process_id = array_distinct($process.principal.process.product_specific_process_id) + $principal_process_parent_process_product_specific_process_id = array_distinct($process.principal.process.parent_process.product_specific_process_id) + $target_process_pid = array_distinct($process.target.process.pid) + $target_process_command_line = array_distinct($process.target.process.command_line) + $target_process_file_sha256 = array_distinct($process.target.process.file.sha256) + $target_process_file_full_path = array_distinct($process.target.process.file.full_path) + $target_process_product_specific_process_id = array_distinct($process.target.process.product_specific_process_id) + $principal_user_userid = array_distinct($process.principal.user.userid) + + condition: + $process +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule recon_environment_enumeration_system_cisa_report { + + meta: + author = "Google Cloud Security" + description = "Detects system enumeration events as identified in CISA Living of the Land pdf. Alone they may be normal but in concert, they may be worth looking into" + rule_id = "mr_086dede6-33ba-42df-b001-5595ceb0d589" + rule_name = "Recon Environment Enumeration System CISA Report" + type = "hunt" + platform = "Windows" + data_source = "microsoft sysmon, windows event logs" + mitre_attack_tactic = "Discovery" + mitre_attack_technique = "System Information Discovery" + mitre_attack_url = "https://attack.mitre.org/versions/v13/techniques/T1082/" + mitre_attack_version = "v13.1" + reference = "https://media.defense.gov/2023/May/24/2003229517/-1/-1/0/CSA_Living_off_the_Land.PDF" + severity = "Low" + priority = "Low" + + events: + $process.metadata.event_type = "PROCESS_LAUNCH" + $process.principal.hostname = $hostname + $process.target.process.command_line = $command_line + + re.regex($process.target.process.command_line, `wevtutil.*qe.*security.*\/rd:true.*\/f:text.*\/q:.*\[System\[\(EventID`) nocase + // below is the more specific command down to the event id, could comment out the about and use this instead if desired + //re.regex($process.target.process.command_line, `wevtutil.*qe.*security.*\/rd:true.*\/f:text.*\/q:\*\[System\[\(EventID=4624\).*TimeCreated\[@SystemTime.*\]\].*EventData\[Data.*\]\]`) nocase + + or + + // cisa report referenced cmd /c in their report throughout, can filter this in/out for tuning as desired + // other wmic switches like /user and /password, these have been excluded to focus on the commands being issued since local access does not require these + ( + re.regex($process.target.process.command_line, `(|cmd.*/c).*ldifde.exe.*-f.*-p.*subtree`) nocase or + re.regex($process.target.process.command_line, `(|cmd.*/c).*reg.*query.*hklm\\software\\`) nocase or + re.regex($process.target.process.command_line, `(|cmd.*/c).*systeminfo`) nocase or + re.regex($process.target.process.command_line, `(|cmd.*/c).*tasklist.*\/v`) nocase or + re.regex($process.target.process.command_line, `(|cmd.*/c).*whoami`) nocase or + re.regex($process.target.process.command_line, `(|cmd.*/c).*wmic.*volume.*list.*brief`) nocase or + // cisa report called out wmic volume list brief, below is alternate that removed brief to widen criteria + //re.regex($process.target.process.command_line, `(|cmd.*/c).*wmic.*volume.*list`) nocase or + re.regex($process.target.process.command_line, `(|cmd.*/c).*wmic.*service.*brief`) nocase or + re.regex($process.target.process.command_line, `(|cmd.*/c).*wmic.*product.*list.*brief`) nocase or + re.regex($process.target.process.command_line, `(|cmd.*/c).*wmic.*baseboard.*list.*full`) nocase or + re.regex($process.target.process.command_line, `(|cmd.*/c).*wmic.*path.*win32_logicaldisk.*get.*(caption|filesystem|freespace|size|volumename)`) nocase + ) + + match: + $hostname over 15m + + outcome: + $risk_score = max(35) + $mitre_attack_tactic = "Discovery" + $mitre_attack_technique = "System Information Discovery" + $mitre_attack_technique_id = "T1082" + $event_count = count_distinct($process.metadata.id) + $unique_command_line_threshold = max(5) + // added to populate alert graph with additional context + // Commented out principal.hostname because it is already represented in graph as match variable. If match changes, can uncomment to add to results + //$principal_hostname = array_distinct($process.principal.hostname) + $principal_process_pid = array_distinct($process.principal.process.pid) + $principal_process_command_line = array_distinct($process.principal.process.command_line) + $principal_process_file_sha256 = array_distinct($process.principal.process.file.sha256) + $principal_process_file_full_path = array_distinct($process.principal.process.file.full_path) + $principal_process_product_specific_process_id = array_distinct($process.principal.process.product_specific_process_id) + $principal_process_parent_process_product_specific_process_id = array_distinct($process.principal.process.parent_process.product_specific_process_id) + $target_process_pid = array_distinct($process.target.process.pid) + $target_process_command_line = array_distinct($process.target.process.command_line) + $target_process_file_sha256 = array_distinct($process.target.process.file.sha256) + $target_process_file_full_path = array_distinct($process.target.process.file.full_path) + $target_process_product_specific_process_id = array_distinct($process.target.process.product_specific_process_id) + $principal_user_userid = array_distinct($process.principal.user.userid) + + condition: + // modify the condition value for command line to throttle how many of these commands can be issued until the rule is triggered + $process and #command_line > 5 +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule mitre_attack_T1021_002_windows_admin_share_with_user_enrichment { + + meta: + author = "Google Cloud Security" + description = "Net use commands for SMB/Windows admin shares focused on UDM enriched user fields" + rule_id = "mr_57f52ed2-c7e2-4c8d-b308-2a3238986e98" + rule_name = "MITRE ATT&CK T1021.002 Windows Admin Share With User Enrichment" + mitre_attack_tactic = "Lateral Movement" + mitre_attack_technique = "Remote Services: SMB/Windows Admin Shares" + mitre_attack_url = "https://attack.mitre.org/techniques/T1021/002/" + mitre_attack_version = "v13.1" + type = "alert" + tags = "user enrichment" + platform = "Windows" + data_source = "microsoft sysmon, microsoft windows events" + severity = "Low" + priority = "Low" + + events: + $process.metadata.event_type = "PROCESS_LAUNCH" + $process.target.process.command_line = /net.*use.*(C|ADMIN|IPC)\$/ nocase + $process.principal.user.userid = $userid + + /* Enriched UDM fields from assets & users can often be used without needing to + join to entity graph for these fields, assuming assets and users are being ingested */ + $process.principal.user.department != "Information Technology" or + $process.principal.user.title = "Intern" + + match: + $userid over 5m + + outcome: + $risk_score = max(35) + $mitre_attack_tactic = array_distinct("Lateral Movement") + $mitre_attack_technique = array_distinct("Remote Services: SMB/Windows Admin Shares") + $mitre_attack_technique_id = array_distinct("T1021.002") + $event_count = count_distinct($process.metadata.id) + // added to populate alert graph with additional context + $principal_hostname = array_distinct($process.principal.hostname) + $principal_process_pid = array_distinct($process.principal.process.pid) + $principal_process_command_line = array_distinct($process.principal.process.command_line) + $principal_process_file_sha256 = array_distinct($process.principal.process.file.sha256) + $principal_process_file_full_path = array_distinct($process.principal.process.file.full_path) + $principal_process_product_specific_process_id = array_distinct($process.principal.process.product_specific_process_id) + $principal_process_parent_process_product_specific_process_id = array_distinct($process.principal.process.parent_process.product_specific_process_id) + $target_process_pid = array_distinct($process.target.process.pid) + $target_process_command_line = array_distinct($process.target.process.command_line) + $target_process_file_sha256 = array_distinct($process.target.process.file.sha256) + $target_process_file_full_path = array_distinct($process.target.process.file.full_path) + $target_process_product_specific_process_id = array_distinct($process.target.process.product_specific_process_id) + // Commented out principal.ip because it is already represented in graph as match variable. If match changes, can uncomment to add to results + //$principal_user_userid = array_distinct($process.principal.user.userid) + + condition: + $process +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule whoami_execution { + + meta: + author = "Google Cloud Security" + description = "Detects the execution of whoami, which is often used by attackers after exploitation to establish what credentials they are logged in under" + rule_id = "mr_4372a068-1411-449f-b572-dc2b9358b5f4" + rule_name = "Whoami Execution" + type = "hunt" + data_source = "microsoft sysmon, microsoft windows events" + mitre_attack_tactic = "Discovery" + mitre_attack_technique = "System Owner/User Discovery" + mitre_attack_url = "https://attack.mitre.org/techniques/T1033/" + mitre_attack_version = "v13.1" + platform = "Windows" + severity = "Info" + priority = "Info" + + events: + $process.metadata.event_type = "PROCESS_LAUNCH" + $process.target.process.command_line = "whoami" + + outcome: + $risk_score = 10 + $mitre_attack_tactic = "Discovery" + $mitre_attack_technique = "System Owner/User Discovery" + $mitre_attack_technique_id = "T1033" + // added to populate alert graph with additional context + $principal_hostname = $process.principal.hostname + $principal_process_pid = $process.principal.process.pid + $principal_process_command_line = $process.principal.process.command_line + $principal_process_file_sha256 = $process.principal.process.file.sha256 + $principal_process_file_full_path = $process.principal.process.file.full_path + $principal_process_product_specific_process_id = $process.principal.process.product_specific_process_id + $principal_process_parent_process_product_specific_process_id = $process.principal.process.parent_process.product_specific_process_id + $target_process_pid = $process.target.process.pid + $target_process_command_line = $process.target.process.command_line + $target_process_file_sha256 = $process.target.process.file.sha256 + $target_process_file_full_path = $process.target.process.file.full_path + $target_process_product_specific_process_id = $process.target.process.product_specific_process_id + $principal_user_userid = $process.principal.user.userid + + condition: + $process +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule mitre_attack_T1021_002_windows_admin_share_basic { + + meta: + author = "Google Cloud Security" + description = "Detect the use of net use for SMB/Windows admin shares" + rule_id = "mr_ceadd402-7315-4462-9716-8b41a6329bdd" + rule_name = "MITRE ATT&CK T1021.002 Windows Admin Share Basic" + mitre_attack_tactic = "Lateral Movement" + mitre_attack_technique = "Remote Services: SMB/Windows Admin Shares" + mitre_attack_url = "https://attack.mitre.org/techniques/T1021/002/" + mitre_attack_version = "v13.1" + type = "alert" + platform = "Windows" + data_source = "microsoft sysmon, microsoft windows events" + severity = "Low" + priority = "Low" + + events: + $process.metadata.event_type = "PROCESS_LAUNCH" + $process.target.process.command_line = /net.*use.*(C|ADMIN|IPC)\$/ nocase + + outcome: + $risk_score = 35 + $mitre_attack_tactic = "Lateral Movement" + $mitre_attack_technique = "Remote Services: SMB/Windows Admin Shares" + $mitre_attack_technique_id = "T1021.002" + // added to populate alert graph with additional context + $principal_hostname = $process.principal.hostname + $principal_process_pid = $process.principal.process.pid + $principal_process_command_line = $process.principal.process.command_line + $principal_process_file_sha256 = $process.principal.process.file.sha256 + $principal_process_file_full_path = $process.principal.process.file.full_path + $principal_process_product_specific_process_id = $process.principal.process.product_specific_process_id + $principal_process_parent_process_product_specific_process_id = $process.principal.process.parent_process.product_specific_process_id + $target_process_pid = $process.target.process.pid + $target_process_command_line = $process.target.process.command_line + $target_process_file_sha256 = $process.target.process.file.sha256 + $target_process_file_full_path = $process.target.process.file.full_path + $target_process_product_specific_process_id = $process.target.process.product_specific_process_id + $principal_user_userid = $process.principal.user.userid + + condition: + $process +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule recon_environment_enumeration_active_directory_cisa_report { + + meta: + author = "Google Cloud Security" + description = "Detects group enumeration commands as identified in CISA Living of the Land pdf. Alone they may be normal but in concert, they may be worth looking into" + rule_id = "mr_f7609336-c490-4601-bb75-1a1a142ad1cd" + rule_name = "Recon Environment Enumeration Active Directory CISA Report" + type = "hunt" + platform = "Windows" + data_source = "microsoft sysmon, windows event logs" + mitre_attack_tactic = "Discovery" + mitre_attack_technique = "Permission Groups Discovery: Domain Groups" + mitre_attack_url = "https://attack.mitre.org/versions/v13/techniques/T1069/002/" + mitre_attack_version = "v13.1" + reference = "https://media.defense.gov/2023/May/24/2003229517/-1/-1/0/CSA_Living_off_the_Land.PDF" + severity = "Low" + priority = "Low" + + events: + $process.metadata.event_type = "PROCESS_LAUNCH" + $process.principal.hostname = $hostname + $process.target.process.command_line = $command_line + + // cisa report referenced cmd /c in their report throughout, can filter this in/out for tuning as desired + ( + re.regex($process.target.process.command_line, `(|cmd.*/c).*net.*localgroup.*administrators`) nocase or + re.regex($process.target.process.command_line, `(|cmd.*/c).*net.*group.*\/dom`) nocase or + re.regex($process.target.process.command_line, `(|cmd.*/c).*net.*group.*Domain.*Admins.*\/dom`) nocase + ) + + match: + $hostname over 15m + + outcome: + $risk_score = max(35) + $mitre_attack_tactic = "Discovery" + $mitre_attack_technique = "Permission Groups Discovery: Domain Groups" + $mitre_attack_technique_id = "T1069.002" + $event_count = count_distinct($process.metadata.id) + $unique_command_line_threshold = max(1) + // added to populate alert graph with additional context + // Commented out principal.hostname because it is already represented in graph as match variable. If match changes, can uncomment to add to results + //$principal_hostname = array_distinct($process.principal.hostname) + $principal_process_pid = array_distinct($process.principal.process.pid) + $principal_process_command_line = array_distinct($process.principal.process.command_line) + $principal_process_file_sha256 = array_distinct($process.principal.process.file.sha256) + $principal_process_file_full_path = array_distinct($process.principal.process.file.full_path) + $principal_process_product_specific_process_id = array_distinct($process.principal.process.product_specific_process_id) + $principal_process_parent_process_product_specific_process_id = array_distinct($process.principal.process.parent_process.product_specific_process_id) + $target_process_pid = array_distinct($process.target.process.pid) + $target_process_command_line = array_distinct($process.target.process.command_line) + $target_process_file_sha256 = array_distinct($process.target.process.file.sha256) + $target_process_file_full_path = array_distinct($process.target.process.file.full_path) + $target_process_product_specific_process_id = array_distinct($process.target.process.product_specific_process_id) + $principal_user_userid = array_distinct($process.principal.user.userid) + + condition: + // modify the condition value for command line to throttle how many of these commands can be issued until the rule is triggered + $process and #command_line > 3 +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule google_workspace_saml_idp_configuration_change { + + meta: + author = "Google Cloud Security" + description = "Identifies SAML provider configuration changes in Google Workspace. Security teams can monitor for changes to SAML provider configuration that may weaken the organization's security posture." + rule_id = "mr_1a321683-9c52-4928-a654-e0677df97c09" + rule_name = "Google Workspace SAML IDP Configuration Change" + mitre_attack_tactic = "Defense Evasion, Persistence, Privilege Escalation, Initial Access" + mitre_attack_technique = "Valid Accounts" + mitre_attack_url = "https://attack.mitre.org/techniques/T1078/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "Workspace Activity" + severity = "High" + priority = "High" + + events: + $ws.metadata.vendor_name = "Google Workspace" + $ws.metadata.product_name = "admin" + $ws.security_result.category_details = "SAML2_SERVICE_PROVIDER_CONFIG_SETTINGS" + $ws.metadata.product_event_type = /SAML2_SERVICE_PROVIDER_CONFIG/ + $ws.principal.user.userid = $userid + + match: + $userid over 1h + + outcome: + $risk_score = max(75) + $mitre_attack_tactic = "Defense Evasion, Persistence, Privilege Escalation, Initial Access" + $mitre_attack_technique = "Valid Accounts" + $mitre_attack_technique_id = "T1078" + $event_count = count_distinct($ws.metadata.id) + $principal_ip = array_distinct($ws.principal.ip) + $principal_country = array_distinct($ws.principal.ip_geo_artifact.location.country_or_region) + $principal_state = array_distinct($ws.principal.ip_geo_artifact.location.state) + $principal_user_emails = array_distinct($ws.principal.user.email_addresses) + $principal_user_id = array_distinct($ws.principal.user.userid) + $saml_entity_id = array_distinct($ws.about.labels["saml2_service_provider_entity_id"]) + $saml_name = array_distinct($ws.about.labels["saml2_service_provider_name"]) + $product_event_type = array_distinct($ws.metadata.product_event_type) + + condition: + $ws +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule google_workspace_multiple_files_deleted_from_google_drive { + + meta: + author = "Google Cloud Security" + description = "Identifies when a user deletes multiple files from Google Drive, which may indicate data destruction." + rule_id = "mr_efa7bd41-506c-49b9-85a0-d799f0345ecf" + rule_name = "Google Workspace Multiple Files Deleted From Google Drive" + mitre_attack_tactic = "Impact" + mitre_attack_technique = "Data Destruction" + mitre_attack_url = "https://attack.mitre.org/techniques/T1485/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "Workspace Activity" + severity = "High" + priority = "High" + + events: + $ws.metadata.vendor_name = "Google Workspace" + $ws.metadata.product_name = "drive" + ( + $ws.metadata.product_event_type = "trash" or + $ws.metadata.product_event_type = "delete" + ) + $ws.principal.user.userid = $user_id + + match: + $user_id over 1h + + outcome: + $risk_score = max(75) + $mitre_attack_tactic = "Impact" + $mitre_attack_technique = "Data Destruction" + $mitre_attack_technique_id = "T1567" + $event_count = count_distinct($ws.metadata.id) + $product_event_type = array_distinct($ws.metadata.product_event_type) + $userid = array_distinct($ws.principal.user.userid) + $doc_type = array_distinct($ws.src.resource.attribute.labels["doc_type"]) + $owner = array_distinct($ws.target.resource.attribute.labels["owner"]) + $doc_name = array_distinct($ws.target.resource.name) + $doc_id = array_distinct($ws.target.resource.product_object_id) + $count_docs = count_distinct($ws.target.resource.product_object_id) + + condition: + // Customize the value of $count_docs to set the alerting threshold for your environment + $ws and $count_docs > 10 +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule google_workspace_custom_admin_role_created { + + meta: + author = "Google Cloud Security" + description = "Identifies when a custom administrator role is created in Google Workspace. Security teams can monitor for malicious or accidental configuration of administrator privileges to prevent unauthorized access to data." + rule_id = "mr_a15f64fc-3eaf-49f0-9f74-c533a63cb531" + rule_name = "Google Workspace Custom Admin Role Created" + mitre_attack_tactic = "Persistence" + mitre_attack_technique = "Account Manipulation: Additional Cloud Roles" + mitre_attack_url = "https://attack.mitre.org/techniques/T1098/003/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "Workspace Activity" + severity = "High" + priority = "High" + + events: + $ws.metadata.vendor_name = "Google Workspace" + $ws.metadata.product_name = "admin" + $ws.metadata.event_type = "USER_RESOURCE_CREATION" + $ws.metadata.product_event_type = "CREATE_ROLE" + $ws.security_result.category_details = "DELEGATED_ADMIN_SETTINGS" + + outcome: + $risk_score = max(85) + $mitre_attack_tactic = "Persistence" + $mitre_attack_technique = "Account Manipulation: Additional Cloud Roles" + $mitre_attack_technique_id = "T1098.003" + $event_count = count_distinct($ws.metadata.id) + $principal_ip = array_distinct($ws.principal.ip) + $principal_country = array_distinct($ws.principal.ip_geo_artifact.location.country_or_region) + $principal_state = array_distinct($ws.principal.ip_geo_artifact.location.state) + $principal_user_emails = array_distinct($ws.principal.user.email_addresses) + $target_user_emails = array_distinct($ws.target.user.email_addresses) + $principal_user_id = $ws.principal.user.userid + $role_id = $ws.target.resource.attribute.labels["role_id"] + $role_name = array_distinct($ws.target.resource.attribute.roles.name) + + condition: + $ws +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule google_workspace_ownership_transferred_on_google_drive { + + meta: + author = "Google Cloud Security" + description = "Identifies when a Google Workspace user transfers the ownership of a file." + rule_id = "mr_05cddcc9-abf6-4c4c-9518-e2218a1f5c84" + rule_name = "Google Workspace Ownership Transferred On Google Drive" + mitre_attack_tactic = "Collection" + mitre_attack_technique = "Data Staged: Remote Data Staging" + mitre_attack_url = "https://attack.mitre.org/techniques/T1074/002/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "Workspace Activity" + severity = "High" + priority = "High" + + events: + $ws.metadata.vendor_name = "Google Workspace" + $ws.metadata.product_name = "admin" + $ws.metadata.product_event_type = "CREATE_DATA_TRANSFER_REQUEST" + $ws.security_result.category_details = "USER_SETTINGS" + + outcome: + $risk_score = max(70) + $mitre_attack_tactic = "Collection" + $mitre_attack_technique = "Data Staged: Remote Data Staging" + $mitre_attack_technique_id = "T1074.002" + $event_count = count_distinct($ws.metadata.id) + $principal_ip = array_distinct($ws.principal.ip) + $principal_country = array_distinct($ws.principal.ip_geo_artifact.location.country_or_region) + $principal_state = array_distinct($ws.principal.ip_geo_artifact.location.state) + $principal_user_emails = array_distinct($ws.principal.user.email_addresses) + $target_user_emails = array_distinct($ws.target.user.email_addresses) + $principal_user_id = $ws.principal.user.userid + $target_application = $ws.target.application + $src_user_emails = array_distinct($ws.src.user.email_addresses) + + condition: + $ws +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule google_workspace_password_policy_changed { + + meta: + author = "Google Cloud Security" + description = "Identifies when Google Workspace password policy is changed. Security teams can monitor for changes to password policy configuration that may weaken the organization's security posture." + rule_id = "mr_fd63a810-800a-4c55-97d2-080fc8a0e567" + rule_name = "Google Workspace Password Policy Changed" + mitre_attack_tactic = "Persistence" + mitre_attack_technique = "Account Manipulation" + mitre_attack_url = "https://attack.mitre.org/techniques/T1098/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "Workspace Activity" + severity = "Low" + priority = "Low" + + events: + $ws.metadata.vendor_name = "Google Workspace" + $ws.metadata.product_name = "admin" + ($ws.metadata.product_event_type = "CREATE_APPLICATION_SETTING" or + $ws.metadata.product_event_type = "CHANGE_APPLICATION_SETTING") + $ws.security_result.category_details = "APPLICATION_SETTINGS" + $ws.target.resource.name = /Password Management/ + $ws.principal.user.email_addresses = $email + + match: + $email over 1h + + outcome: + $risk_score = max(35) + $mitre_attack_tactic = "Persistence" + $mitre_attack_technique = "Account Manipulation" + $mitre_attack_technique_id = "T1098" + $event_count = count_distinct($ws.metadata.id) + $principal_ip = array_distinct($ws.principal.ip) + $principal_country = array_distinct($ws.principal.ip_geo_artifact.location.country_or_region) + $principal_state = array_distinct($ws.principal.ip_geo_artifact.location.state) + $principal_user_emails = array_distinct($ws.principal.user.email_addresses) + $principal_user_id = array_distinct($ws.principal.user.userid) + $target_application =array_distinct($ws.target.application) + $password_policies =array_distinct($ws.target.resource.name) + + condition: + $ws +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule google_workspace_encryption_key_files_accessed_by_anonymous_user { + + meta: + author = "Google Cloud Security" + description = "Identifies when an encryption key file is accessed by an anonymous user in Google Drive. An adversary may attempt to access encryption keys before moving laterally and compromising sensitive data." + rule_id = "mr_5d7defeb-13d4-48f3-b6b0-d2cdab30ab57" + rule_name = "Google Workspace Encryption Key File Accessed By An Anonymous User" + mitre_attack_tactic = "Credential Access" + mitre_attack_technique = "Unsecured Credentials: Private Keys" + mitre_attack_url = "https://attack.mitre.org/techniques/T1552/004/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "Workspace Activity" + severity = "Medium" + priority = "Medium" + + events: + $ws.metadata.vendor_name = "Google Workspace" + $ws.metadata.product_name = "drive" + ($ws.metadata.product_event_type = "download" or + $ws.metadata.product_event_type = "view" or + $ws.metadata.product_event_type = "copy") + + ($ws.target.resource.attribute.labels["visibility"] = "people_with_link" or + $ws.target.resource.attribute.labels["visibility"] = "public_on_the_web") + $ws.target.resource.name = /.*token|.*assig|.*pssc|.*keystore|.*pub|.*pgp.asc|.*ps1xml|.*pem|.*gpg.sig|.*der|.*key|.*p7r|.*p12|.*asc|.*jks|.*p7b|.*signature|.*gpg|.*pgp.sig|.*sst|.*pgp|.*gpgz|.*pfx|.*crt|.*p8|.*sig|.*pkcs7|.*jceks|.*pkcs8|.*psc1|.*p7c|.*csr|.*cer|.*spc|.*ps2xml/ + + outcome: + $risk_score = max(35) + $mitre_attack_tactic = "Credential Access" + $mitre_attack_technique = "Unsecured Credentials: Private Keys" + $mitre_attack_technique_id = "T1552.004" + $event_count = count_distinct($ws.metadata.id) + $product_event_type = $ws.metadata.product_event_type + $userid = $ws.principal.user.userid + $doc_type = $ws.src.resource.attribute.labels["doc_type"] + $owner = $ws.target.resource.attribute.labels["owner"] + $doc_name = $ws.target.resource.name + //$doc_id = $ws.target.resource.product_object_id + + condition: + $ws +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule google_workspace_suspicious_login_and_google_drive_file_download { + + meta: + author = "Google Cloud Security" + description = "Identifies when a Google Workspace user downloads a file from Google Drive after a suspicious login event occurred." + rule_id = "mr_3c55c930-d9be-4d34-a90e-baf92c22ae40" + rule_name = "Google Workspace Suspicious Login and Google Drive File Download" + mitre_attack_tactic = "Exfiltration" + mitre_attack_technique = "Exfiltration Over Web Service" + mitre_attack_url = "https://attack.mitre.org/techniques/T1567/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "Workspace Activity" + severity = "High" + priority = "High" + + events: + // Suspicious Login Event + $login.metadata.vendor_name = "Google Workspace" + $login.metadata.product_name = "login" + $login.metadata.product_event_type = "login_success" + $login.about.labels["is_suspicious"] = "true" + + // Document Download Event + $download.metadata.vendor_name = "Google Workspace" + $download.metadata.product_name = "drive" + $download.metadata.product_event_type = "download" + + // Joining login and download events using userid + $login.target.user.userid = $download.principal.user.userid + + // Placeholders for match section + $login.principal.ip = $principal_ip + $login.target.user.userid = $target_userid + + // First login event occurs later a download event + $login.metadata.event_timestamp.seconds < $download.metadata.event_timestamp.seconds + + match: + $target_userid, $principal_ip over 1h + + outcome: + + $risk_score = max(75) + $mitre_attack_tactic = "Exfiltration" + $mitre_attack_technique = "Exfiltration Over Web Service" + $mitre_attack_technique_id = "T1567" + $event_count = count_distinct($download.metadata.id) + $product_event_type = array_distinct($download.metadata.product_event_type) + $userid = array_distinct($download.principal.user.userid) + $doc_type = array_distinct($download.src.resource.attribute.labels["doc_type"]) + $owner = array_distinct($download.target.resource.attribute.labels["owner"]) + $doc_name = array_distinct($download.target.resource.name) + $doc_id = array_distinct($download.target.resource.product_object_id) + + condition: + $login and $download +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule google_workspace_multiple_files_copied_from_google_drive { + + meta: + author = "Google Cloud Security" + description = "Identifies when a user copies multiple files from Google Drive, which may indicate data exfiltration." + rule_id = "mr_dc187a73-9ea0-47bf-9a78-9a6f915de0f0" + rule_name = "Google Workspace Multiple Files Copied From Google Drive" + mitre_attack_tactic = "Exfiltration" + mitre_attack_technique = "Exfiltration Over Web Service" + mitre_attack_url = "https://attack.mitre.org/techniques/T1567/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "Workspace Activity" + severity = "High" + priority = "High" + + events: + $ws.metadata.vendor_name = "Google Workspace" + $ws.metadata.product_name = "drive" + ( + $ws.metadata.product_event_type = "copy" or + $ws.metadata.product_event_type = "source_copy" + ) + $ws.principal.user.userid = $user_id + + match: + $user_id over 1h + + outcome: + $risk_score = max(75) + $mitre_attack_tactic = "Exfiltration" + $mitre_attack_technique = "Exfiltration Over Web Service" + $mitre_attack_technique_id = "T1567" + $event_count = count_distinct($ws.metadata.id) + $product_event_type = array_distinct($ws.metadata.product_event_type) + $userid = array_distinct($ws.principal.user.userid) + $doc_type = array_distinct($ws.src.resource.attribute.labels["doc_type"]) + $owner = array_distinct($ws.target.resource.attribute.labels["owner"]) + $doc_name = array_distinct($ws.target.resource.name) + $doc_id = array_distinct($ws.target.resource.product_object_id) + $count_docs = count_distinct($ws.target.resource.product_object_id) + + condition: + // Customize the value of $count_docs to set the alerting threshold for your environment + $ws and $count_docs > 10 +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule google_workspace_file_shared_from_google_drive_to_free_email_domain { + + meta: + author = "Google Cloud Security" + description = "Identifies when a user shares a file on Google Drive with a free email domain, which may indicate data exfiltration." + rule_id = "mr_054c422b-2a42-4dde-b937-e80d063f65e7" + rule_name = "Google Workspace File Shared From Google Drive To Free Email Domain" + mitre_attack_tactic = "Exfiltration" + mitre_attack_technique = "Exfiltration Over Web Service" + mitre_attack_url = "https://attack.mitre.org/techniques/T1567/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "Workspace Activity" + severity = "High" + priority = "High" + + events: + $ws.metadata.vendor_name = "Google Workspace" + $ws.metadata.product_name = "drive" + + ( + $ws.metadata.product_event_type = "change_user_access" or + $ws.metadata.product_event_type = "change_document_visibility" or + $ws.metadata.product_event_type = "change_document_access_scope" or + $ws.metadata.product_event_type = "change_acl_editors" + ) + + // File shared externally with free email domains + $ws.target.resource.attribute.labels["visibility"] = "shared_externally" + $ws.target.user.email_addresses = /.*@gmail\.com|.*@aol\.com|.*@ymail\.com|.*@ymail\.com|.*@hotmail\.com|.*@outlook\.com|.*@icloud\.com/ + + outcome: + $risk_score = max(75) + $mitre_attack_tactic = "Exfiltration" + $mitre_attack_technique = "Exfiltration Over Web Service" + $mitre_attack_technique_id = "T1567" + $event_count = count_distinct($ws.metadata.id) + $product_event_type = array_distinct($ws.metadata.product_event_type) + $userid = array_distinct($ws.principal.user.userid) + $doc_type = array_distinct($ws.src.resource.attribute.labels["doc_type"]) + $owner = array_distinct($ws.target.resource.attribute.labels["owner"]) + $target_emails = array_distinct($ws.target.user.email_addresses) + $doc_name = array_distinct($ws.target.resource.name) + $doc_id = array_distinct($ws.target.resource.product_object_id) + + condition: + $ws + } +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule google_workspace_suspicious_login_and_google_drive_file_share { + + meta: + author = "Google Cloud Security" + description = "Identifies when a Google Workspace user shares a file on Google Drive after a suspicious login event occurred." + rule_id = "mr_0ddcbd08-e918-4f7c-918b-3190c8b54ea4" + rule_name = "Google Workspace Suspicious Login and Google Drive File Share" + mitre_attack_tactic = "Exfiltration" + mitre_attack_technique = "Exfiltration Over Web Service" + mitre_attack_url = "https://attack.mitre.org/techniques/T1567/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "Workspace Activity" + severity = "High" + priority = "High" + + events: + // Suspicious Login Event + $login.metadata.vendor_name = "Google Workspace" + $login.metadata.product_name = "login" + $login.metadata.product_event_type = "login_success" + $login.about.labels["is_suspicious"] = "true" + + // Document Download Event + $share.metadata.vendor_name = "Google Workspace" + $share.metadata.product_name = "drive" + ( + $share.metadata.product_event_type = "change_user_access" or + $share.metadata.product_event_type = "change_document_visibility" or + $share.metadata.product_event_type = "change_document_access_scope" or + $share.metadata.product_event_type = "change_acl_editors" + ) + + // Joining login and download events using userid + $login.target.user.userid = $share.principal.user.userid + + // Placeholders for match section + $login.principal.ip = $principal_ip + $login.target.user.userid = $target_userid + + // First login event occurs later a download event + $login.metadata.event_timestamp.seconds < $share.metadata.event_timestamp.seconds + + match: + $target_userid, $principal_ip over 1h + + outcome: + + $risk_score = max(75) + $mitre_attack_tactic = "Exfiltration" + $mitre_attack_technique = "Exfiltration Over Web Service" + $mitre_attack_technique_id = "T1567" + $event_count = count_distinct($share.metadata.id) + $product_event_type = array_distinct($share.metadata.product_event_type) + $userid = array_distinct($share.principal.user.userid) + $doc_type = array_distinct($share.src.resource.attribute.labels["doc_type"]) + $owner = array_distinct($share.target.resource.attribute.labels["owner"]) + $doc_name = array_distinct($share.target.resource.name) + $doc_id = array_distinct($share.target.resource.product_object_id) + + condition: + $login and $share +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule chrome_browser_safe_browsing_user_bypass { + + meta: + author = "Google Cloud Security" + description = "Detects and alerts on users bypassing Chrome Safe Browsing warnings and accessing potentially dangerous content or downloads" + rule_id = "mr_73e2a3d4-13ba-47ef-b250-a2bdcd98dc48" + rule_name = "Chrome Browser Safe Browsing User Bypass" + mitre_attack_tactic = "Initial Access" + mitre_attack_technique = "Phishing: Spearphishing Link" + mitre_attack_url = "https://attack.mitre.org/techniques/T1566/002/" + mitre_attack_version = "v14.1" + type = "alert" + tags = "chrome enterprise" + data_source = "Chrome Management" + severity = "Low" + priority = "Low" + + events: + $process.metadata.product_name = "Chrome Management" + ( + $process.metadata.product_event_type = "badNavigationEvent" or + $process.metadata.product_event_type = "dangerousDownloadEvent" or + $process.metadata.product_event_type = "contentTransferEvent" or + $process.metadata.product_event_type = "unscannedFileEvent" + ) + $process.security_result.action_details = "EVENT_RESULT_BYPASSED" + $process.security_result.category_details = $category + strings.coalesce($process.principal.user.email_addresses, $process.principal.hostname ) = $user + + match: + $user over 5m + + outcome: + $risk_score = max( + if ($category = "", 10) + + if ($category = "THREAT_TYPE_UNSPECIFIED", 20) + + if ($category = "SSL_ERROR", 30) + + if ($category = "UNWANTED_SOFTWARE", 50) + + if ($category = "DANGEROUS", 60) + + if ($category = "SOCIAL_ENGINEERING", 70) + + if ($category = "DANGEROUS_HOST", 80) + + if ($category = "MALWARE", 90) + ) + $instances = count_distinct($user) + $suspicious_url = array_distinct($process.target.url) + $suspicious_file_sha256 = array_distinct($process.target.file.sha256) + $principal_user_userid = array_distinct($user) + +condition: + // To reduce the number of alerts to just higher risk events, uncomment the value in the line below + $process // and $risk_score >= 50 +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule google_workspace_multiple_files_downloaded_from_google_drive { + + meta: + author = "Google Cloud Security" + description = "Identifies when a user downloads multiple files from Google Drive, which may indicate data exfiltration." + rule_id = "mr_72855af9-fba4-4424-b879-4de733374e8b" + rule_name = "Google Workspace Multiple Files Downloaded From Google Drive" + mitre_attack_tactic = "Exfiltration" + mitre_attack_technique = "Exfiltration Over Web Service" + mitre_attack_url = "https://attack.mitre.org/techniques/T1567/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "Workspace Activity" + severity = "High" + priority = "High" + + events: + // Document downloaded from Google Drive + $download.metadata.vendor_name = "Google Workspace" + $download.metadata.product_name = "drive" + $download.metadata.product_event_type = "download" + $download.principal.user.userid = $user_id + + match: + $user_id over 1h + + outcome: + $risk_score = max(75) + $mitre_attack_tactic = "Exfiltration" + $mitre_attack_technique = "Exfiltration Over Web Service" + $mitre_attack_technique_id = "T1567" + $event_count = count_distinct($download.metadata.id) + $product_event_type = array_distinct($download.metadata.product_event_type) + $userid = array_distinct($download.principal.user.userid) + $doc_type = array_distinct($download.src.resource.attribute.labels["doc_type"]) + $owner = array_distinct($download.target.resource.attribute.labels["owner"]) + $doc_name = array_distinct($download.target.resource.name) + $doc_id = array_distinct($download.target.resource.product_object_id) + $count_docs = count_distinct($download.target.resource.product_object_id) + + condition: + // Customize the value of $count_docs to set the alerting threshold for your environment + $download and $count_docs > 10 + } +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule google_workspace_alerts_aggregated_by_severity { + + meta: + author = "Google Cloud Security" + description = "Generates alerts based on Google Workspace alerts center and aggregates them based on severity." + rule_id = "mr_311cc4ab-627b-43a1-a744-8d7aa5e44fbf" + rule_name = "Google Workspace Alerts Aggregated By Severity" + type = "Alert" + data_source = "Workspace Alerts" + + events: + $ws.metadata.vendor_name = "Google Workspace" + $ws.metadata.product_name = "Google Workspace Alerts" + $ws.security_result.severity = $severity + + match: + $severity over 1h + + outcome: + $risk_score = max(30 + + if($ws.security_result.severity = "LOW", 10)+ + if($ws.security_result.severity = "MEDIUM", 30)+ + if($ws.security_result.severity = "HIGH", 50) + ) + $event_count = count_distinct($ws.metadata.id) + $event_type = array_distinct($ws.metadata.event_type) + $product_event_type = array_distinct($ws.metadata.product_event_type) + $security_category_details = array_distinct($ws.security_result.category_details) + $security_category = array_distinct($ws.security_result.category) + $security_investigation_tool_link = array_distinct($ws.security_result.detection_fields["security_investigation_tool_link"]) + $security_summary = array_distinct($ws.security_result.summary) + $alert_severity = array_distinct($ws.security_result.severity) + + condition: + $ws +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule google_workspace_malicious_file_downloaded { + + meta: + author = "Google Cloud Security" + description = "Identifies when a user downloads a potentially malicious file from Google Drive." + rule_id = "mr_72af4504-955b-4c61-9071-bb767c9bae88" + rule_name = "Google Workspace Malicious File Downloaded" + mitre_attack_tactic = "Execution" + mitre_attack_technique = "User Execution: Malicious File" + mitre_attack_url = "https://attack.mitre.org/techniques/T1204/002/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "Workspace Activity" + severity = "Medium" + priority = "Medium" + + events: + $ws.metadata.vendor_name = "Google Workspace" + $ws.metadata.product_name = "drive" + ($ws.metadata.product_event_type = "download" or + $ws.metadata.product_event_type = "view" or + $ws.metadata.product_event_type = "copy") + + ($ws.target.resource.attribute.labels["visibility"] = "people_with_link" or + $ws.target.resource.attribute.labels["visibility"] = "public_on_the_web") + $ws.target.resource.name = /.*dll|.*exe|.*scr|.*jar|.*pif|.*app|.*dmg|.*pkg|.*elf|.*so|.*bin|.*deb|.*rpm|.*sh|.*hta|.*lnk/ + + outcome: + $risk_score = max(35) + $mitre_attack_tactic = "Execution" + $mitre_attack_technique = "User Execution: Malicious File" + $mitre_attack_technique_id = "T1204.002" + $event_count = count_distinct($ws.metadata.id) + $product_event_type = $ws.metadata.product_event_type + $userid = $ws.principal.user.userid + $doc_type = $ws.src.resource.attribute.labels["doc_type"] + $owner = $ws.target.resource.attribute.labels["owner"] + $doc_name = $ws.target.resource.name + //$doc_id = $ws.target.resource.product_object_id + + condition: + $ws +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule google_workspace_user_unsuspended { + + meta: + author = "Google Cloud Security" + description = "Identifies when a user account is unsuspended in Google Workspace." + rule_id = "mr_6bf3e4c9-b380-4562-9aa8-6416a9126ee1" + rule_name = "Google Workspace User Unsuspended" + mitre_attack_tactic = "Initial Access" + mitre_attack_technique = "Valid Accounts: Cloud Accounts" + mitre_attack_url = "https://attack.mitre.org/techniques/T1078/004/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "Workspace Activity" + severity = "Medium" + priority = "Medium" + + events: + $ws.metadata.vendor_name = "Google Workspace" + $ws.metadata.product_name = "admin" + $ws.metadata.product_event_type = "UNSUSPEND_USER" + + outcome: + $risk_score = max(35) + $mitre_attack_tactic = "Initial Access" + $mitre_attack_technique = "Valid Accounts: Cloud Accounts" + $mitre_attack_technique_id = "T1078.004" + $event_count = count_distinct($ws.metadata.id) + $principal_ip = array_distinct($ws.principal.ip) + $principal_country = array_distinct($ws.principal.ip_geo_artifact.location.country_or_region) + $principal_state = array_distinct($ws.principal.ip_geo_artifact.location.state) + $principal_user_emails = array_distinct($ws.principal.user.email_addresses) + $target_user_emails = array_distinct($ws.target.user.email_addresses) + $principal_user_id = $ws.principal.user.userid + + condition: + $ws +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule google_workspace_multiple_files_sent_as_email_attachment_from_google_drive { + + meta: + author = "Google Cloud Security" + description = "Identifies when a user sends multiple files from Google Drive as an email attachment to a free email domain, which may indicate data exfiltration." + rule_id = "mr_125c517c-3ef9-4687-8af6-d71eff83d0e9" + rule_name = "Google Workspace Multiple Files Sent As Email Attachments From Google Drive" + mitre_attack_tactic = "Exfiltration" + mitre_attack_technique = "Exfiltration Over Web Service" + mitre_attack_url = "https://attack.mitre.org/techniques/T1567/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "Workspace Activity" + severity = "High" + priority = "High" + + events: + $email.metadata.vendor_name = "Google Workspace" + $email.metadata.product_name = "drive" + $email.metadata.event_type = "EMAIL_TRANSACTION" + $email.metadata.product_event_type = "email_as_attachment" + $email.target.user.email_addresses = /.*@gmail\.com|.*@aol\.com|.*@ymail\.com|.*@ymail\.com|.*@hotmail\.com|.*@outlook\.com|.*@icloud\.com/ + $email.principal.user.userid = $user_id + + match: + $user_id over 1h + + outcome: + $risk_score = max(75) + $mitre_attack_tactic = "Exfiltration" + $mitre_attack_technique = "Exfiltration Over Web Service" + $mitre_attack_technique_id = "T1567" + $event_count = count_distinct($email.metadata.id) + $product_event_type = array_distinct($email.metadata.product_event_type) + $userid = array_distinct($email.principal.user.userid) + $doc_type = array_distinct($email.src.resource.attribute.labels["doc_type"]) + $owner = array_distinct($email.target.resource.attribute.labels["owner"]) + $target_emails = array_distinct($email.target.user.email_addresses) + $doc_name = array_distinct($email.target.resource.name) + $doc_id = array_distinct($email.target.resource.product_object_id) + $count_docs = count_distinct($email.target.resource.product_object_id) + + condition: + // Customize the value of $count_docs to set the alerting threshold for your environment + $email and $count_docs > 10 +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule google_workspace_external_user_added_to_group { + + meta: + author = "Google Cloud Security" + description = "Identifies when an external user account is added to a group in Google Workspace. Security teams can monitor for unexpected user accounts being added to Google Workspace groups to prevent unauthorized access to data." + rule_id = "mr_c64af222-e029-4add-ac9c-b9285c5eb135" + rule_name = "Google Workspace External User Added To Group" + mitre_attack_tactic = "Initial Access" + mitre_attack_technique = "Valid Accounts: Cloud Accounts" + mitre_attack_url = "https://attack.mitre.org/techniques/T1078/004/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "Workspace Activity" + severity = "Medium" + priority = "Medium" + + events: + $ws.metadata.vendor_name = "Google Workspace" + $ws.metadata.product_name = "admin" + $ws.metadata.event_type = "GROUP_MODIFICATION" + $ws.metadata.product_event_type = "ADD_GROUP_MEMBER" + + $group_domain = re.capture($ws.target.group.email_addresses, `@[a-zA-Z0-9\.]*`) + $user_domain = re.capture($ws.src.user.email_addresses, `@[a-zA-Z0-9\.]*`) + + $group_domain != $user_domain + + outcome: + $risk_score = max(35) + $mitre_attack_tactic = "Initial Access" + $mitre_attack_technique = "Valid Accounts: Cloud Accounts" + $mitre_attack_technique_id = "T1078.004" + $event_count = count_distinct($ws.metadata.id) + $target_group_domain = $group_domain + $src_user_domain = $user_domain + $target_group_emails = array_distinct($ws.target.group.email_addresses) + $src_user_emails = array_distinct($ws.src.user.email_addresses) + $principal_ip = array_distinct($ws.principal.ip) + $principal_country = array_distinct($ws.principal.ip_geo_artifact.location.country_or_region) + $principal_state = array_distinct($ws.principal.ip_geo_artifact.location.state) + $principal_user_emails = array_distinct($ws.principal.user.email_addresses) + $principal_user_id = $ws.principal.user.userid + + condition: + $ws +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule google_workspace_application_added { + + meta: + author = "Google Cloud Security" + description = "Identifies when a Marketplace app is added in a Google Workspace organization. Installing certain apps may increase the organization's risk of data exfiltration/leakage and increase its attack surface." + rule_id = "mr_bb4f5ff0-76b8-4b08-8b1b-fcb81e5a10cc" + rule_name = "Google Workspace Application Added" + mitre_attack_tactic = "Persistence" + mitre_attack_technique = "" + mitre_attack_url = "" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "Workspace Activity" + severity = "High" + priority = "High" + + events: + $ws.metadata.vendor_name = "Google Workspace" + $ws.metadata.product_name = "admin" + $ws.metadata.product_event_type = "ADD_APPLICATION" + + outcome: + $risk_score = max(75) + $mitre_attack_tactic = "Persistence" + $mitre_attack_technique = "" + $mitre_attack_technique_id = "" + $event_count = count_distinct($ws.metadata.id) + $principal_ip = array_distinct($ws.principal.ip) + $principal_country = array_distinct($ws.principal.ip_geo_artifact.location.country_or_region) + $principal_state = array_distinct($ws.principal.ip_geo_artifact.location.state) + $principal_user_emails = array_distinct($ws.principal.user.email_addresses) + $principal_user_id = array_distinct($ws.principal.user.userid) + $target_application = $ws.target.application + $application_enabled = $ws.target.labels["application_enabled"] + $application_id = $ws.target.resource.name + + condition: + $ws +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule google_workspace_user_ou_changed { + + meta: + author = "Google Cloud Security" + description = "Identifies when a Google Workspace user account is moved between Organizational Units." + rule_id = "mr_e265b499-9a83-4e7d-acf8-ae7674e1c743" + rule_name = "Google Workspace User Ou Changed" + mitre_attack_tactic = "Persistence" + mitre_attack_technique = "Account Manipulation: Additional Cloud Roles" + mitre_attack_url = "https://attack.mitre.org/techniques/T1098/003/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "Workspace Activity" + severity = "High" + priority = "High" + + events: + $ws.metadata.vendor_name = "Google Workspace" + $ws.metadata.product_name = "admin" + $ws.metadata.product_event_type = "MOVE_USER_TO_ORG_UNIT" + $ws.security_result.category_details = "USER_SETTINGS" + + outcome: + $risk_score = max(70) + $mitre_attack_tactic = "Persistence" + $mitre_attack_technique = "Account Manipulation: Additional Cloud Roles" + $mitre_attack_technique_id = "T1098.003" + $event_count = count_distinct($ws.metadata.id) + $principal_ip = array_distinct($ws.principal.ip) + $principal_country = array_distinct($ws.principal.ip_geo_artifact.location.country_or_region) + $principal_state = array_distinct($ws.principal.ip_geo_artifact.location.state) + $principal_user_emails = array_distinct($ws.principal.user.email_addresses) + $target_user_emails = array_distinct($ws.target.user.email_addresses) + $principal_user_id = $ws.principal.user.userid + $old_org_unit_name = $ws.about.labels["org_unit_name"] + $new_org_unit_name = $ws.target.user.attribute.labels["new_value"] + + condition: + $ws +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule google_workspace_marketplace_allowlist_configuration { + + meta: + author = "Google Cloud Security" + description = "Identifies when the Google Workspace Marketplace allowlist is configured to allow users to install and run any apps from the Marketplace. Allowing users to install and run any apps may increase the organization's risk of data exfiltration/leakage and increase its attack surface." + rule_id = "mr_3dd74ce1-27cb-4c57-b4cf-4cfb29293ab5" + rule_name = "Google Workspace Marketplace Allowlist Configuration" + mitre_attack_tactic = "Defense Evasion" + mitre_attack_technique = "Impair Defenses: Disable or Modify Tools" + mitre_attack_url = "https://attack.mitre.org/techniques/T1562/001/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "Workspace Activity" + severity = "Low" + priority = "Low" + + events: + $ws.metadata.vendor_name = "Google Workspace" + $ws.metadata.product_name = "admin" + $ws.metadata.product_event_type = "CHANGE_APPLICATION_SETTING" + $ws.security_result.category_details = "APPLICATION_SETTINGS" + $ws.target.application = "Google Workspace Marketplace" + $ws.target.resource.name = "Apps Access Setting Allowlist access" + $ws.target.resource.attribute.labels["new_value"] = "ALLOW_ALL" + + outcome: + $risk_score = max(35) + $mitre_attack_tactic = "Defense Evasion" + $mitre_attack_technique = "Impair Defenses: Disable or Modify Tools" + $mitre_attack_technique_id = "T1562.001" + $event_count = count_distinct($ws.metadata.id) + $principal_ip = array_distinct($ws.principal.ip) + $principal_country = array_distinct($ws.principal.ip_geo_artifact.location.country_or_region) + $principal_state = array_distinct($ws.principal.ip_geo_artifact.location.state) + $principal_user_emails = array_distinct($ws.principal.user.email_addresses) + $principal_user_id = array_distinct($ws.principal.user.userid) + $target_application = $ws.target.application + + condition: + $ws +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule google_workspace_mfa_disabled { + + meta: + author = "Google Cloud Security" + description = "Identifies when multi-factor authentication (MFA) is disabled for a Google Workspace organization. Security teams can monitor for changes to MFA configuration that may weaken the organization's security posture." + rule_id = "mr_63139204-0d18-4410-b4c4-839bc9ccd456" + rule_name = "Google Workspace MFA Disabled" + mitre_attack_tactic = "Persistence" + mitre_attack_technique = "Modify Authentication Process" + mitre_attack_url = "https://attack.mitre.org/techniques/T1556/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "Workspace Activity" + severity = "High" + priority = "High" + + events: + $ws.metadata.vendor_name = "Google Workspace" + $ws.metadata.product_name = "admin" + ($ws.metadata.product_event_type = "ENFORCE_STRONG_AUTHENTICATION" or + $ws.metadata.product_event_type = "ALLOW_STRONG_AUTHENTICATION") + $ws.target.labels["new_value"] = "false" + + outcome: + $risk_score = max(70) + $mitre_attack_tactic = "Persistence" + $mitre_attack_technique = "Modify Authentication Process" + $mitre_attack_technique_id = "T1556" + $event_count = count_distinct($ws.metadata.id) + $principal_ip = array_distinct($ws.principal.ip) + $principal_country = array_distinct($ws.principal.ip_geo_artifact.location.country_or_region) + $principal_state = array_distinct($ws.principal.ip_geo_artifact.location.state) + $principal_user_emails = array_distinct($ws.principal.user.email_addresses) + $target_user_emails = array_distinct($ws.target.user.email_addresses) + $principal_user_id = $ws.principal.user.userid + + condition: + $ws +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule google_workspace_new_trusted_domain_added { + + meta: + author = "Google Cloud Security" + description = "Identifies when a domain is added to the list of trusted domains in Google Workspace. An adversary may attempt to manipulate sharing settings for trusted domains to gain unauthorized access to sensitive files and folders within an organization." + rule_id = "mr_319d97c3-6f63-4a6c-9fab-e70cc3f03aaf" + rule_name = "Google Workspace New Trusted Domain Added" + mitre_attack_tactic = "Defense Evasion" + mitre_attack_technique = "Impair Defenses: Disable or Modify Cloud Firewall" + mitre_attack_url = "https://attack.mitre.org/techniques/T1562/007/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "Workspace Activity" + severity = "High" + priority = "High" + + events: + $ws.metadata.vendor_name = "Google Workspace" + $ws.metadata.product_name = "admin" + $ws.metadata.product_event_type = "ADD_TRUSTED_DOMAINS" + + outcome: + $risk_score = max(75) + $mitre_attack_tactic = "Defense Evasion" + $mitre_attack_technique = "Impair Defenses: Disable or Modify Cloud Firewall" + $mitre_attack_technique_id = "T1562.007" + $event_count = count_distinct($ws.metadata.id) + $principal_ip = array_distinct($ws.principal.ip) + $principal_country = array_distinct($ws.principal.ip_geo_artifact.location.country_or_region) + $principal_state = array_distinct($ws.principal.ip_geo_artifact.location.state) + $principal_user_emails = array_distinct($ws.principal.user.email_addresses) + $principal_user_id = array_distinct($ws.principal.user.userid) + $target_domain = $ws.target.domain.name + + + condition: + $ws + } +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule google_workspace_admin_role_assignment { + + meta: + author = "Google Cloud Security" + description = "Identifies when an administrator role is assigned to a user account in Google Workspace. Security teams can monitor for the malicious or accidental assignment of administrator privileges to prevent unauthorized access to data." + rule_id = "mr_0c547820-1095-42a1-94d8-a00d5ef2df76" + rule_name = "Google Workspace Admin Role Assignment" + mitre_attack_tactic = "Persistence" + mitre_attack_technique = "Account Manipulation: Additional Cloud Roles" + mitre_attack_url = "https://attack.mitre.org/techniques/T1098/003/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "Workspace Activity" + severity = "High" + priority = "High" + + events: + $ws.metadata.vendor_name = "Google Workspace" + $ws.metadata.product_name = "admin" + $ws.metadata.event_type = "USER_RESOURCE_UPDATE_PERMISSIONS" + $ws.metadata.product_event_type = "ASSIGN_ROLE" + $ws.security_result.category_details = "DELEGATED_ADMIN_SETTINGS" + + outcome: + $risk_score = max(35 + + if($ws.target.resource.attribute.roles.name = "_SEED_ADMIN_ROLE", 50) + ) + $mitre_attack_tactic = "Persistence" + $mitre_attack_technique = "Account Manipulation: Additional Cloud Roles" + $mitre_attack_technique_id = "T1098.003" + $event_count = count_distinct($ws.metadata.id) + $principal_ip = array_distinct($ws.principal.ip) + $principal_country = array_distinct($ws.principal.ip_geo_artifact.location.country_or_region) + $principal_state = array_distinct($ws.principal.ip_geo_artifact.location.state) + $principal_user_emails = array_distinct($ws.principal.user.email_addresses) + $target_user_emails = array_distinct($ws.target.user.email_addresses) + $principal_user_id = $ws.principal.user.userid + $role_name = array_distinct($ws.target.resource.attribute.roles.name) + + condition: + $ws +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule high_risk_user_download_executable_from_macro { + + meta: + author = "Google Cloud Security" + description = "Executable downloaded by Microsoft Excel by user with GCP entity relationship" + rule_id = "mr_352c77a7-67b6-4dfb-95e5-75fef8fa4a6c" + rule_name = "High Risk User Download Executable From Macro" + type = "alert" + data_source = "zscaler nss, crowdstrike" + tags = "user entity, resource entity" + severity = "High" + priority = "High" + platform = "Windows" + assumption = "This rule assumes that GCP DLP has been deployed and resources have been assigned to a user context" + mitre_attack_tactic = "Execution" + mitre_attack_technique = "User Execution: Malicious File" + mitre_attack_url = "https://attack.mitre.org/techniques/T1204/002/" + mitre_attack_version = "v13.1" + + events: + // proxy event with suspected executable download + $proxy_event.metadata.event_type = "NETWORK_HTTP" + $proxy_event.target.url = /.*\.exe$/ or + $proxy_event.network.received_bytes > 102400 + $proxy_event.principal.user.userid = $user + $proxy_event.principal.user.userid != /test/ + $proxy_event.target.hostname = $hostname + + // correlate with EDR event indicating Excel activity + $edr_event.target.user.userid = $user + $edr_event.target.process.file.full_path = /excel/ nocase + ($edr_event.metadata.event_type = "NETWORK_HTTP" or $edr_event.metadata.event_type = "NETWORK_CONNECTION") + $edr_event.target.hostname = $hostname + + // first hop into entity graph to find the permissions + $user_entity.graph.entity.user.userid = $user + $user_entity.graph.metadata.entity_type = "USER" + $user_entity.graph.metadata.source_type = "ENTITY_CONTEXT" + $user_entity.graph.relations.entity.resource.name != "" + $user_entity.graph.relations.entity.resource.name = $table_name + + // second hop for the table context + $table_context.graph.entity.resource.product_object_id = $table_name + $table_context.graph.metadata.entity_type = "RESOURCE" + $table_context.graph.metadata.source_type = "ENTITY_CONTEXT" + $table_context.graph.metadata.product_name = "GCP DLP CONTEXT" + + match: + $user, $hostname over 5m + + outcome: + $risk_score = max(if($table_context.graph.entity.resource.attribute.labels.value = "US_SOCIAL_SECURITY_NUMBER", 80)) + $mitre_attack_tactic = array_distinct("Execution") + $mitre_attack_technique = array_distinct("User Execution: Malicious File") + $mitre_attack_technique_id = array_distinct("T1204.002") + $entity_resource_name = array_distinct($table_context.graph.entity.resource.name) + // added to populate alert graph with additional context + $principal_hostname = array_distinct($proxy_event.principal.hostname) + // Commented out target.hostname because it is already represented in graph as match variable. If match changes, can uncomment to add to results + //$target_hostname = array_distinct($proxy_event.target.hostname) + $principal_process_pid = array_distinct($edr_event.principal.process.pid) + $principal_process_command_line = array_distinct($edr_event.principal.process.command_line) + $principal_process_file_sha256 = array_distinct($edr_event.principal.process.file.sha256) + $principal_process_file_full_path = array_distinct($edr_event.principal.process.file.full_path) + $principal_process_product_specific_process_id = array_distinct($edr_event.principal.process.product_specific_process_id) + $principal_process_parent_process_product_specific_process_id = array_distinct($edr_event.principal.process.parent_process.product_specific_process_id) + $target_process_pid = array_distinct($edr_event.target.process.pid) + $target_process_command_line = array_distinct($edr_event.target.process.command_line) + $target_process_file_sha256 = array_distinct($edr_event.target.process.file.sha256) + $target_process_file_full_path = array_distinct($edr_event.target.process.file.full_path) + $target_process_product_specific_process_id = array_distinct($edr_event.target.process.product_specific_process_id) + $target_process_parent_process_product_specific_process_id = array_distinct($edr_event.target.process.parent_process.product_specific_process_id) + // Commented out principal.user.userid because it is already represented in graph as match variable. If match changes, can uncomment to add to results + //$principal_user_userid = array_distinct($edr_event.principal.user.userid) + $target_user_userid = array_distinct($edr_event.target.user.userid) + $target_url = array_distinct($proxy_event.target.url) + + condition: + $proxy_event and $edr_event and $user_entity and $table_context +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule suspicious_asn { + + meta: + author = "Google Cloud Security" + description = "Identify network traffic based on a specific ASN" + rule_id = "mr_da77bdeb-38fc-43c8-8be4-b6c6baa8e92a" + rule_name = "Suspicious ASN" + type = "alert" + tags = "geoip enrichment" + data_source = "microsoft windows events" + severity = "Low" + priority = "Low" + + events: + $network.metadata.event_type = "NETWORK_CONNECTION" + //Specify an autonomoous system number to monitor or add additional ASNs using an or statement + $network.target.ip_geo_artifact.network.asn = "12741" + $network.target.ip = $ip + + match: + $ip over 30m + + outcome: + $risk_score = max(35) + $event_count = count_distinct($network.metadata.id) + // added to populate alert graph with additional context + $principal_ip = array_distinct($network.principal.ip) + // Commented out target.ip because it is already represented in graph as match variable. If match changes, can uncomment to add to results + //$target_ip = array_distinct($network.target.ip) + $principal_process_pid = array_distinct($network.principal.process.pid) + $principal_process_command_line = array_distinct($network.principal.process.command_line) + $principal_process_file_sha256 = array_distinct($network.principal.process.file.sha256) + $principal_process_file_full_path = array_distinct($network.principal.process.file.full_path) + $principal_process_product_specific_process_id = array_distinct($network.principal.process.product_specific_process_id) + $principal_process_parent_process_product_specific_process_id = array_distinct($network.principal.process.parent_process.product_specific_process_id) + $target_process_pid = array_distinct($network.target.process.pid) + $target_process_command_line = array_distinct($network.target.process.command_line) + $target_process_file_sha256 = array_distinct($network.target.process.file.sha256) + $target_process_file_full_path = array_distinct($network.target.process.file.full_path) + $target_process_product_specific_process_id = array_distinct($network.target.process.product_specific_process_id) + $target_process_parent_process_product_specific_process_id = array_distinct($network.target.process.parent_process.product_specific_process_id) + $principal_user_userid = array_distinct($network.principal.user.userid) + $target_user_userid = array_distinct($network.target.user.userid) + + condition: + $network +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule suspicious_asn_watchlist { + + meta: + author = "Google Cloud Security" + description = "Identify any network connections to a list of ASNs" + rule_id = "mr_4b4311e2-8505-4758-8435-dbd951d2ee0d" + rule_name = "Suspicious ASN Watchlist" + type = "alert" + tags = "geoip enrichment, list" + assumption = "List named suspicious_asn needs to be created and populated" + data_source = "microsoft windows events" + severity = "Low" + priority = "Low" + + events: + $network.metadata.event_type = "NETWORK_CONNECTION" + // Specify multiple autonomoous system numbers using a list called suspicious_asn + $network.target.ip_geo_artifact.network.asn in %suspicious_asn + $network.target.ip = $ip + + match: + $ip over 30m + + outcome: + $risk_score = max(35) + $event_count = count_distinct($network.metadata.id) + // added to populate alert graph with additional context + $principal_ip = array_distinct($network.principal.ip) + // Commented out target.ip because it is already represented in graph as match variable. If match changes, can uncomment to add to results + //$target_ip = array_distinct($network.target.ip) + $principal_process_pid = array_distinct($network.principal.process.pid) + $principal_process_command_line = array_distinct($network.principal.process.command_line) + $principal_process_file_sha256 = array_distinct($network.principal.process.file.sha256) + $principal_process_file_full_path = array_distinct($network.principal.process.file.full_path) + $principal_process_product_specific_process_id = array_distinct($network.principal.process.product_specific_process_id) + $principal_process_parent_process_product_specific_process_id = array_distinct($network.principal.process.parent_process.product_specific_process_id) + $target_process_pid = array_distinct($network.target.process.pid) + $target_process_command_line = array_distinct($network.target.process.command_line) + $target_process_file_sha256 = array_distinct($network.target.process.file.sha256) + $target_process_file_full_path = array_distinct($network.target.process.file.full_path) + $target_process_product_specific_process_id = array_distinct($network.target.process.product_specific_process_id) + $target_process_parent_process_product_specific_process_id = array_distinct($network.target.process.parent_process.product_specific_process_id) + $principal_user_userid = array_distinct($network.principal.user.userid) + $target_user_userid = array_distinct($network.target.user.userid) + + condition: + $network +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule network_traffic_to_specific_country { + + meta: + author = "Google Cloud Security" + description = "Identify network traffic based on target country" + rule_id = "mr_f1ab5184-771f-48dc-82e6-11a72632fcd5" + rule_name = "Network Traffic To Specific Country" + type = "alert" + tags = "geoip enrichment" + data_source = "microsoft windows events" + severity = "Low" + priority = "Low" + + events: + $network.metadata.event_type = "NETWORK_CONNECTION" + //Specify a country of interest to monitor or add additional countries using an or statement + $network.target.ip_geo_artifact.location.country_or_region = "France" nocase + $network.target.ip = $ip + + match: + $ip over 30m + + outcome: + $risk_score = max(35) + $event_count = count_distinct($network.metadata.id) + // added to populate alert graph with additional context + $principal_ip = array_distinct($network.principal.ip) + // Commented out target.ip because it is already represented in graph as match variable. If match changes, can uncomment to add to results + //$target_ip = array_distinct($network.target.ip) + $principal_process_pid = array_distinct($network.principal.process.pid) + $principal_process_command_line = array_distinct($network.principal.process.command_line) + $principal_process_file_sha256 = array_distinct($network.principal.process.file.sha256) + $principal_process_file_full_path = array_distinct($network.principal.process.file.full_path) + $principal_process_product_specific_process_id = array_distinct($network.principal.process.product_specific_process_id) + $principal_process_parent_process_product_specific_process_id = array_distinct($network.principal.process.parent_process.product_specific_process_id) + $target_process_pid = array_distinct($network.target.process.pid) + $target_process_command_line = array_distinct($network.target.process.command_line) + $target_process_file_sha256 = array_distinct($network.target.process.file.sha256) + $target_process_file_full_path = array_distinct($network.target.process.file.full_path) + $target_process_product_specific_process_id = array_distinct($network.target.process.product_specific_process_id) + $target_process_parent_process_product_specific_process_id = array_distinct($network.target.process.parent_process.product_specific_process_id) + $principal_user_userid = array_distinct($network.principal.user.userid) + $target_user_userid = array_distinct($network.target.user.userid) + + condition: + $network +} +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + rule gcp_admin_privileged_roles_added_to_service_accounts { + + meta: + author = "Google Cloud Security" + description = "Detect when admin privileged roles such as Owner or Editor are added to a Service Account." + rule_id = "mr_9ffebc73-6d73-40bd-8973-2d53a810272f" + rule_name = "GCP Admin Privileged Roles Added To Service Accounts" + mitre_attack_tactic = "Persistence, Privilege Escalation" + mitre_attack_technique = "Account Manipulation: Additional Cloud Roles" + mitre_attack_url = "https://attack.mitre.org/techniques/T1098/003/" + mitre_attack_version = "v14.1" + type = "Alert" + data_source = "GCP Cloud Audit" + platform = "GCP" + severity = "Low" + priority = "Low" + + events: + $gcp.metadata.event_type = "USER_RESOURCE_UPDATE_PERMISSIONS" + $gcp.metadata.log_type = "GCP_CLOUDAUDIT" + $gcp.metadata.product_event_type = "SetIamPolicy" + $gcp.security_result.action = "ALLOW" + $gcp.target.resource.attribute.labels["ser_binding_deltas_action"] = "ADD" + $gcp.target.resource.attribute.labels["ser_binding_deltas_role"] = /roles\/owner.*|roles\/editor.*/ nocase + $gcp.target.resource.attribute.labels["ser_binding_deltas_member"] = /^serviceAccount/ nocase + + outcome: + $risk_score = max(35) + $mitre_attack_tactic = "Persistence, Privilege Escalation" + $mitre_attack_technique = "Account Manipulation: Additional Cloud Roles" + $mitre_attack_technique_id = "T1098.003" + $event_count = count_distinct($gcp.metadata.id) + $network_http_user_agent = array_distinct($gcp.network.http.user_agent) + $principal_ip = array_distinct($gcp.principal.ip) + $principal_ip_country = array_distinct($gcp.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($gcp.principal.ip_geo_artifact.location.state) + $principal_user_id = $gcp.principal.user.userid + $principal_user_display_name = $gcp.principal.user.user_display_name + $target_resource_name = $gcp.target.resource.name + $event_name = $gcp.metadata.product_event_type + $target_email_addresses = array_distinct($gcp.target.user.email_addresses) + + condition: + $gcp +} +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + rule gcp_successful_api_from_tor_exit_node { + + meta: + author = "Google Cloud Security" + description = "Detects successful API executions from a Tor exit node." + rule_id = "mr_5912e2be-4366-4f34-a770-0ac8358f2cb9" + rule_name = "GCP Successful API Call From Tor Exit Node" + mitre_attack_tactic = "Execution" + mitre_attack_technique = "User Execution" + mitre_attack_url = "https://attack.mitre.org/techniques/T1204/" + mitre_attack_version = "v14.1" + type = "Alert" + data_source = "GCP Cloud Audit" + platform = "GCP" + severity = "High" + priority = "High" + + events: + + $gcp.metadata.log_type = "GCP_CLOUDAUDIT" + $gcp.security_result.action = "ALLOW" + $gcp.principal.ip = $ip + + // Tor IP listing provided by GCTI Feed + $gcti_feed.graph.entity.artifact.ip = $ip + $gcti_feed.graph.metadata.entity_type = "IP_ADDRESS" + $gcti_feed.graph.metadata.threat.threat_feed_name = "Tor Exit Nodes" + $gcti_feed.graph.metadata.product_name = "GCTI Feed" + $gcti_feed.graph.metadata.source_type = "GLOBAL_CONTEXT" + + match: + $ip over 5m + + outcome: + $risk_score = max( + //Baseline + 35 + + // Unauthorized geographies + if($gcp.principal.ip_geo_artifact.location.country_or_region = "Cuba", 40) + + if($gcp.principal.ip_geo_artifact.location.country_or_region = "Iran", 40) + + if($gcp.principal.ip_geo_artifact.location.country_or_region = "North Korea" , 40) + + if($gcp.principal.ip_geo_artifact.location.country_or_region = "Russia", 40) + + if($gcp.principal.ip_geo_artifact.location.country_or_region = "Syria", 40) + ) + $mitre_attack_tactic = "Execution" + $mitre_attack_technique = "User Execution" + $mitre_attack_technique_id = "T1204" + $event_count = count_distinct($gcp.metadata.id) + $network_http_user_agent = array_distinct($gcp.network.http.user_agent) + $principal_ip = array_distinct($gcp.principal.ip) + $principal_ip_country = array_distinct($gcp.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($gcp.principal.ip_geo_artifact.location.state) + $principal_user_display_name = array_distinct($gcp.principal.user.user_display_name) + $dc_principal_user_display_name = count_distinct($gcp.principal.user.user_display_name) + $target_resource_name = array_distinct($gcp.target.resource.name) + + condition: + $gcp and $gcti_feed +} +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + rule gcp_bigquery_datasets_opened_to_public { + + meta: + author = "Google Cloud Security" + description = "Detect when GCP BigQuery datasets are opened to public by adding allUsers or allAuthenticatedUsers to the access policy." + rule_id = "mr_6d331411-347b-432e-ba52-ff78e4c66a3f" + rule_name = "GCP BigQuery Datasets Opened To Public" + mitre_attack_tactic = "Defense Evasion" + mitre_attack_technique = "Impair Defenses" + mitre_attack_url = "https://attack.mitre.org/techniques/T1562/" + mitre_attack_version = "v14.1" + type = "Alert" + data_source = "GCP Cloud Audit" + platform = "GCP" + severity = "High" + priority = "High" + + events: + $gcp.metadata.event_type = "USER_RESOURCE_UPDATE_PERMISSIONS" + $gcp.metadata.log_type = "GCP_CLOUDAUDIT" + $gcp.metadata.vendor_name = "Google Cloud Platform" + $gcp.metadata.product_name = "BigQuery" + $gcp.metadata.product_event_type = "google.iam.v1.IAMPolicy.SetIamPolicy" + $gcp.target.application = "bigquery.googleapis.com" + $gcp.security_result.action = "ALLOW" + $gcp.target.resource.attribute.labels["dataset_change_binding_deltas_action"] = "ADD" + $gcp.target.resource.attribute.labels["dataset_change_binding_deltas_role"] = /roles\/bigquery.*/ + $gcp.target.resource.attribute.labels["dataset_change_binding_deltas_member"] = /allUsers|allAuthenticatedUsers/ + $gcp.target.resource.resource_subtype = "bigquery_dataset" + $gcp.target.resource.resource_type = "DATABASE" + + outcome: + $risk_score = max(75) + $mitre_attack_tactic = "Defense Evasion" + $mitre_attack_technique = "Impair Defenses" + $mitre_attack_technique_id = "T1562" + $event_count = count_distinct($gcp.metadata.id) + $network_http_user_agent = array_distinct($gcp.network.http.user_agent) + $principal_ip = array_distinct($gcp.principal.ip) + $principal_ip_country = array_distinct($gcp.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($gcp.principal.ip_geo_artifact.location.state) + $principal_user_id = $gcp.principal.user.userid + $principal_user_display_name = $gcp.principal.user.user_display_name + $target_resource_name = $gcp.target.resource.name + $event_name = $gcp.metadata.product_event_type + + condition: + $gcp +} +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + rule gcp_free_gmail_domains_added_to_iam_policy { + + meta: + author = "Google Cloud Security" + description = "Detect when free Google Email addressess are added to IAM Policy such as gmail.com, googlemail.com or googlegroups.com." + rule_id = "mr_eec293b2-75d6-48f1-871d-182d67345a9c" + rule_name = "GCP Free Gmail Domains Added To IAM Policy" + mitre_attack_tactic = "Persistence" + mitre_attack_technique = "Create Account: Cloud Account" + mitre_attack_url = "https://attack.mitre.org/techniques/T1136/003/" + mitre_attack_version = "v14.1" + type = "Alert" + data_source = "GCP Cloud Audit" + platform = "GCP" + severity = "High" + priority = "High" + + events: + $gcp.metadata.event_type = "USER_RESOURCE_UPDATE_PERMISSIONS" + $gcp.metadata.log_type = "GCP_CLOUDAUDIT" + $gcp.metadata.product_event_type = "SetIamPolicy" + $gcp.metadata.product_name = "Google Cloud Platform" + $gcp.metadata.vendor_name = "Google Cloud Platform" + $gcp.security_result.action = "ALLOW" + $gcp.target.resource.attribute.labels["ser_binding_deltas_action"] = "ADD" + $gcp.target.resource.attribute.labels["ser_binding_deltas_member"] = /.*@gmail\.com|.*@googlemail\.com|.*@googlegroups\.com/ nocase + + outcome: + $risk_score = max(75) + $mitre_attack_tactic = "Persistence" + $mitre_attack_technique = "Create Account: Cloud Account" + $mitre_attack_technique_id = "T1136.003" + $event_count = count_distinct($gcp.metadata.id) + $network_http_user_agent = array_distinct($gcp.network.http.user_agent) + $principal_ip = array_distinct($gcp.principal.ip) + $principal_ip_country = array_distinct($gcp.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($gcp.principal.ip_geo_artifact.location.state) + $principal_user_id = $gcp.principal.user.userid + $principal_user_display_name = $gcp.principal.user.user_display_name + $target_resource_name = $gcp.target.resource.name + $event_name = $gcp.metadata.product_event_type + $target_email_addresses = array_distinct($gcp.target.user.email_addresses) + + condition: + $gcp +} +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + rule gcp_cloud_audit_logging_removed_from_all_services { + + meta: + author = "Google Cloud Security" + description = "Detect when GCP Cloud Audit logs are removed from all services at project or organization level. Audit logging helps organizations maintain security and minimize risk." + rule_id = "mr_6ffed437-4666-433f-8ba8-b6043daef4c5" + rule_name = "GCP Cloud Audit Logging Removed From All Services" + mitre_attack_tactic = "Defense Evasion" + mitre_attack_technique = "Impair Defenses: Disable Cloud Logs" + mitre_attack_url = "https://attack.mitre.org/techniques/T1562/008/" + mitre_attack_version = "v14.1" + type = "Alert" + data_source = "GCP Cloud Audit" + platform = "GCP" + severity = "High" + priority = "High" + + events: + $gcp.metadata.event_type = "USER_RESOURCE_UPDATE_PERMISSIONS" + $gcp.metadata.log_type = "GCP_CLOUDAUDIT" + $gcp.metadata.product_event_type = "SetIamPolicy" + $gcp.security_result.action = "ALLOW" + $gcp.security_result.detection_fields["action"] = "REMOVE" + $gcp.security_result.detection_fields["SERVICE"] = "allServices" + $gcp.target.resource.attribute.labels["ser_type"] = "type.googleapis.com/google.iam.v1.logging.AuditData" + $gcp.target.application = "cloudresourcemanager.googleapis.com" + + outcome: + //Increase risk score if it is organization wide + $risk_score = max(45 + + if($gcp.target.resource.name = /organizations/,30,0) + ) + $mitre_attack_tactic = "Defense Evasion" + $mitre_attack_technique = "Impair Defenses: Disable Cloud Logs" + $mitre_attack_technique_id = "T1562.008" + $event_count = count_distinct($gcp.metadata.id) + $network_http_user_agent = array_distinct($gcp.network.http.user_agent) + $principal_ip = array_distinct($gcp.principal.ip) + $principal_ip_country = array_distinct($gcp.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($gcp.principal.ip_geo_artifact.location.state) + $principal_user_id = $gcp.principal.user.userid + $principal_user_display_name = $gcp.principal.user.user_display_name + $target_resource_name = $gcp.target.resource.name + $event_name = $gcp.metadata.product_event_type + + condition: + $gcp +} +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + rule gcp_firewall_rule_opened_to_world { + + meta: + author = "Google Cloud Security" + description = "Detect when a GCP Firewall rule is opened to the world (0.0.0.0/0) on all protocols." + rule_id = "mr_340c7a66-56ea-498a-bf00-270e9e61fed0" + rule_name = "GCP Firewall Rule Opened To The World" + mitre_attack_tactic = "Defense Evasion" + mitre_attack_technique = "Impair Defenses" + mitre_attack_url = "https://attack.mitre.org/techniques/T1562/" + mitre_attack_version = "v14.1" + type = "Alert" + data_source = "GCP Cloud Audit" + platform = "GCP" + severity = "High" + priority = "High" + + events: + $gcp.metadata.event_type = "RESOURCE_CREATION" + $gcp.metadata.log_type = "GCP_CLOUDAUDIT" + $gcp.metadata.product_event_type = "beta.compute.firewalls.insert" + $gcp.metadata.product_name = "Google Compute Engine" + $gcp.security_result.action = "ALLOW" + $gcp.target.resource.attribute.labels["source_ranges"] = "0.0.0.0/0" + $gcp.security_result.detection_fields["allowed_ipprotocol"] = "all" + $gcp.target.resource.attribute.labels["req_disabled"] = "false" + $gcp.target.resource.attribute.labels["response_status"] = "RUNNING" + + outcome: + $risk_score = max(75) + $mitre_attack_tactic = "Defense Evasion" + $mitre_attack_technique = "Impair Defenses" + $mitre_attack_technique_id = "T1562" + $event_count = count_distinct($gcp.metadata.id) + $network_http_user_agent = array_distinct($gcp.network.http.user_agent) + $principal_ip = array_distinct($gcp.principal.ip) + $principal_ip_country = array_distinct($gcp.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($gcp.principal.ip_geo_artifact.location.state) + $principal_user_id = $gcp.principal.user.userid + $principal_user_display_name = $gcp.principal.user.user_display_name + $target_resource_name = $gcp.target.resource.name + $event_name = $gcp.metadata.product_event_type + + condition: + $gcp +} +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + rule gcp_service_account_key_used_from_multiple_countries { + + meta: + author = "Google Cloud Security" + description = "Detects usage of service account key from multiple countries using Chronicle GeoIP enrichment." + rule_id = "mr_dbc9cf09-7c2d-4c9e-b9d4-60df60f360a1" + rule_name = "GCP Service Account Key Used From Multiple Countries" + mitre_attack_tactic = "Credential Access" + mitre_attack_technique = "Unsecured Credentials: Private Keys" + mitre_attack_url = "https://attack.mitre.org/techniques/T1552/004/" + mitre_attack_version = "v14.1" + type = "Alert" + data_source = "GCP Cloud Audit" + platform = "GCP" + severity = "Low" + priority = "Low" + + events: + $gcp.metadata.log_type = "GCP_CLOUDAUDIT" + $gcp.security_result.action = "ALLOW" + $gcp.principal.ip_geo_artifact.location.country_or_region != "" + $gcp.principal.ip_geo_artifact.network.organization_name != /google/ + $gcp.security_result.detection_fields["key_id"] = $sa_key_id + + match: + $sa_key_id over 1h + + outcome: + $risk_score = max(35) + $mitre_attack_tactic = "Credential Access" + $mitre_attack_technique = "Unsecured Credentials: Private Keys" + $mitre_attack_technique_id = "T1552.004" + $event_count = count_distinct($gcp.metadata.id) + $network_http_user_agent = array_distinct($gcp.network.http.user_agent) + $principal_ip = array_distinct($gcp.principal.ip) + $principal_ip_country = array_distinct($gcp.principal.ip_geo_artifact.location.country_or_region) + $dc_principal_ip_country = count_distinct($gcp.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($gcp.principal.ip_geo_artifact.location.state) + $principal_user_display_name = array_distinct($gcp.principal.user.user_display_name) + $target_resource_name = array_distinct($gcp.target.resource.name) + $sa_key_name = array_distinct($gcp.security_result.detection_fields["service_account_key_name"]) + + condition: + $gcp and $dc_principal_ip_country > 2 +} +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule gcp_multiple_hmac_keys_deleted { + + meta: + author = "Google Cloud Security" + description = "Detect when multiple HMAC authentication keys are deleted from GCP Storage settings." + rule_id = "mr_75b441f1-edde-4a33-bc12-06a92ccb9ba8" + rule_name = "GCP Multiple HMAC Keys Deleted" + mitre_attack_tactic = "Impact" + mitre_attack_technique = "Account Access Removal" + mitre_attack_url = "https://attack.mitre.org/techniques/T1531/" + mitre_attack_version = "v14.1" + type = "Alert" + data_source = "GCP Cloud Audit" + platform = "GCP" + severity = "High" + priority = "High" + + events: + $gcp.metadata.event_type = "RESOURCE_DELETION" + $gcp.metadata.log_type = "GCP_CLOUDAUDIT" + $gcp.metadata.product_event_type = "storage.hmacKeys.delete" + $gcp.target.application = "storage.googleapis.com" + $gcp.target.user.userid = $user_id + + match: + $user_id over 1h + + outcome: + $risk_score = max(75) + $mitre_attack_tactic = "Impact" + $mitre_attack_technique = "Account Access Removal" + $mitre_attack_technique_id = "T1531" + $event_count = count_distinct($gcp.metadata.id) + $network_http_user_agent = array_distinct($gcp.network.http.user_agent) + $principal_ip = array_distinct($gcp.principal.ip) + $principal_ip_country = array_distinct($gcp.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($gcp.principal.ip_geo_artifact.location.state) + $principal_user_id = array_distinct($gcp.principal.user.userid) + $principal_user_display_name = array_distinct($gcp.principal.user.user_display_name) + $target_resource_name = array_distinct($gcp.target.resource.name) + + condition: + #gcp >= 2 +} +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + rule gcp_excessive_permission_denied_events { + + meta: + author = "Google Cloud Security" + description = "Detects excessive PermissionDenied events within an hour timeframe from a user" + rule_id = "mr_2edbd86a-703a-41a3-b2b2-596dd9dbed8d" + rule_name = "GCP Excessive Permission Denied Events" + mitre_attack_tactic = "Discovery" + mitre_attack_technique = "Cloud Infrastructure Discovery" + mitre_attack_url = "https://attack.mitre.org/techniques/T1580/" + mitre_attack_version = "v14.1" + type = "Alert" + data_source = "GCP Cloud Audit" + platform = "GCP" + severity = "Low" + priority = "Low" + + events: + $gcp.metadata.log_type = "GCP_CLOUDAUDIT" + $gcp.security_result.action = "BLOCK" + $gcp.security_result.severity = "ERROR" + $gcp.security_result.detection_fields["status_code"] = "7" + $gcp.principal.user.userid = $user_id + $gcp.target.application = $target_application + $gcp.metadata.product_event_type = $product_event_type + + match: + $user_id over 1h + + outcome: + $risk_score = max(35) + $mitre_attack_tactic = "Discovery" + $mitre_attack_technique = "Cloud Infrastructure Discovery" + $mitre_attack_technique_id = "T1580" + $event_count = count_distinct($gcp.metadata.id) + $network_http_user_agent = array_distinct($gcp.network.http.user_agent) + $principal_ip = array_distinct($gcp.principal.ip) + $principal_ip_country = array_distinct($gcp.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($gcp.principal.ip_geo_artifact.location.state) + $principal_user_display_name = array_distinct($gcp.principal.user.user_display_name) + $target_resource_name = array_distinct($gcp.target.resource.name) + + condition: + #gcp > 5 and #target_application > 1 and #product_event_type > 1 +} +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + rule gcp_storage_bucket_opened_to_public { + + meta: + author = "Google Cloud Security" + description = "Detect when Google Cloud Storage buckets are opened to public by adding allUsers or allAuthenticatedUsers to the access policy." + rule_id = "mr_b776abb0-9e7b-444d-ae0f-8a88b5654ded" + rule_name = "GCP Storage Bucket Opened To Public" + mitre_attack_tactic = "Defense Evasion" + mitre_attack_technique = "Impair Defenses" + mitre_attack_url = "https://attack.mitre.org/techniques/T1562/" + mitre_attack_version = "v14.1" + type = "Alert" + data_source = "GCP Cloud Audit" + platform = "GCP" + severity = "High" + priority = "High" + + events: + $gcp.metadata.event_type = "USER_RESOURCE_UPDATE_PERMISSIONS" + $gcp.metadata.log_type = "GCP_CLOUDAUDIT" + $gcp.metadata.vendor_name = "Google Cloud Platform" + $gcp.metadata.product_name = "Google Cloud Storage" + $gcp.metadata.product_event_type = "storage.setIamPermissions" + $gcp.target.application = "storage.googleapis.com" + $gcp.security_result.action = "ALLOW" + $gcp.target.resource.attribute.labels["ser_binding_deltas_action"] = "ADD" + $gcp.target.resource.attribute.labels["ser_binding_deltas_role"] = /roles\/storage.*/ + $gcp.target.resource.attribute.labels["ser_binding_deltas_member"] = /allUsers|allAuthenticatedUsers/ + $gcp.target.resource.resource_type = "STORAGE_BUCKET" + + outcome: + $risk_score = max(75) + $mitre_attack_tactic = "Defense Evasion" + $mitre_attack_technique = "Impair Defenses" + $mitre_attack_technique_id = "T1562" + $event_count = count_distinct($gcp.metadata.id) + $network_http_user_agent = array_distinct($gcp.network.http.user_agent) + $principal_ip = array_distinct($gcp.principal.ip) + $principal_ip_country = array_distinct($gcp.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($gcp.principal.ip_geo_artifact.location.state) + $principal_user_id = $gcp.principal.user.userid + $principal_user_display_name = $gcp.principal.user.user_display_name + $target_resource_name = $gcp.target.resource.name + $event_name = $gcp.metadata.product_event_type + + condition: + $gcp +} +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + rule gcp_iam_organization_policy_updated_or_deleted { + + meta: + author = "Google Cloud Security" + description = "Detect when GCP IAM Organization Policy is updated or deleted." + rule_id = "mr_327c1753-1cd5-424a-8a9f-1648278e2831" + rule_name = "GCP IAM Organization Policy Updated Or Deleted" + mitre_attack_tactic = "Persistence, Privilege Escalation" + mitre_attack_technique = "Account Manipulation" + mitre_attack_url = "https://attack.mitre.org/techniques/T1098/" + mitre_attack_version = "v14.1" + type = "Alert" + data_source = "GCP Cloud Audit" + platform = "GCP" + severity = "High" + priority = "High" + + events: + $gcp.metadata.log_type = "GCP_CLOUDAUDIT" + ( + ($gcp.metadata.event_type = "RESOURCE_WRITTEN" and $gcp.metadata.product_event_type = "google.cloud.orgpolicy.v2.OrgPolicy.UpdatePolicy") or + ($gcp.metadata.event_type = "RESOURCE_DELETION" and $gcp.metadata.product_event_type = "google.cloud.orgpolicy.v2.OrgPolicy.DeletePolicy") + ) + $gcp.security_result.action = "ALLOW" + $gcp.target.application = "orgpolicy.googleapis.com" + + outcome: + $risk_score = max(75) + $mitre_attack_tactic = "Persistence, Privilege Escalation" + $mitre_attack_technique = "Account Manipulation" + $mitre_attack_technique_id = "T1098" + $event_count = count_distinct($gcp.metadata.id) + $network_http_user_agent = array_distinct($gcp.network.http.user_agent) + $principal_ip = array_distinct($gcp.principal.ip) + $principal_ip_country = array_distinct($gcp.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($gcp.principal.ip_geo_artifact.location.state) + $principal_user_id = $gcp.principal.user.userid + $principal_user_display_name = $gcp.principal.user.user_display_name + $target_resource_name = $gcp.target.resource.name + $event_name = $gcp.metadata.product_event_type + + condition: + $gcp +} +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + rule gcp_gce_image_open_to_public { + + meta: + author = "Google Cloud Security" + description = "Detect when GCP Compute Image is opened to public by adding allAuthenticatedUsers to the access policy." + rule_id = "mr_4a1525be-9e17-41d6-ba67-a11058ee4d3c" + rule_name = "GCP GCE Image Open To Public" + mitre_attack_tactic = "Exfiltration" + mitre_attack_technique = "Transfer Data to Cloud Account" + mitre_attack_url = "https://attack.mitre.org/techniques/T1537/" + mitre_attack_version = "v14.1" + type = "Alert" + data_source = "GCP Cloud Audit" + platform = "GCP" + severity = "High" + priority = "High" + + events: + $gcp.metadata.event_type = "USER_RESOURCE_UPDATE_PERMISSIONS" + $gcp.metadata.log_type = "GCP_CLOUDAUDIT" + $gcp.metadata.vendor_name = "Google Cloud Platform" + $gcp.metadata.product_event_type = "beta.compute.images.setIamPolicy" + $gcp.target.application = "compute.googleapis.com" + $gcp.security_result.action = "ALLOW" + any $gcp.target.resource.attribute.labels.value = "allAuthenticatedUsers" + $gcp.target.resource.resource_subtype = "gce_image" + + outcome: + $risk_score = max(75) + $mitre_attack_tactic = "Exfiltration" + $mitre_attack_technique = "Transfer Data to Cloud Account" + $mitre_attack_technique_id = "T1537" + $event_count = count_distinct($gcp.metadata.id) + $network_http_user_agent = array_distinct($gcp.network.http.user_agent) + $principal_ip = array_distinct($gcp.principal.ip) + $principal_ip_country = array_distinct($gcp.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($gcp.principal.ip_geo_artifact.location.state) + $principal_user_id = $gcp.principal.user.userid + $principal_user_display_name = $gcp.principal.user.user_display_name + $target_resource_name = $gcp.target.resource.name + $event_name = $gcp.metadata.product_event_type + $target_email_addresses = array_distinct($gcp.target.user.email_addresses) + + condition: + $gcp +} +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + rule gcp_multiple_kms_keys_disabled_or_destroyed { + + meta: + author = "Google Cloud Security" + description = "Detect when multiple KMS crypto key versions are disabled or destroyed from GCP Cloud KMS." + rule_id = "mr_1457dcf4-b20b-4ec0-a295-d04074889991" + rule_name = "GCP Multiple KMS Keys Disabled Or Destroyed" + mitre_attack_tactic = "Impact" + mitre_attack_technique = "Data Destruction" + mitre_attack_url = "https://attack.mitre.org/techniques/T1485/" + mitre_attack_version = "v14.1" + type = "Alert" + data_source = "GCP Cloud Audit" + platform = "GCP" + severity = "High" + priority = "High" + + events: + $gcp.metadata.log_type = "GCP_CLOUDAUDIT" + ( + $gcp.metadata.product_event_type = "DestroyCryptoKeyVersion" or + ( + $gcp.metadata.product_event_type = "UpdateCryptoKeyVersion" and + $gcp.target.resource.attribute.labels["req_cryptokey_version_state"] = "DISABLED" + ) + ) + $gcp.target.application = "cloudkms.googleapis.com" + $gcp.security_result.action = "ALLOW" + $gcp.target.user.userid = $user_id + + match: + $user_id over 1h + + outcome: + $risk_score = max(75) + $mitre_attack_tactic = "Impact" + $mitre_attack_technique = "Data Destruction" + $mitre_attack_technique_id = "T1485" + $event_count = count_distinct($gcp.metadata.id) + $network_http_user_agent = array_distinct($gcp.network.http.user_agent) + $principal_ip = array_distinct($gcp.principal.ip) + $principal_ip_country = array_distinct($gcp.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($gcp.principal.ip_geo_artifact.location.state) + $principal_user_id = array_distinct($gcp.principal.user.userid) + $principal_user_display_name = array_distinct($gcp.principal.user.user_display_name) + $target_resource_name = array_distinct($gcp.target.resource.name) + + condition: + #gcp >= 10 +} +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + rule gcp_security_command_center_service_disabled { + + meta: + author = "Google Cloud Security" + description = "Detect when GCP Security Command Center services are disabled." + rule_id = "mr_0d065dd8-4489-434a-bb6e-066537318484" + rule_name = "GCP Security Command Center Service Disabled" + mitre_attack_tactic = "Defense Evasion" + mitre_attack_technique = "Impair Defenses" + mitre_attack_url = "https://attack.mitre.org/techniques/T1562/" + mitre_attack_version = "v14.1" + type = "Alert" + data_source = "GCP Cloud Audit" + platform = "GCP" + severity = "High" + priority = "High" + + events: + $gcp.metadata.event_type = "RESOURCE_WRITTEN" + $gcp.metadata.log_type = "GCP_CLOUDAUDIT" + $gcp.metadata.product_event_type = /google.cloud.securitycenter.settings.*.Settings.Update/ + $gcp.security_result.action = "ALLOW" + $gcp.target.application = "securitycenter.googleapis.com" + $gcp.target.resource.attribute.labels["service_enablement_state"] = "DISABLED" + + outcome: + $risk_score = max(75) + $mitre_attack_tactic = "Defense Evasion" + $mitre_attack_technique = "Impair Defenses" + $mitre_attack_technique_id = "T1562" + $event_count = count_distinct($gcp.metadata.id) + $network_http_user_agent = $gcp.network.http.user_agent + $principal_ip = array_distinct($gcp.principal.ip) + $principal_ip_country = array_distinct($gcp.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($gcp.principal.ip_geo_artifact.location.state) + $principal_user_id = $gcp.principal.user.userid + $principal_user_display_name = $gcp.principal.user.user_display_name + $target_resource_name = $gcp.target.resource.name + + condition: + $gcp +} +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + rule gcp_multiple_secrets_deleted { + + meta: + author = "Google Cloud Security" + description = "Detect when multiple secrets or secret versions are deleted from GCP Secret Manager." + rule_id = "mr_c91c9fe8-6569-4764-a8d8-9b88dd3b7f77" + rule_name = "GCP Multiple Secrets Deleted" + mitre_attack_tactic = "Impact" + mitre_attack_technique = "Data Destruction" + mitre_attack_url = "https://attack.mitre.org/techniques/T1485/" + mitre_attack_version = "v14.1" + type = "Alert" + data_source = "GCP Cloud Audit" + platform = "GCP" + severity = "High" + priority = "High" + + events: + $gcp.metadata.log_type = "GCP_CLOUDAUDIT" + ( + $gcp.metadata.product_event_type = "google.cloud.secretmanager.v1.SecretManagerService.DestroySecretVersion" or + $gcp.metadata.product_event_type = "google.cloud.secretmanager.v1.SecretManagerService.DeleteSecret" + ) + $gcp.target.application = "secretmanager.googleapis.com" + $gcp.security_result.action = "ALLOW" + $gcp.target.user.userid = $user_id + + match: + $user_id over 1h + + outcome: + $risk_score = max(75) + $mitre_attack_tactic = "Impact" + $mitre_attack_technique = "Data Destruction" + $mitre_attack_technique_id = "T1485" + $event_count = count_distinct($gcp.metadata.id) + $network_http_user_agent = array_distinct($gcp.network.http.user_agent) + $principal_ip = array_distinct($gcp.principal.ip) + $principal_ip_country = array_distinct($gcp.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($gcp.principal.ip_geo_artifact.location.state) + $principal_user_id = array_distinct($gcp.principal.user.userid) + $principal_user_display_name = array_distinct($gcp.principal.user.user_display_name) + $target_resource_name = array_distinct($gcp.target.resource.name) + + condition: + #gcp >= 10 +} +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + rule gcp_workload_identity_pool_disabled_or_deleted { + + meta: + author = "Google Cloud Security" + description = "Detect when GCP Workload identity pools are disabled or deleted. Disabling or deleting a pool will prevent any connected identities from accessing all GCP resources." + rule_id = "mr_265fbe68-80c6-48b0-a211-dca6bcef0fd2" + rule_name = "GCP Workload Identity Pool Disabled Or Deleted" + mitre_attack_tactic = "Defense Evasion, Persistence, Privilege Escalation, Initial Access" + mitre_attack_technique = "Valid Accounts: Cloud Accounts" + mitre_attack_url = "https://attack.mitre.org/techniques/T1078/004/" + mitre_attack_version = "v14.1" + type = "Alert" + data_source = "GCP Cloud Audit" + platform = "GCP" + severity = "High" + priority = "High" + + events: + $gcp.metadata.log_type = "GCP_CLOUDAUDIT" + ( + $gcp.metadata.product_event_type = "google.iam.v1.WorkloadIdentityPools.DeleteWorkloadIdentityPool" or + ( + $gcp.metadata.product_event_type = "google.iam.v1.WorkloadIdentityPools.UpdateWorkloadIdentityPool" and + $gcp.target.resource.attribute.labels["req_identityPool_disabled"] = "true" + ) + ) + $gcp.target.application = "iam.googleapis.com" + $gcp.security_result.action = "ALLOW" + + outcome: + $risk_score = max(75) + $mitre_attack_tactic = "Defense Evasion, Persistence, Privilege Escalation, Initial Access" + $mitre_attack_technique = "Valid Accounts: Cloud Accounts" + $mitre_attack_technique_id = "T1078.004" + $event_count = count_distinct($gcp.metadata.id) + $network_http_user_agent = array_distinct($gcp.network.http.user_agent) + $principal_ip = array_distinct($gcp.principal.ip) + $principal_ip_country = array_distinct($gcp.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($gcp.principal.ip_geo_artifact.location.state) + $principal_user_id = $gcp.principal.user.userid + $principal_user_display_name = $gcp.principal.user.user_display_name + $target_resource_name = $gcp.target.resource.name + $event_name = $gcp.metadata.product_event_type + + condition: + $gcp +} +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + rule gcp_multiple_service_apis_disabled { + + meta: + author = "Google Cloud Security" + description = "Detect when multiple GCP Service APIs are disabled in a short period of time." + rule_id = "mr_5a4ce357-e4da-4a4b-8cc2-ed5515f1043d" + rule_name = "GCP Multiple Service APIs Disabled" + mitre_attack_tactic = "Impact" + mitre_attack_technique = "Service Stop" + mitre_attack_url = "https://attack.mitre.org/techniques/T1489/" + mitre_attack_version = "v14.1" + type = "Alert" + data_source = "GCP Cloud Audit" + platform = "GCP" + severity = "High" + priority = "High" + + events: + $gcp.metadata.event_type = "USER_RESOURCE_UPDATE_CONTENT" + $gcp.metadata.log_type = "GCP_CLOUDAUDIT" + $gcp.metadata.product_event_type = "google.api.serviceusage.v1.ServiceUsage.DisableService" + $gcp.security_result.action = "ALLOW" + $gcp.target.application = "serviceusage.googleapis.com" + $gcp.principal.user.userid = $userid + + match: + $userid over 1h + + outcome: + $risk_score = max(75) + $mitre_attack_tactic = "Impact" + $mitre_attack_technique = "Service Stop" + $mitre_attack_technique_id = "T1489" + $event_count = count_distinct($gcp.metadata.id) + $network_http_user_agent = array_distinct($gcp.network.http.user_agent) + $principal_ip = array_distinct($gcp.principal.ip) + $principal_ip_country = array_distinct($gcp.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($gcp.principal.ip_geo_artifact.location.state) + $principal_user_id = array_distinct($gcp.principal.user.userid) + $principal_user_display_name = array_distinct($gcp.principal.user.user_display_name) + $target_resource_name = array_distinct($gcp.target.resource.name) + $dc_target_resource_name = count_distinct($gcp.target.resource.name) + + condition: + $gcp and $dc_target_resource_name > 5 +} +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +rule google_cloud_service_account_key_created_or_uploaded { + + meta: + author = "Google Cloud Security" + description = "Detects when a service account key is created in or uploaded to a monitored Google Cloud project." + rule_id = "mr_751d64b3-2aef-4c5b-bf39-abc6577f6ce8" + rule_name = "Google Cloud Service Account Key Created or Uploaded" + assumption = "Google SecOps is ingesting Google Cloud logs. Reference: https://cloud.google.com/chronicle/docs/ingestion/cloud/ingest-gcp-logs" + type = "alert" + severity = "Medium" + priority = "Medium" + platform = "Google Cloud" + data_source = "GCP Cloud Audit" + mitre_attack_tactic = "Persistence" + mitre_attack_technique = "Account Manipulation: Additional Cloud Credentials" + mitre_attack_url = "https://attack.mitre.org/techniques/T1098/001/" + mitre_attack_version = "v15" + reference = "https://cloud.google.com/iam/docs/best-practices-for-managing-service-account-keys" + + events: + $gc.metadata.log_type = "GCP_CLOUDAUDIT" + $gc.metadata.product_name = "Google Cloud IAM" + ( + $gc.metadata.product_event_type = "google.iam.admin.v1.CreateServiceAccountKey" or + $gc.metadata.product_event_type = "google.iam.admin.v1.UploadServiceAccountKey" + ) + $gc.security_result.action = "ALLOW" + $gc.security_result.detection_fields["key_id"] = $sa_key_id + + match: + $sa_key_id over 30m + + outcome: + $risk_score = max(65) + $mitre_attack_tactic = "Persistence" + $mitre_attack_technique = "Account Manipulation: Additional Cloud Credentials" + $mitre_attack_technique_id = "T1098.001" + $event_count = count_distinct($gc.metadata.id) + $principal_ip = array_distinct($gc.principal.ip) + $principal_user_userid = array_distinct($gc.principal.user.userid) + $principal_ip_country = array_distinct($gc.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($gc.principal.ip_geo_artifact.location.state) + $principal_ip_city = array_distinct($gc.principal.location.city) + $security_result_summary = array_distinct($gc.security_result.summary) + $sa_key_expiry_date = array_distinct(timestamp.get_date(cast.as_int($gc.about.labels["res_valid_before_time"]))) + + condition: + $gc +} +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + rule gcp_service_api_key_retrieved { + + meta: + author = "Google Cloud Security" + description = "Detects a successful attempt to retrieve the service API Keys." + rule_id = "mr_ee63778e-20ac-482c-84ef-abf5ceacd36e" + rule_name = "GCP Service API Key Retrieved" + mitre_attack_tactic = "Credential Access" + mitre_attack_technique = "Credentials from Password Stores" + mitre_attack_url = "https://attack.mitre.org/techniques/T1555/" + mitre_attack_version = "v14.1" + type = "Alert" + data_source = "GCP Cloud Audit" + platform = "GCP" + severity = "High" + priority = "High" + + events: + $gcp.metadata.log_type = "GCP_CLOUDAUDIT" + $gcp.metadata.product_event_type = "google.api.apikeys.v2.ApiKeys.GetKeyString" + $gcp.target.application = "apikeys.googleapis.com" + $gcp.security_result.action = "ALLOW" + $gcp.principal.user.userid = $userid + + match: + $userid over 1h + + outcome: + $risk_score = max(75) + $mitre_attack_tactic = "Credential Access" + $mitre_attack_technique = "Credentials from Password Stores" + $mitre_attack_technique_id = "T1555" + $event_count = count_distinct($gcp.metadata.id) + $network_http_user_agent = array_distinct($gcp.network.http.user_agent) + $principal_ip = array_distinct($gcp.principal.ip) + $principal_ip_country = array_distinct($gcp.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($gcp.principal.ip_geo_artifact.location.state) + $principal_user_id = array_distinct($gcp.principal.user.userid) + $principal_user_display_name = array_distinct($gcp.principal.user.user_display_name) + $target_resource_name = array_distinct($gcp.target.resource.name) + $dc_target_resource_name = count_distinct($gcp.target.resource.name) + + condition: + $gcp +} +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + rule gcp_bigquery_results_downloaded_from_multiple_tables { + + meta: + author = "Google Cloud Security" + description = "Detect a user downloads GCP BigQuery results from multiple tables which might indicate data exfiltration activity." + rule_id = "mr_dc6b1f68-734d-4b4b-91c2-1675f2422c11" + rule_name = "GCP BigQuery Results Downloaded From Multiple Tables" + mitre_attack_tactic = "Exfiltration" + mitre_attack_technique = "Exfiltration Over Web Service" + mitre_attack_url = "https://attack.mitre.org/techniques/T1567/" + mitre_attack_version = "v14.1" + type = "Alert" + data_source = "GCP Cloud Audit" + platform = "GCP" + severity = "High" + priority = "High" + + events: + $gcp.metadata.event_type = "USER_RESOURCE_ACCESS" + $gcp.metadata.log_type = "GCP_CLOUDAUDIT" + $gcp.metadata.product_event_type = "jobservice.getqueryresults" + $gcp.metadata.product_name = "BigQuery" + $gcp.security_result.action = "ALLOW" + $gcp.principal.user.userid = $user_id + + match: + $user_id over 1h + + outcome: + $risk_score = max(75) + $mitre_attack_tactic = "Exfiltration" + $mitre_attack_technique = "Exfiltration Over Web Service" + $mitre_attack_technique_id = "T1567" + $event_count = count_distinct($gcp.metadata.id) + $network_http_user_agent = array_distinct($gcp.network.http.user_agent) + $principal_ip = array_distinct($gcp.principal.ip) + $principal_ip_country = array_distinct($gcp.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($gcp.principal.ip_geo_artifact.location.state) + $principal_user_id = array_distinct($gcp.principal.user.userid) + $principal_user_display_name = array_distinct($gcp.principal.user.user_display_name) + $target_resource_name = array_distinct($gcp.target.resource.name) + $event_name = array_distinct($gcp.metadata.product_event_type) + $bq_table_name = array_distinct($gcp.target.resource.name) + $dc_bq_table_name = count_distinct($gcp.target.resource.name) + + condition: + $gcp and $dc_bq_table_name > 3 +} +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + rule gcp_exempt_principals_from_audit_log { + + meta: + author = "Google Cloud Security" + description = "Detect when GCP Cloud Audit logs are exempted for principals in all services at project or organization level. Audit logging helps organizations maintain security and minimize risk." + rule_id = "mr_6ebf472c-bf50-468c-a0b1-e0f53dd91a61" + rule_name = "GCP Exempt Principals From Audit Log" + mitre_attack_tactic = "Defense Evasion" + mitre_attack_technique = "Impair Defenses: Disable Cloud Logs" + mitre_attack_url = "https://attack.mitre.org/techniques/T1562/008/" + mitre_attack_version = "v14.1" + type = "Alert" + data_source = "GCP Cloud Audit" + platform = "GCP" + severity = "High" + priority = "High" + + events: + $gcp.metadata.event_type = "USER_RESOURCE_UPDATE_PERMISSIONS" + $gcp.metadata.log_type = "GCP_CLOUDAUDIT" + $gcp.metadata.product_event_type = "SetIamPolicy" + $gcp.security_result.action = "ALLOW" + $gcp.target.application = "cloudresourcemanager.googleapis.com" + any $gcp.target.resource.attribute.labels.value = "ADD" + any $gcp.target.resource.attribute.labels.value = "allServices" + any $gcp.target.resource.attribute.labels.key = /service_data_policy_delta_audit_config_delta_.*_exempted_member/ + + outcome: + //Increase risk score if it is organization wide + $risk_score = max(45 + + if($gcp.target.resource.name = /organizations/,30,0) + ) + $mitre_attack_tactic = "Defense Evasion" + $mitre_attack_technique = "Impair Defenses: Disable Cloud Logs" + $mitre_attack_technique_id = "T1562.008" + $event_count = count_distinct($gcp.metadata.id) + $network_http_user_agent = array_distinct($gcp.network.http.user_agent) + $principal_ip = array_distinct($gcp.principal.ip) + $principal_ip_country = array_distinct($gcp.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($gcp.principal.ip_geo_artifact.location.state) + $principal_user_id = $gcp.principal.user.userid + $principal_user_display_name = $gcp.principal.user.user_display_name + $target_resource_name = $gcp.target.resource.name + $event_name = $gcp.metadata.product_event_type + + condition: + $gcp +} +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule onelogin_otp_brute_force_attack { + + meta: + author = "Google Cloud Security" + description = "Detects a successful login after multiple failed OTP intents" + rule_id = "mr_cc37e0cf-c8c5-4e46-be0e-b2b992775500" + rule_name = "OneLogin OTP Bruteforce Attack" + reference = "https://www.onelogin.com/blog/brute-force-attacks" + mitre_attack_tactic = "Credential Access" + mitre_attack_technique = "Brute Force" + mitre_attack_url = "https://attack.mitre.org/techniques/T1110/" + mitre_attack_version = "v15.1" + type = "Alert" + data_source = "OneLogin" + severity = "High" + priority = "High" + + events: + $failed_otp.metadata.event_type = "USER_RESOURCE_ACCESS" + $failed_otp.metadata.product_name = "ONELOGIN_SSO" + $failed_otp.metadata.vendor_name = "ONELOGIN" + $failed_otp.metadata.product_event_type = "1002" //failed otp challenge + $failed_otp.principal.user.userid = $userid + + $success_otp.metadata.event_type = "USER_LOGIN" + $success_otp.metadata.product_name = "ONELOGIN_SSO" + $success_otp.metadata.vendor_name = "ONELOGIN" + $success_otp.metadata.product_event_type = "1400" //User verified otp device + $success_otp.principal.user.userid = $userid + + $login.metadata.event_type = "USER_LOGIN" + $login.metadata.product_name = "ONELOGIN_SSO" + $login.metadata.vendor_name = "ONELOGIN" + $login.metadata.product_event_type = "5" //User logged into onelogin + $login.principal.user.userid = $userid + + $failed_otp.metadata.event_timestamp.seconds <= $success_otp.metadata.event_timestamp.seconds + $success_otp.metadata.event_timestamp.seconds <= $login.metadata.event_timestamp.seconds + + match: + $userid over 15m + + outcome: + $risk_score = max(75) + $mitre_attack_tactic = "Credential Access" + $mitre_attack_technique = "Brute Force" + $target_user_agent = array_distinct($login.network.http.user_agent) + $principal_ip = array_distinct($login.principal.ip) + $principal_ip_country = array_distinct($login.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($login.principal.ip_geo_artifact.location.state) + $principal_user_user_display_name = array_distinct($login.principal.user.user_display_name) + $target_user_userid = array_distinct($login.target.user.userid) + $otp_device_name = array_distinct($success_otp.additional.fields["otp_device_name"]) + $otp_device_id = array_distinct($success_otp.principal.asset_id) + + condition: + #failed_otp >= 4 and $success_otp and $login +} +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule onelogin_user_logins_from_multiple_countries { + + meta: + author = "Google Cloud Security" + description = "Detects user logins for the same user from different cities within 24 hours." + rule_id = "mr_92eb87fb-0310-460f-9640-8bc0bb87a8a3" + rule_name = "OneLogin User Logins From Multiple Countries" + mitre_attack_tactic = "Initial Access" + mitre_attack_technique = "Valid Accounts: Cloud Accounts" + mitre_attack_url = "https://attack.mitre.org/techniques/T1078/004/" + mitre_attack_version = "v15.1" + type = "Alert" + data_source = "OneLogin" + severity = "Medium" + priority = "Medium" + + events: + $login.metadata.event_type = "USER_LOGIN" + $login.metadata.product_name = "ONELOGIN_SSO" + $login.metadata.vendor_name = "ONELOGIN" + $login.metadata.product_event_type = "5" //user logged into onelogin + $login.principal.user.userid = $userid + + match: + $userid over 24h + + outcome: + $risk_score = max( + 35 + + // Unauthorized target geographies + if($login.principal.ip_geo_artifact.location.country_or_region = "Cuba", 20) + + if($login.principal.ip_geo_artifact.location.country_or_region = "Iran", 20) + + if($login.principal.ip_geo_artifact.location.country_or_region = "North Korea", 20) + + if($login.principal.ip_geo_artifact.location.country_or_region = "Russia", 20) + + if($login.principal.ip_geo_artifact.location.country_or_region = "Syria", 20) + ) + $mitre_attack_tactic = "Initial Access" + $mitre_attack_technique = "Valid Accounts: Cloud Accounts" + $network_user_agent = array_distinct($login.network.http.user_agent) + $principal_ip = array_distinct($login.principal.ip) + $principal_ip_country = array_distinct($login.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($login.principal.ip_geo_artifact.location.state) + $dc_principal_ip_country = count_distinct($login.principal.ip_geo_artifact.location.country_or_region) + $principal_user_userid = array_distinct($login.principal.user.userid) + $principal_user_user_display_name = array_distinct($login.principal.user.user_display_name) + $target_user_userid = array_distinct($login.target.user.userid) + + condition: + $login and $dc_principal_ip_country > 1 +} +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule onelogin_super_user_privileges_assigned { + + meta: + author = "Google Cloud Security" + description = "Detects when a user is assigned super user privileges." + rule_id = "mr_5a2dc2cc-a66a-413c-83de-99e0ed698849" + rule_name = "OneLogin Super User Privileges Assigned" + reference = "https://onelogin.service-now.com/kb_view_customer.do?sysparm_article=KB0010391" + mitre_attack_tactic = "Privilege Escalation" + mitre_attack_technique = "Valid Accounts: Cloud Accounts" + mitre_attack_url = "https://attack.mitre.org/techniques/T1078/004/" + mitre_attack_version = "v15.1" + type = "Alert" + data_source = "OneLogin" + severity = "High" + priority = "High" + + events: + $user.metadata.event_type = "USER_CHANGE_PERMISSIONS" + $user.metadata.product_name = "ONELOGIN_SSO" + $user.metadata.vendor_name = "ONELOGIN" + $user.metadata.product_event_type = "72" //user granted permission to a specific privilege + $user.target.resource.name = "Super user" + + outcome: + $risk_score = max(35) + $mitre_attack_tactic = "Privilege Escalation" + $mitre_attack_technique = "Valid Accounts: Cloud Accounts" + $principal_user_userid = array_distinct($user.principal.user.userid) + $principal_user_user_display_name = array_distinct($user.principal.user.user_display_name) + $principal_ip = array_distinct($user.principal.ip) + $principal_ip_country = array_distinct($user.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($user.principal.ip_geo_artifact.location.state) + $target_user_userid = array_distinct($user.target.user.userid) + + condition: + $user +} +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule onelogin_multiple_users_assumed { + + meta: + author = "Google Cloud Security" + description = "Detects when a user assumes multiple user accounts." + rule_id = "mr_20b98df8-72a3-4163-8654-b66e4192d744" + rule_name = "OneLogin Multiple Users Assumed" + reference = "https://onelogin.service-now.com/kb_view_customer.do?sysparm_article=KB0010594" + mitre_attack_tactic = "Lateral Movement" + mitre_attack_technique = "Use Alternate Authentication Material" + mitre_attack_url = "https://attack.mitre.org/techniques/T1550/" + mitre_attack_version = "v15.1" + type = "Alert" + data_source = "OneLogin" + severity = "Low" + priority = "Low" + + events: + $assume.metadata.event_type = "USER_RESOURCE_ACCESS" + $assume.metadata.product_name = "ONELOGIN_SSO" + $assume.metadata.vendor_name = "ONELOGIN" + $assume.metadata.product_event_type = "3" //a user assumed another user + $assume.principal.user.userid = $actor_user + + match: + $actor_user over 1h + + outcome: + $risk_score = max(35) + $mitre_attack_tactic = "Lateral Movement" + $mitre_attack_technique = "Use Alternate Authentication Material" + $assume_reason = array_distinct($assume.metadata.description) + $principal_user_userid = array_distinct($assume.principal.user.userid) + $principal_user_user_display_name = array_distinct($assume.principal.user.user_display_name) + $principal_ip = array_distinct($assume.principal.ip) + $principal_ip_country = array_distinct($assume.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($assume.principal.ip_geo_artifact.location.state) + $target_user_userid = array_distinct($assume.target.user.userid) + $dc_target_user_userid = count_distinct($assume.target.user.userid) + + condition: + $assume and $dc_target_user_userid > 3 +} +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule onelogin_multiple_users_login_failures_from_the_same_ip { + + meta: + author = "Google Cloud Security" + description = "Detects multiple users login failures from a single IP." + rule_id = "mr_8e302561-6fc5-430d-ae0c-bd285a0aec21" + rule_name = "OneLogin Multiple Users Login Failures From The Same IP" + mitre_attack_tactic = "Initial Access" + mitre_attack_technique = "Valid Accounts: Cloud Accounts" + mitre_attack_url = "https://attack.mitre.org/techniques/T1078/004/" + mitre_attack_version = "v15.1" + type = "Alert" + data_source = "OneLogin" + severity = "Medium" + priority = "Medium" + + events: + $login.metadata.event_type = "USER_LOGIN" + $login.metadata.product_name = "ONELOGIN_SSO" + $login.metadata.vendor_name = "ONELOGIN" + $login.security_result.action = "BLOCK" + $login.metadata.product_event_type = "6" //user failed authentication + $login.principal.ip = $ip + + match: + $ip over 1h + + outcome: + $risk_score = max(35 + + // Unauthorized target geographies + if($login.target.ip_geo_artifact.location.country_or_region = "Cuba", 20) + + if($login.target.ip_geo_artifact.location.country_or_region = "Iran", 20) + + if($login.target.ip_geo_artifact.location.country_or_region = "North Korea", 20) + + if($login.target.ip_geo_artifact.location.country_or_region = "Russia", 20) + + if($login.target.ip_geo_artifact.location.country_or_region = "Syria", 20) + ) + $mitre_attack_tactic = "Initial Access" + $mitre_attack_technique = "Valid Accounts: Cloud Accounts" + $principal_ip = array_distinct($login.principal.ip) + $principal_ip_country = array_distinct($login.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($login.principal.ip_geo_artifact.location.state) + $principal_user_userid = array_distinct($login.principal.user.userid) + $principal_user_user_display_name = array_distinct($login.principal.user.user_display_name) + $dc_principal_user_userid = count_distinct($login.principal.user.userid) + $metadata_description = array_distinct($login.metadata.description) + + condition: + $login and $dc_principal_user_userid > 3 +} +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule onelogin_user_authentication_factor_removed { + + meta: + author = "Google Cloud Security" + description = "Detects when a user removes an authentication factor or otp device." + rule_id = "mr_1b251f11-1699-4707-9027-a279dea7d47e" + rule_name = "OneLogin User Authentication Factor Removed" + reference = "https://onelogin.service-now.com/kb_view_customer.do?sysparm_article=KB0010426" + mitre_attack_tactic = "Defense Evasion" + mitre_attack_technique = "Modify Authentication Process: Multi-Factor Authentication" + mitre_attack_url = "https://attack.mitre.org/techniques/T1556/006/" + mitre_attack_version = "v15.1" + type = "Alert" + data_source = "OneLogin" + severity = "High" + priority = "High" + + events: + $user.metadata.event_type = "USER_RESOURCE_ACCESS" + $user.metadata.product_name = "ONELOGIN_SSO" + $user.metadata.vendor_name = "ONELOGIN" + $user.metadata.product_event_type = "24" //otp_device deregistered for user + + outcome: + $risk_score = max(75) + $mitre_attack_tactic = "Defense Evasion" + $mitre_attack_technique = "Modify Authentication Process: Multi-Factor Authentication" + $principal_user_userid = array_distinct($user.principal.user.userid) + $principal_user_user_display_name = array_distinct($user.principal.user.user_display_name) + $principal_user_email_addresses = array_distinct($user.principal.user.email_addresses) + $principal_ip = array_distinct($user.principal.ip) + $principal_ip_country = array_distinct($user.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($user.principal.ip_geo_artifact.location.state) + $target_user_userid = array_distinct($user.target.user.userid) + $otp_device_name = array_distinct($user.additional.fields["otp_device_name"]) + + condition: + $user +} +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + rule onelogin_application_password_revealed { + + meta: + author = "Google Cloud Security" + description = "Detects when a user revealed another user's application password." + rule_id = "mr_785c2d0e-067e-4ad6-a27b-91d0af644718" + rule_name = "OneLogin Application Password Revealed" + reference = "https://onelogin.service-now.com/kb_view_customer.do?sysparm_article=KB0010598" + mitre_attack_tactic = "Credential Access" + mitre_attack_technique = "Unsecured Credentials" + mitre_attack_url = "https://attack.mitre.org/techniques/T1552/" + mitre_attack_version = "v15.1" + type = "Alert" + data_source = "OneLogin" + severity = "High" + priority = "High" + + events: + $password.metadata.event_type = "USER_RESOURCE_ACCESS" + $password.metadata.product_name = "ONELOGIN_SSO" + $password.metadata.vendor_name = "ONELOGIN" + $password.principal.user.userid != $password.target.user.userid //different users + $password.metadata.product_event_type = "240" //actor_user revealed password to an app for user + $password.principal.user.userid = $userid + + match: + $userid over 1h + + outcome: + $risk_score = max(75) + $mitre_attack_tactic = "Credential Access" + $mitre_attack_technique = "Unsecured Credentials" + $principal_ip = array_distinct($password.principal.ip) + $principal_ip_country = array_distinct($password.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($password.principal.ip_geo_artifact.location.state) + $principal_user_userid = array_distinct($password.principal.user.userid) + $principal_user_user_display_name = array_distinct($password.principal.user.user_display_name) + $target_user_userid = array_distinct($password.target.user.userid) + $target_user_user_display_name = array_distinct($password.target.user.user_display_name) + $target_application = array_distinct($password.target.application) + + condition: + $password +} +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule github_personal_access_token_auto_approve_policy_modified { + + meta: + author = "Google Cloud Security" + description = "Detects when changes are made to a GitHub organization's fine-grained Personal Access Token approval policy." + rule_id = "mr_516c8368-2e3c-4585-afa1-c5df49b214ad" + rule_name = "GitHub Personal Access Token Auto Approve Policy Modified" + assumption = "Your GitHub enterprise audit log settings are configured to log the source IP address for events. Reference: https://docs.github.com/en/organizations/keeping-your-organization-secure/managing-security-settings-for-your-organization/displaying-ip-addresses-in-the-audit-log-for-your-organization" + type = "alert" + severity = "Medium" + priority = "Medium" + platform = "GitHub" + data_source = "github" + mitre_attack_tactic = "Defense Evasion" + mitre_attack_technique = "Impair Defenses: Disable or Modify Tools" + mitre_attack_url = "https://attack.mitre.org/versions/v14/techniques/T1562/001/" + mitre_attack_version = "v14" + reference = "https://docs.github.com/en/enterprise-cloud@latest/admin/monitoring-activity-in-your-enterprise/reviewing-audit-logs-for-your-enterprise/audit-log-events-for-your-enterprise" + + events: + $github.metadata.vendor_name = "GITHUB" + $github.metadata.product_name = "GITHUB" + ( + $github.metadata.product_event_type = "auto_approve_personal_access_token_requests.disable" or + $github.metadata.product_event_type = "auto_approve_personal_access_token_requests.enable" or + $github.metadata.product_event_type = "forbid_auto_approve_personal_access_token_requests.disable" or + $github.metadata.product_event_type = "forbid_auto_approve_personal_access_token_requests.enable" + ) + + outcome: + $risk_score = max(65) + $mitre_attack_tactic = "Defense Evasion" + $mitre_attack_technique = "Impair Defenses: Disable or Modify Tools" + $mitre_attack_technique_id = "T1562.001" + $principal_ip = array_distinct($github.principal.ip) + $principal_user_userid = array_distinct($github.principal.user.userid) + $principal_ip_country = array_distinct($github.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($github.principal.ip_geo_artifact.location.state) + $principal_ip_city = array_distinct($github.principal.location.city) + $security_result_summary = array_distinct($github.security_result.summary) + + condition: + $github +} +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule github_high_number_of_non_public_github_repositories_downloaded { + + meta: + author = "Google Cloud Security" + description = "Detects when a user downloads a high number of non-public GitHub repositories. An adversary may attempt to steal the contents of several GitHub repositories after compromising a user account." + rule_id = "mr_549561b8-1088-4a08-b1f4-a1029a142919" + rule_name = "GitHub High Number Of Non Public GitHub Repositories Downloaded" + assumption = "Your GitHub enterprise audit log settings are configured to log the source IP address for events. Reference: https://docs.github.com/en/organizations/keeping-your-organization-secure/managing-security-settings-for-your-organization/displaying-ip-addresses-in-the-audit-log-for-your-organization" + type = "alert" + severity = "High" + priority = "High" + platform = "GitHub" + data_source = "github" + mitre_attack_tactic = "Collection" + mitre_attack_technique = "Data from Information Repositories: Code Repositories" + mitre_attack_url = "https://attack.mitre.org/versions/v14/techniques/T1213/003/" + mitre_attack_version = "v14" + reference = "https://docs.github.com/en/enterprise-cloud@latest/admin/monitoring-activity-in-your-enterprise/reviewing-audit-logs-for-your-enterprise/audit-log-events-for-your-enterprise" + + events: + $github.metadata.vendor_name = "GITHUB" + $github.metadata.product_name = "GITHUB" + $github.metadata.product_event_type = "repo.download_zip" + $github.extracted.fields["public_repo"] = "false" + $github.principal.user.userid = $user_id + $github.target.resource.name = $github_repo_name + + match: + $user_id over 30m + + outcome: + $github_repo_name_distinct_count = count_distinct($github_repo_name) + $risk_score = max(85) + $mitre_attack_tactic = "Collection" + $mitre_attack_technique = "Data from Information Repositories: Code Repositories" + $mitre_attack_technique_id = "T1213.003" + $event_count = count_distinct($github.metadata.id) + $principal_ip = array_distinct($github.principal.ip) + $principal_user_userid = array_distinct($github.principal.user.userid) + $principal_ip_country = array_distinct($github.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($github.principal.ip_geo_artifact.location.state) + $principal_ip_city = array_distinct($github.principal.location.city) + $security_result_summary = array_distinct($github.security_result.summary) + + condition: + // Customize GitHub repo count to fit your environment + $github and $github_repo_name_distinct_count > 5 +} +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule github_secret_scanning_alert { + + meta: + author = "Google Cloud Security" + description = "Detects when a secret is found in a GitHub repository. Adversaries may attempt to harvest leaked/exposed secrets to further infiltrate their target's environment, maintain access, or steal data." + rule_id = "mr_7cd99259-68ef-4b09-96a5-3130f44664b5" + rule_name = "GitHub Secret Scanning Alert" + assumption = "Your GitHub enterprise audit log settings are configured to log the source IP address for events. Reference: https://docs.github.com/en/organizations/keeping-your-organization-secure/managing-security-settings-for-your-organization/displaying-ip-addresses-in-the-audit-log-for-your-organization" + type = "alert" + severity = "High" + priority = "High" + platform = "GitHub" + data_source = "github" + mitre_attack_tactic = "Credential Access" + mitre_attack_technique = "Unsecured Credentials" + mitre_attack_url = "https://attack.mitre.org/versions/v14/techniques/T1552/" + mitre_attack_version = "v14" + reference = "https://docs.github.com/en/enterprise-cloud@latest/admin/monitoring-activity-in-your-enterprise/reviewing-audit-logs-for-your-enterprise/audit-log-events-for-your-enterprise" + + events: + $github.metadata.vendor_name = "GITHUB" + $github.metadata.product_name = "GITHUB" + $github.metadata.product_event_type = "secret_scanning_alert.create" + + outcome: + $risk_score = max(85) + $mitre_attack_tactic = "Credential Access" + $mitre_attack_technique = "Unsecured Credentials" + $mitre_attack_technique_id = "T1552" + $principal_ip = array_distinct($github.principal.ip) + $principal_user_userid = array_distinct($github.principal.user.userid) + $principal_ip_country = array_distinct($github.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($github.principal.ip_geo_artifact.location.state) + $principal_ip_city = array_distinct($github.principal.location.city) + $security_result_summary = array_distinct($github.security_result.summary) + + condition: + $github +} +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule github_dependabot_vulnerability_alerts_disabled { + + meta: + author = "Google Cloud Security" + description = "Detects when vulnerability alerts are disabled for GitHub Dependabot." + rule_id = "mr_fe479d25-26d1-4eef-b22d-fd1a0e9fdd86" + rule_name = "GitHub Dependabot Vulnerability Alerts Disabled" + assumption = "Your GitHub enterprise audit log settings are configured to log the source IP address for events. Reference: https://docs.github.com/en/organizations/keeping-your-organization-secure/managing-security-settings-for-your-organization/displaying-ip-addresses-in-the-audit-log-for-your-organization" + type = "alert" + severity = "High" + priority = "High" + platform = "GitHub" + data_source = "github" + mitre_attack_tactic = "Defense Evasion" + mitre_attack_technique = "Impair Defenses: Disable or Modify Tools" + mitre_attack_url = "https://attack.mitre.org/versions/v14/techniques/T1562/001/" + mitre_attack_version = "v14" + reference = "https://docs.github.com/en/enterprise-cloud@latest/admin/monitoring-activity-in-your-enterprise/reviewing-audit-logs-for-your-enterprise/audit-log-events-for-your-enterprise" + + events: + $github.metadata.vendor_name = "GITHUB" + $github.metadata.product_name = "GITHUB" + ( + $github.metadata.product_event_type = "repository_vulnerability_alerts.disable" or + $github.metadata.product_event_type = "business_dependabot_alerts.disable" or + $github.metadata.product_event_type = "business_dependabot_alerts_new_repos.disable" or + $github.metadata.product_event_type = "dependabot_alerts.disable" or + $github.metadata.product_event_type = "dependabot_alerts_new_repos.disable" or + $github.metadata.product_event_type = "dependabot_security_updates.disable" or + $github.metadata.product_event_type = "dependabot_security_updates_new_repos.disable" + ) + + $github.principal.user.userid = $user_id + + match: + $user_id over 30m + + outcome: + $risk_score = max(85) + $mitre_attack_tactic = "Defense Evasion" + $mitre_attack_technique = "Impair Defenses: Disable or Modify Tools" + $mitre_attack_technique_id = "T1562.001" + $event_count = count_distinct($github.metadata.id) + $principal_ip = array_distinct($github.principal.ip) + $principal_user_userid = array_distinct($github.principal.user.userid) + $principal_ip_country = array_distinct($github.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($github.principal.ip_geo_artifact.location.state) + $principal_ip_city = array_distinct($github.principal.location.city) + $security_result_summary = array_distinct($github.security_result.summary) + + condition: + $github +} +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule github_application_installed { + + meta: + author = "Google Cloud Security" + description = "Detects when a GitHub application is installed within an organization. An untrusted application can be installed and granted permissions to access data within a GitHub organization." + rule_id = "mr_d1c8d420-774f-4fab-af11-2e5cac2023b2" + rule_name = "GitHub Application Installed" + assumption = "Your GitHub enterprise audit log settings are configured to log the source IP address for events. Reference: https://docs.github.com/en/organizations/keeping-your-organization-secure/managing-security-settings-for-your-organization/displaying-ip-addresses-in-the-audit-log-for-your-organization" + type = "alert" + severity = "Low" + priority = "Low" + platform = "GitHub" + data_source = "github" + reference = "https://docs.github.com/en/enterprise-cloud@latest/admin/monitoring-activity-in-your-enterprise/reviewing-audit-logs-for-your-enterprise/audit-log-events-for-your-enterprise" + + events: + $github.metadata.vendor_name = "GITHUB" + $github.metadata.product_name = "GITHUB" + $github.metadata.product_event_type = "integration_installation.create" + + outcome: + $risk_score = max(35) + $principal_ip = array_distinct($github.principal.ip) + $principal_user_userid = array_distinct($github.principal.user.userid) + $principal_ip_country = array_distinct($github.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($github.principal.ip_geo_artifact.location.state) + $principal_ip_city = array_distinct($github.principal.location.city) + $security_result_summary = array_distinct($github.security_result.summary) + + condition: + $github +} +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule github_high_number_of_non_public_github_repositories_cloned { + + meta: + author = "Google Cloud Security" + description = "Detects when a user clones a high number of non-public GitHub repositories. An adversary may attempt to steal the contents of several GitHub repositories after compromising a user account." + rule_id = "mr_9063e681-ac7b-4fad-8bcf-08ed1ae367da" + rule_name = "GitHub High Number Of Non Public GitHub Repositories Cloned" + assumption = "Your GitHub enterprise audit log settings are configured to log the source IP address for events. Reference: https://docs.github.com/en/organizations/keeping-your-organization-secure/managing-security-settings-for-your-organization/displaying-ip-addresses-in-the-audit-log-for-your-organization" + type = "alert" + severity = "High" + priority = "High" + platform = "GitHub" + data_source = "github" + mitre_attack_tactic = "Collection" + mitre_attack_technique = "Data from Information Repositories: Code Repositories" + mitre_attack_url = "https://attack.mitre.org/versions/v14/techniques/T1213/003/" + mitre_attack_version = "v14" + reference = "https://docs.github.com/en/enterprise-cloud@latest/admin/monitoring-activity-in-your-enterprise/reviewing-audit-logs-for-your-enterprise/audit-log-events-for-your-enterprise" + + events: + $github.metadata.vendor_name = "GITHUB" + $github.metadata.product_name = "GITHUB" + $github.metadata.product_event_type = "git.clone" + $github.extracted.fields["repository_public"] = "false" + $github.principal.user.userid = $user_id + $github.target.resource.name = $github_repo_name + + match: + $user_id over 30m + + outcome: + $github_repo_name_distinct_count = count_distinct($github_repo_name) + $risk_score = max(85) + $mitre_attack_tactic = "Collection" + $mitre_attack_technique = "Data from Information Repositories: Code Repositories" + $mitre_attack_technique_id = "T1213.003" + $event_count = count_distinct($github.metadata.id) + $principal_ip = array_distinct($github.principal.ip) + $principal_user_userid = array_distinct($github.principal.user.userid) + $principal_ip_country = array_distinct($github.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($github.principal.ip_geo_artifact.location.state) + $principal_ip_city = array_distinct($github.principal.location.city) + $security_result_summary = array_distinct($github.security_result.summary) + + condition: + // Customize GitHub repo count to fit your environment + $github and $github_repo_name_distinct_count > 5 +} +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule github_oauth_application_access_restrictions_disabled { + + meta: + author = "Google Cloud Security" + description = "Detects when third-party application access restrictions are disabled for a GitHub organization." + rule_id = "mr_9faa8dae-8e9f-4c10-9d11-e45eaebe1070" + rule_name = "GitHub OAuth Application Access Restrictions Disabled" + assumption = "Your GitHub enterprise audit log settings are configured to log the source IP address for events. Reference: https://docs.github.com/en/organizations/keeping-your-organization-secure/managing-security-settings-for-your-organization/displaying-ip-addresses-in-the-audit-log-for-your-organization" + type = "alert" + severity = "Low" + priority = "Low" + platform = "GitHub" + data_source = "github" + reference = "https://docs.github.com/en/enterprise-cloud@latest/admin/monitoring-activity-in-your-enterprise/reviewing-audit-logs-for-your-enterprise/audit-log-events-for-your-enterprise" + + events: + $github.metadata.vendor_name = "GITHUB" + $github.metadata.product_name = "GITHUB" + $github.metadata.product_event_type = "org.disable_oauth_app_restrictions" + + outcome: + $risk_score = max(35) + $principal_ip = array_distinct($github.principal.ip) + $principal_user_userid = array_distinct($github.principal.user.userid) + $principal_ip_country = array_distinct($github.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($github.principal.ip_geo_artifact.location.state) + $principal_ip_city = array_distinct($github.principal.location.city) + $security_result_summary = array_distinct($github.security_result.summary) + + condition: + $github +} +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule github_user_unblocked_from_accessing_organization_repositories { + + meta: + author = "Google Cloud Security" + description = "Detects when a user is unblocked from accessing repositories within a GitHub organization." + rule_id = "mr_3a6905e8-e5e1-40af-b911-52bc4918d2ba" + rule_name = "GitHub User Unblocked From Accessing Organization Repositories" + assumption = "Your GitHub enterprise audit log settings are configured to log the source IP address for events. Reference: https://docs.github.com/en/organizations/keeping-your-organization-secure/managing-security-settings-for-your-organization/displaying-ip-addresses-in-the-audit-log-for-your-organization" + type = "alert" + severity = "Low" + priority = "Low" + platform = "GitHub" + data_source = "github" + reference = "https://docs.github.com/en/enterprise-cloud@latest/admin/monitoring-activity-in-your-enterprise/reviewing-audit-logs-for-your-enterprise/audit-log-events-for-your-enterprise" + + events: + $github.metadata.vendor_name = "GITHUB" + $github.metadata.product_name = "GITHUB" + $github.metadata.product_event_type = "org.unblock_user" + $github.principal.user.userid = $actor_user_id + $github.extracted.fields["blocked_user"] = $target_user_id + + match: + $actor_user_id, $target_user_id over 30m + + outcome: + $risk_score = max(35) + $event_count = count_distinct($github.metadata.id) + $principal_ip = array_distinct($github.principal.ip) + $principal_user_userid = array_distinct($github.principal.user.userid) + $principal_ip_country = array_distinct($github.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($github.principal.ip_geo_artifact.location.state) + $principal_ip_city = array_distinct($github.principal.location.city) + $security_result_summary = array_distinct($github.security_result.summary) + + condition: + $github +} +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule github_repository_visibility_changed_to_public { + + meta: + author = "Google Cloud Security" + description = "Detects when the visibility for a GitHub repository is changed to public." + rule_id = "mr_0f64f779-e61b-4827-9797-9eca5a825780" + rule_name = "GitHub Repository Visibility Changed To Public" + assumption = "Your GitHub enterprise audit log settings are configured to log the source IP address for events. Reference: https://docs.github.com/en/organizations/keeping-your-organization-secure/managing-security-settings-for-your-organization/displaying-ip-addresses-in-the-audit-log-for-your-organization" + type = "alert" + // Customize the severity and priority values depending on how normal this behavior is for your organization + severity = "High" + priority = "High" + platform = "GitHub" + data_source = "github" + reference = "https://docs.github.com/en/enterprise-cloud@latest/admin/monitoring-activity-in-your-enterprise/reviewing-audit-logs-for-your-enterprise/audit-log-events-for-your-enterprise" + + events: + // If internal/private GitHub repositories are often made public by your organization, consider filtering events based on + // what behavior is considered normal, e.g., is a specific GitHub account used to make repos public? + $github.metadata.vendor_name = "GITHUB" + $github.metadata.product_name = "GITHUB" + $github.metadata.product_event_type = "repo.access" + $github.extracted.fields["previous_visibility"] = "internal" + $github.extracted.fields["public_repo"] = "true" + $github.principal.user.userid = $user_id + $github.target.resource.name = $github_repo_name + + match: + $user_id, $github_repo_name over 30m + + outcome: + $risk_score = max(85) + $event_count = count_distinct($github.metadata.id) + $principal_ip = array_distinct($github.principal.ip) + $principal_user_userid = array_distinct($github.principal.user.userid) + $principal_ip_country = array_distinct($github.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($github.principal.ip_geo_artifact.location.state) + $principal_ip_city = array_distinct($github.principal.location.city) + $security_result_summary = array_distinct($github.security_result.summary) + + condition: + $github +} +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule github_outgoing_organization_transfer_initiated { + + meta: + author = "Google Cloud Security" + description = "Detects when a GitHub organization is transferred to another enterprise account. An adversary may attempt to transfer a GitHub organization to an enterprise account they control in order to steal data." + rule_id = "mr_052eb23f-84de-43a3-b9cb-736f8770cd8d" + rule_name = "GitHub Outgoing Organization Transfer Initiated" + assumption = "Your GitHub enterprise audit log settings are configured to log the source IP address for events. Reference: https://docs.github.com/en/organizations/keeping-your-organization-secure/managing-security-settings-for-your-organization/displaying-ip-addresses-in-the-audit-log-for-your-organization" + type = "alert" + severity = "Low" + priority = "Low" + platform = "GitHub" + data_source = "github" + mitre_attack_tactic = "Exfiltration" + mitre_attack_technique = "Transfer Data to Cloud Account" + mitre_attack_url = "https://attack.mitre.org/versions/v14/techniques/T1537/" + mitre_attack_version = "v14" + reference = "https://docs.github.com/en/enterprise-cloud@latest/admin/monitoring-activity-in-your-enterprise/reviewing-audit-logs-for-your-enterprise/audit-log-events-for-your-enterprise" + + events: + $github.metadata.vendor_name = "GITHUB" + $github.metadata.product_name = "GITHUB" + $github.metadata.product_event_type = "org.transfer_outgoing" + + outcome: + $risk_score = max(35) + $mitre_attack_tactic = "Exfiltration" + $mitre_attack_technique = "Transfer Data to Cloud Account" + $mitre_attack_technique_id = "T1537" + $event_count = count_distinct($github.metadata.id) + $principal_ip = array_distinct($github.principal.ip) + $principal_user_userid = array_distinct($github.principal.user.userid) + $principal_ip_country = array_distinct($github.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($github.principal.ip_geo_artifact.location.state) + $principal_ip_city = array_distinct($github.principal.location.city) + $security_result_summary = array_distinct($github.security_result.summary) + + condition: + $github +} +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule github_access_granted_to_personal_access_token_followed_by_high_number_of_cloned_non_public_repositories { + + meta: + author = "Google Cloud Security" + description = "Detects when a user grants access to a GitHub Personal Access Token prior to cloning several GitHub non-public GitHub repositories. An adversary may grant access to a Personal Access Token before attempting to steal the contents of several GitHub repositories using a an automated script or offensive tool." + rule_id = "mr_11aaa6f7-7fcc-42cb-af2e-42ed39226c43" + rule_name = "GitHub Access Granted To Personal Access Token Followed By High Number Of Cloned Non Public Repositories" + assumption = "Your GitHub enterprise audit log settings are configured to log the source IP address for events. Reference: https://docs.github.com/en/organizations/keeping-your-organization-secure/managing-security-settings-for-your-organization/displaying-ip-addresses-in-the-audit-log-for-your-organization" + type = "alert" + severity = "High" + priority = "High" + platform = "GitHub" + data_source = "github" + mitre_attack_tactic = "Collection" + mitre_attack_technique = "Data from Information Repositories: Code Repositories" + mitre_attack_url = "https://attack.mitre.org/versions/v14/techniques/T1213/003/" + mitre_attack_version = "v14" + reference = "https://docs.github.com/en/enterprise-cloud@latest/admin/monitoring-activity-in-your-enterprise/reviewing-audit-logs-for-your-enterprise/audit-log-events-for-your-enterprise" + + events: + // GitHub Personal Access Token (PAT) access granted event + $github_pat.metadata.vendor_name = "GITHUB" + $github_pat.metadata.product_name = "GITHUB" + $github_pat.metadata.product_event_type = "personal_access_token.access_granted" + + // GitHub repository clone event + $github_pat.metadata.vendor_name = "GITHUB" + $github_clone.metadata.product_name = "GITHUB" + $github_clone.metadata.product_event_type = "git.clone" + $github_clone.target.resource.name = $github_repo_name + + // Join GitHub PAT access granted event to GitHub repository clone event + $github_pat.principal.user.userid = $github_clone.principal.user.userid + + // Placeholder for match section + $github_pat.principal.user.userid = $user_id + + // Ensure PAT access granted event occurred before repository clone events + $github_pat.metadata.event_timestamp.seconds < $github_clone.metadata.event_timestamp.seconds + + match: + $user_id over 30m + + outcome: + $github_repo_name_distinct_count = count_distinct($github_repo_name) + $risk_score = max(85) + $mitre_attack_tactic = "Collection" + $mitre_attack_technique = "Data from Information Repositories: Code Repositories" + $mitre_attack_technique_id = "T1213.003" + $event_count = count_distinct($github_clone.metadata.id) + $principal_ip = array_distinct($github_pat.principal.ip) + $principal_user_userid = array_distinct($github_pat.principal.user.userid) + $principal_ip_country = array_distinct($github_pat.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($github_pat.principal.ip_geo_artifact.location.state) + $principal_ip_city = array_distinct($github_pat.principal.location.city) + $security_result_summary = array_distinct($github_pat.security_result.summary) + + condition: + // Customize GitHub repo count to fit your environment + $github_pat and $github_clone and $github_repo_name_distinct_count > 5 +} +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule github_invitation_sent_to_non_company_email_domain { + + meta: + author = "Google Cloud Security" + description = "Detects when an invitation to join a GitHub enterprise or organization is sent to a non-company email address. This rule can be customized to alert you when a GitHub invitation is sent to an unexpected domain i.e. not one of your company's domains used for email." + rule_id = "mr_c191df42-006f-485a-b037-f0cbf737bdd4" + rule_name = "GitHub Invitation Sent To Non Company Email Domain" + assumption = "Your GitHub enterprise audit log settings are configured to log the source IP address for events. Reference: https://docs.github.com/en/organizations/keeping-your-organization-secure/managing-security-settings-for-your-organization/displaying-ip-addresses-in-the-audit-log-for-your-organization" + type = "alert" + severity = "High" + priority = "High" + platform = "GitHub" + data_source = "github" + reference = "https://docs.github.com/en/enterprise-cloud@latest/admin/monitoring-activity-in-your-enterprise/reviewing-audit-logs-for-your-enterprise/audit-log-events-for-your-enterprise" + + events: + $github.metadata.vendor_name = "GITHUB" + $github.metadata.product_name = "GITHUB" + ( + $github.metadata.product_event_type = "business.invite_admin" or + $github.metadata.product_event_type = "business.invite_billing_manager" or + $github.metadata.product_event_type = "org.invite_member" + ) + + // Filter events based on the invitee's email address. Customize the regex expression to fit your environment i.e. alert on invites sent to domains that are not managed by your company + $github.extracted.fields["invitee_email"] != /@my-company-domain-name\.com/ nocase + $github.extracted.fields["invitee_email"] = $invitee_email + + match: + $invitee_email over 30m + + outcome: + $risk_score = max(85) + $event_count = count_distinct($github.metadata.id) + $principal_ip = array_distinct($github.principal.ip) + $principal_user_userid = array_distinct($github.principal.user.userid) + $principal_ip_country = array_distinct($github.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($github.principal.ip_geo_artifact.location.state) + $principal_ip_city = array_distinct($github.principal.location.city) + $security_result_summary = array_distinct($github.security_result.summary) + + condition: + $github +} +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule github_enterprise_deleted { + + meta: + author = "Google Cloud Security" + description = "Detects when a GitHub enterprise is deleted." + rule_id = "mr_6443a51b-c381-4504-9b45-9d8b5e9531d7" + rule_name = "GitHub Enterprise Deleted" + assumption = "Your GitHub enterprise audit log settings are configured to log the source IP address for events. Reference: https://docs.github.com/en/organizations/keeping-your-organization-secure/managing-security-settings-for-your-organization/displaying-ip-addresses-in-the-audit-log-for-your-organization" + type = "alert" + severity = "High" + priority = "High" + platform = "GitHub" + data_source = "github" + mitre_attack_tactic = "Impact" + mitre_attack_technique = "Data Destruction" + mitre_attack_url = "https://attack.mitre.org/versions/v14/techniques/T1485/" + mitre_attack_version = "v14" + reference = "https://docs.github.com/en/enterprise-cloud@latest/admin/monitoring-activity-in-your-enterprise/reviewing-audit-logs-for-your-enterprise/audit-log-events-for-your-enterprise" + + events: + $github.metadata.vendor_name = "GITHUB" + $github.metadata.product_name = "GITHUB" + $github.metadata.product_event_type = "business.delete" + $github.principal.user.userid = $user_id + $github.target.user.company_name = $github_enterprise_name + + match: + $user_id, $github_enterprise_name over 30m + +outcome: + $risk_score = max(85) + $mitre_attack_tactic = "Impact" + $mitre_attack_technique = "Data Destruction" + $mitre_attack_technique_id = "T1485" + $event_count = count_distinct($github.metadata.id) + $principal_ip = array_distinct($github.principal.ip) + $principal_user_userid = array_distinct($github.principal.user.userid) + $principal_ip_country = array_distinct($github.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($github.principal.ip_geo_artifact.location.state) + $principal_ip_city = array_distinct($github.principal.location.city) + $security_result_summary = array_distinct($github.security_result.summary) + + condition: + $github +} +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule github_repository_branch_protection_rules_disabled { + + meta: + author = "Google Cloud Security" + description = "Detects when branch protection rules are disabled for a GitHub repository." + rule_id = "mr_6cf2c5d1-3e94-428f-b29c-84d09c209424" + rule_name = "GitHub Repository Branch Protection Rules Disabled" + assumption = "Your GitHub enterprise audit log settings are configured to log the source IP address for events. Reference: https://docs.github.com/en/organizations/keeping-your-organization-secure/managing-security-settings-for-your-organization/displaying-ip-addresses-in-the-audit-log-for-your-organization" + type = "alert" + severity = "Medium" + priority = "Medium" + platform = "GitHub" + data_source = "github" + mitre_attack_tactic = "Defense Evasion" + mitre_attack_technique = "Impair Defenses: Disable or Modify Tools" + mitre_attack_url = "https://attack.mitre.org/versions/v14/techniques/T1562/001/" + mitre_attack_version = "v14" + reference = "https://docs.github.com/en/enterprise-cloud@latest/admin/monitoring-activity-in-your-enterprise/reviewing-audit-logs-for-your-enterprise/audit-log-events-for-your-enterprise" + + events: + $github.metadata.vendor_name = "GITHUB" + $github.metadata.product_name = "GITHUB" + $github.metadata.product_event_type = "repository_branch_protection_evaluation.disable" + $github.principal.user.userid = $user_id + $github.target.resource.name = $github_repo_name + + match: + $user_id, $github_repo_name over 30m + + outcome: + $risk_score = max(65) + $mitre_attack_tactic = "Defense Evasion" + $mitre_attack_technique = "Impair Defenses: Disable or Modify Tools" + $mitre_attack_technique_id = "T1562.001" + $event_count = count_distinct($github.metadata.id) + $principal_ip = array_distinct($github.principal.ip) + $principal_user_userid = array_distinct($github.principal.user.userid) + $principal_ip_country = array_distinct($github.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($github.principal.ip_geo_artifact.location.state) + $principal_ip_city = array_distinct($github.principal.location.city) + $security_result_summary = array_distinct($github.security_result.summary) + + condition: + $github +} +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule github_enterprise_or_organization_recovery_codes_activity { + + meta: + author = "Google Cloud Security" + description = "Detects when the Single Sign-On (SSO) recovery codes are accessed for a GitHub enterprise or organization. An adversary may attempt to access or steal SSO recovery codes in order to maintain access to their target's GitHub environment." + rule_id = "mr_2bb0bc58-b799-4b8f-96c3-f1cfd7cea201" + rule_name = "GitHub Enterprise Or Organization Recovery Codes Activity" + assumption = "Your GitHub enterprise audit log settings are configured to log the source IP address for events. Reference: https://docs.github.com/en/organizations/keeping-your-organization-secure/managing-security-settings-for-your-organization/displaying-ip-addresses-in-the-audit-log-for-your-organization" + type = "alert" + severity = "Medium" + priority = "Medium" + platform = "GitHub" + data_source = "github" + reference = "https://docs.github.com/en/enterprise-cloud@latest/admin/monitoring-activity-in-your-enterprise/reviewing-audit-logs-for-your-enterprise/audit-log-events-for-your-enterprise" + + events: + $github.metadata.vendor_name = "GITHUB" + $github.metadata.product_name = "GITHUB" + ( + // GitHub enterprise events + $github.metadata.product_event_type = "business.recovery_codes_downloaded" or + $github.metadata.product_event_type = "business.recovery_codes_generated" or + $github.metadata.product_event_type = "business.recovery_codes_printed" or + $github.metadata.product_event_type = "business.recovery_codes_viewed" or + // GitHub organization events + $github.metadata.product_event_type = "org.recovery_codes_downloaded" or + $github.metadata.product_event_type = "org.recovery_codes_generated" or + $github.metadata.product_event_type = "org.recovery_codes_printed" or + $github.metadata.product_event_type = "org.recovery_codes_viewed" + ) + $github.principal.user.userid = $user_id + + match: + $user_id over 30m + + outcome: + $risk_score = max(65) + $event_count = count_distinct($github.metadata.id) + $principal_ip = array_distinct($github.principal.ip) + $principal_user_userid = array_distinct($github.principal.user.userid) + $principal_ip_country = array_distinct($github.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($github.principal.ip_geo_artifact.location.state) + $principal_ip_city = array_distinct($github.principal.location.city) + $security_result_summary = array_distinct($github.security_result.summary) + + condition: + $github +} +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule github_user_blocked_from_accessing_organization_repositories { + + meta: + author = "Google Cloud Security" + description = "Detects when a user is blocked from accessing repositories within a GitHub organization." + rule_id = "mr_f422422c-7a15-47da-accd-b499b8d0b33f" + rule_name = "GitHub User Blocked From Accessing Organization Repositories" + assumption = "Your GitHub enterprise audit log settings are configured to log the source IP address for events. Reference: https://docs.github.com/en/organizations/keeping-your-organization-secure/managing-security-settings-for-your-organization/displaying-ip-addresses-in-the-audit-log-for-your-organization" + type = "alert" + severity = "Low" + priority = "Low" + platform = "GitHub" + data_source = "github" + reference = "https://docs.github.com/en/enterprise-cloud@latest/admin/monitoring-activity-in-your-enterprise/reviewing-audit-logs-for-your-enterprise/audit-log-events-for-your-enterprise" + + events: + $github.metadata.vendor_name = "GITHUB" + $github.metadata.product_name = "GITHUB" + $github.metadata.product_event_type = "org.block_user" + $github.principal.user.userid = $actor_user_id + $github.extracted.fields["blocked_user"] = $target_user_id + + match: + $actor_user_id, $target_user_id over 30m + + outcome: + $risk_score = max(35) + $event_count = count_distinct($github.metadata.id) + $principal_ip = array_distinct($github.principal.ip) + $principal_user_userid = array_distinct($github.principal.user.userid) + $principal_ip_country = array_distinct($github.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($github.principal.ip_geo_artifact.location.state) + $principal_ip_city = array_distinct($github.principal.location.city) + $security_result_summary = array_distinct($github.security_result.summary) + + condition: + $github +} +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule github_enterprise_audit_log_stream_modified { + + meta: + author = "Google Cloud Security" + description = "Detects when a GitHub audit log stream is modified (e.g. paused, enabled, or disabled). An adversary may attempt to interrupt audit logging to erase their tracks." + rule_id = "mr_6a64250e-df54-4037-80f7-1486775c6f37" + rule_name = "GitHub Enterprise Audit Log Stream Modified" + assumption = "Your GitHub enterprise audit log settings are configured to log the source IP address for events. Reference: https://docs.github.com/en/organizations/keeping-your-organization-secure/managing-security-settings-for-your-organization/displaying-ip-addresses-in-the-audit-log-for-your-organization" + type = "alert" + severity = "High" + priority = "High" + platform = "GitHub" + data_source = "github" + mitre_attack_tactic = "Defense Evasion" + mitre_attack_technique = "Impair Defenses: Disable or Modify Cloud Logs" + mitre_attack_url = "https://attack.mitre.org/versions/v14/techniques/T1562/008/" + mitre_attack_version = "v14" + reference = "https://docs.github.com/en/enterprise-cloud@latest/admin/monitoring-activity-in-your-enterprise/reviewing-audit-logs-for-your-enterprise/audit-log-events-for-your-enterprise" + + events: + $github.metadata.vendor_name = "GITHUB" + $github.metadata.product_name = "GITHUB" + $github.metadata.product_event_type = "audit_log_streaming.update" + + outcome: + $risk_score = max(85) + $mitre_attack_tactic = "Defense Evasion" + $mitre_attack_technique = "Impair Defenses: Disable or Modify Cloud Logs" + $mitre_attack_technique_id = "T1562.008" + $principal_ip = array_distinct($github.principal.ip) + $principal_user_userid = array_distinct($github.principal.user.userid) + $principal_ip_country = array_distinct($github.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($github.principal.ip_geo_artifact.location.state) + $principal_ip_city = array_distinct($github.principal.location.city) + $security_result_summary = array_distinct($github.security_result.summary) + + condition: + $github +} +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule github_sso_configuration_modified { + + meta: + author = "Google Cloud Security" + description = "Detects when changes are made to a GitHub enterprise or organization's Single Sign-On (SSO) configuration." + rule_id = "mr_65a0f413-7f77-4039-a241-383c13e96dc2" + rule_name = "GitHub SSO Configuration Modified" + assumption = "Your GitHub enterprise audit log settings are configured to log the source IP address for events. Reference: https://docs.github.com/en/organizations/keeping-your-organization-secure/managing-security-settings-for-your-organization/displaying-ip-addresses-in-the-audit-log-for-your-organization" + type = "alert" + severity = "High" + priority = "High" + platform = "GitHub" + data_source = "github" + mitre_attack_tactic = "Defense Evasion" + mitre_attack_technique = "Impair Defenses: Disable or Modify Tools" + mitre_attack_url = "https://attack.mitre.org/versions/v14/techniques/T1562/001/" + mitre_attack_version = "v14" + reference = "https://docs.github.com/en/enterprise-cloud@latest/admin/monitoring-activity-in-your-enterprise/reviewing-audit-logs-for-your-enterprise/audit-log-events-for-your-enterprise" + + events: + $github.metadata.vendor_name = "GITHUB" + $github.metadata.product_name = "GITHUB" + ( + // Configuration changes for a GitHub enterprise + $github.metadata.product_event_type = "business.disable_saml" or + $github.metadata.product_event_type = "business.update_saml_provider_settings" or + $github.metadata.product_event_type = "business.disable_oidc" or + + // Configuration changes for a GitHub organization + $github.metadata.product_event_type = "org_credential_authorization.deauthorize" or + $github.metadata.product_event_type = "org_credential_authorization.grant" or + $github.metadata.product_event_type = "org_credential_authorization.revoke" or + $github.metadata.product_event_type = "org.disable_saml" or + $github.metadata.product_event_type = "org.update_saml_provider_settings" or + $github.metadata.product_event_type = "sso_redirect.disable" + ) + + outcome: + $risk_score = max(85) + $mitre_attack_tactic = "Defense Evasion" + $mitre_attack_technique = "Impair Defenses: Disable or Modify Tools" + $mitre_attack_technique_id = "T1562.001" + $principal_ip = array_distinct($github.principal.ip) + $principal_user_userid = array_distinct($github.principal.user.userid) + $principal_ip_country = array_distinct($github.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($github.principal.ip_geo_artifact.location.state) + $principal_ip_city = array_distinct($github.principal.location.city) + $security_result_summary = array_distinct($github.security_result.summary) + + condition: + $github +} +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule github_enterprise_audit_log_stream_destroyed { + + meta: + author = "Google Cloud Security" + description = "Detects when a GitHub audit log stream is destroyed. An adversary may attempt to destroy audit logs to erase their tracks." + rule_id = "mr_f86cc19d-4cbb-4ba5-97ef-1d648d53d06a" + rule_name = "GitHub Enterprise Audit Log Stream Destroyed" + assumption = "Your GitHub enterprise audit log settings are configured to log the source IP address for events. Reference: https://docs.github.com/en/organizations/keeping-your-organization-secure/managing-security-settings-for-your-organization/displaying-ip-addresses-in-the-audit-log-for-your-organization" + type = "alert" + severity = "High" + priority = "High" + platform = "GitHub" + data_source = "github" + mitre_attack_tactic = "Defense Evasion" + mitre_attack_technique = "Impair Defenses: Disable or Modify Cloud Logs" + mitre_attack_url = "https://attack.mitre.org/versions/v14/techniques/T1562/008/" + mitre_attack_version = "v14" + reference = "https://docs.github.com/en/enterprise-cloud@latest/admin/monitoring-activity-in-your-enterprise/reviewing-audit-logs-for-your-enterprise/audit-log-events-for-your-enterprise" + + events: + $github.metadata.vendor_name = "GITHUB" + $github.metadata.product_name = "GITHUB" + $github.metadata.product_event_type = "audit_log_streaming.destroy" + + outcome: + $risk_score = max(85) + $mitre_attack_tactic = "Defense Evasion" + $mitre_attack_technique = "Impair Defenses: Disable or Modify Cloud Logs" + $mitre_attack_technique_id = "T1562.008" + $principal_ip = array_distinct($github.principal.ip) + $principal_user_userid = array_distinct($github.principal.user.userid) + $principal_ip_country = array_distinct($github.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($github.principal.ip_geo_artifact.location.state) + $principal_ip_city = array_distinct($github.principal.location.city) + $security_result_summary = array_distinct($github.security_result.summary) + + condition: + $github +} +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule github_organization_removed_from_enterprise { + + meta: + author = "Google Cloud Security" + description = "Detects when a GitHub organization is removed from an enterprise." + rule_id = "mr_705af31b-6257-436d-830d-ad9c9e2f052c" + rule_name = "GitHub Organization Removed From Enterprise" + assumption = "Your GitHub enterprise audit log settings are configured to log the source IP address for events. Reference: https://docs.github.com/en/organizations/keeping-your-organization-secure/managing-security-settings-for-your-organization/displaying-ip-addresses-in-the-audit-log-for-your-organization" + type = "alert" + severity = "Medium" + priority = "Medium" + platform = "GitHub" + data_source = "github" + mitre_attack_tactic = "Impact" + mitre_attack_technique = "Data Destruction" + mitre_attack_url = "https://attack.mitre.org/versions/v14/techniques/T1485/" + mitre_attack_version = "v14" + reference = "https://docs.github.com/en/enterprise-cloud@latest/admin/monitoring-activity-in-your-enterprise/reviewing-audit-logs-for-your-enterprise/audit-log-events-for-your-enterprise" + + events: + $github.metadata.vendor_name = "GITHUB" + $github.metadata.product_name = "GITHUB" + $github.metadata.product_event_type = "business.remove_organization" + $github.principal.user.userid = $user_id + $github.target.user.company_name = $github_enterprise_name + $github.target.administrative_domain = $github_org_name + + match: + $user_id, $github_enterprise_name, $github_org_name over 30m + +outcome: + $risk_score = max(65) + $mitre_attack_tactic = "Impact" + $mitre_attack_technique = "Data Destruction" + $mitre_attack_technique_id = "T1485" + $event_count = count_distinct($github.metadata.id) + $principal_ip = array_distinct($github.principal.ip) + $principal_user_userid = array_distinct($github.principal.user.userid) + $principal_ip_country = array_distinct($github.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($github.principal.ip_geo_artifact.location.state) + $principal_ip_city = array_distinct($github.principal.location.city) + $security_result_summary = array_distinct($github.security_result.summary) + + condition: + $github +} +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule github_outgoing_repository_transfer_initiated { + + meta: + author = "Google Cloud Security" + description = "Detects when a GitHub repository is transferred." + rule_id = "mr_28486f60-1be2-467c-a3e6-6105491c3226" + rule_name = "GitHub Outgoing Repository Transfer Initiated" + assumption = "Your GitHub enterprise audit log settings are configured to log the source IP address for events. Reference: https://docs.github.com/en/organizations/keeping-your-organization-secure/managing-security-settings-for-your-organization/displaying-ip-addresses-in-the-audit-log-for-your-organization" + type = "alert" + severity = "High" + priority = "High" + platform = "GitHub" + data_source = "github" + reference = "https://docs.github.com/en/enterprise-cloud@latest/admin/monitoring-activity-in-your-enterprise/reviewing-audit-logs-for-your-enterprise/audit-log-events-for-your-enterprise" + + events: + $github.metadata.vendor_name = "GITHUB" + $github.metadata.product_name = "GITHUB" + $github.metadata.product_event_type = "repo.transfer_outgoing" + $github.principal.user.userid = $user_id + $github.target.resource.name = $github_repo_name + + match: + $user_id, $github_repo_name over 30m + + outcome: + $risk_score = max(85) + $event_count = count_distinct($github.metadata.id) + $principal_ip = array_distinct($github.principal.ip) + $principal_user_userid = array_distinct($github.principal.user.userid) + $principal_ip_country = array_distinct($github.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($github.principal.ip_geo_artifact.location.state) + $principal_ip_city = array_distinct($github.principal.location.city) + $security_result_summary = array_distinct($github.security_result.summary) + + condition: + $github +} +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule github_two_factor_authentication_requirement_disabled { + + meta: + author = "Google Cloud Security" + description = "Detects when two-factor authentication requirements are disabled for a GitHub enterprise or organization." + rule_id = "mr_43f096a4-42dc-4da7-a6aa-c81379f529c6" + rule_name = "GitHub Two-Factor Authentication Requirement Disabled" + assumption = "Your GitHub enterprise audit log settings are configured to log the source IP address for events. Reference: https://docs.github.com/en/organizations/keeping-your-organization-secure/managing-security-settings-for-your-organization/displaying-ip-addresses-in-the-audit-log-for-your-organization" + type = "alert" + severity = "High" + priority = "High" + platform = "GitHub" + data_source = "github" + mitre_attack_tactic = "Defense Evasion" + mitre_attack_technique = "Impair Defenses: Disable or Modify Tools" + mitre_attack_url = "https://attack.mitre.org/versions/v14/techniques/T1562/001/" + mitre_attack_version = "v14" + reference = "https://docs.github.com/en/enterprise-cloud@latest/admin/monitoring-activity-in-your-enterprise/reviewing-audit-logs-for-your-enterprise/audit-log-events-for-your-enterprise" + + events: + $github.metadata.vendor_name = "GITHUB" + $github.metadata.product_name = "GITHUB" + ( + $github.metadata.product_event_type = "business.disable_two_factor_requirement" or + $github.metadata.product_event_type = "org.disable_two_factor_requirement" + ) + + outcome: + $risk_score = max(85) + $mitre_attack_tactic = "Defense Evasion" + $mitre_attack_technique = "Impair Defenses: Disable or Modify Tools" + $mitre_attack_technique_id = "T1562.001" + $principal_ip = array_distinct($github.principal.ip) + $principal_user_userid = array_distinct($github.principal.user.userid) + $principal_ip_country = array_distinct($github.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($github.principal.ip_geo_artifact.location.state) + $principal_ip_city = array_distinct($github.principal.location.city) + $security_result_summary = array_distinct($github.security_result.summary) + + condition: + $github +} +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule github_repository_deploy_key_created_or_modified { + + meta: + author = "Google Cloud Security" + description = "Detects when an SSH deploy key is added or modified in a GitHub repository. A compromised or unauthorized deploy key could allow malicious actors to push unauthorized changes into production environments, potentially bypassing code reviews and testing procedures. This could lead to the introduction of backdoors, malware, or the exfiltration of sensitive data." + rule_id = "mr_e10b0f8b-6a90-48af-aecb-95ef2ca10de8" + rule_name = "GitHub Repository Deploy Key Created Or Modified" + assumption = "Your GitHub enterprise audit log settings are configured to log the source IP address for events. Reference: https://docs.github.com/en/organizations/keeping-your-organization-secure/managing-security-settings-for-your-organization/displaying-ip-addresses-in-the-audit-log-for-your-organization" + type = "alert" + severity = "High" + priority = "High" + platform = "GitHub" + data_source = "github" + mitre_attack_tactic = "Persistence" + mitre_attack_technique = "Account Manipulation: Additional Cloud Credentials" + mitre_attack_url = "https://attack.mitre.org/techniques/T1098/001/" + mitre_attack_version = "v14" + reference = "https://docs.github.com/en/enterprise-cloud@latest/admin/monitoring-activity-in-your-enterprise/reviewing-audit-logs-for-your-enterprise/audit-log-events-for-your-enterprise" + + events: + $github.metadata.vendor_name = "GITHUB" + $github.metadata.product_name = "GITHUB" + ( + $github.metadata.product_event_type = "public_key.create" or + $github.metadata.product_event_type = "public_key.update" + ) + $github.principal.user.userid = $user_id + $github.target.resource.name = $github_repo_name + + match: + $user_id, $github_repo_name over 30m + + outcome: + $risk_score = max(65) + $mitre_attack_tactic = "Persistence" + $mitre_attack_technique = "Account Manipulation: Additional Cloud Credentials" + $mitre_attack_technique_id = "T1098.001" + $event_count = count_distinct($github.metadata.id) + $principal_ip = array_distinct($github.principal.ip) + $principal_user_userid = array_distinct($github.principal.user.userid) + $principal_ip_country = array_distinct($github.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($github.principal.ip_geo_artifact.location.state) + $principal_ip_city = array_distinct($github.principal.location.city) + $security_result_summary = array_distinct($github.security_result.summary) + + condition: + $github +} +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule github_secret_scanning_disabled_or_bypassed { + + meta: + author = "Google Cloud Security" + description = "Detects when components of GitHub secret scanning is disabled for an enterprise or organization." + rule_id = "mr_982454f3-81ab-491a-b61c-bae718d6028e" + rule_name = "GitHub Secret Scanning Disabled Or Bypassed" + assumption = "Your GitHub enterprise audit log settings are configured to log the source IP address for events. Reference: https://docs.github.com/en/organizations/keeping-your-organization-secure/managing-security-settings-for-your-organization/displaying-ip-addresses-in-the-audit-log-for-your-organization" + type = "alert" + severity = "High" + priority = "High" + platform = "GitHub" + data_source = "github" + mitre_attack_tactic = "Defense Evasion" + mitre_attack_technique = "Impair Defenses: Disable or Modify Tools" + mitre_attack_url = "https://attack.mitre.org/versions/v14/techniques/T1562/001/" + mitre_attack_version = "v14" + reference = "https://docs.github.com/en/enterprise-cloud@latest/admin/monitoring-activity-in-your-enterprise/reviewing-audit-logs-for-your-enterprise/audit-log-events-for-your-enterprise" + + events: + $github.metadata.vendor_name = "GITHUB" + $github.metadata.product_name = "GITHUB" + ( + $github.metadata.product_event_type = "secret_scanning.disable" or + $github.metadata.product_event_type = "secret_scanning_new_repos.disable" or + $github.metadata.product_event_type = "secret_scanning_push_protection.bypass" or + $github.metadata.product_event_type = "business_secret_scanning_custom_pattern_push_protection.disabled" or + $github.metadata.product_event_type = "business_secret_scanning.disable" or + $github.metadata.product_event_type = "business_secret_scanning.disabled_for_new_repos" or + $github.metadata.product_event_type = "business_secret_scanning_push_protection_custom_message.disable" or + $github.metadata.product_event_type = "business_secret_scanning_push_protection.disable" or + $github.metadata.product_event_type = "business_secret_scanning_push_protection.disabled_for_new_repos" or + $github.metadata.product_event_type = "org_secret_scanning_generic_secrets.disabled" or + $github.metadata.product_event_type = "repository_secret_scanning.disable" or + $github.metadata.product_event_type = "repository_secret_scanning_generic_secrets.disabled" or + $github.metadata.product_event_type = "repository_secret_scanning_push_protection.disable" + ) + + outcome: + $risk_score = max(85) + $mitre_attack_tactic = "Defense Evasion" + $mitre_attack_technique = "Impair Defenses: Disable or Modify Tools" + $mitre_attack_technique_id = "T1562.001" + $principal_ip = array_distinct($github.principal.ip) + $principal_user_userid = array_distinct($github.principal.user.userid) + $principal_ip_country = array_distinct($github.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($github.principal.ip_geo_artifact.location.state) + $principal_ip_city = array_distinct($github.principal.location.city) + $security_result_summary = array_distinct($github.security_result.summary) + + condition: + $github +} +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule github_personal_access_token_created_from_tor_ip_address { + + meta: + author = "Google Cloud Security" + description = "Detects when a GitHub Personal Access Token is created from a known Tor exit node IP address. An adversary may create a Personal Access Token before carrying out follow up actions such as cloning GitHub repositories to steal data." + rule_id = "mr_39b42a3c-6b7a-4fa7-a6ca-df084ca92da4" + rule_name = "GitHub Personal Access Token Created from Tor IP Address" + assumption = "Your GitHub enterprise audit log settings are configured to log the source IP address for events. Reference: https://docs.github.com/en/organizations/keeping-your-organization-secure/managing-security-settings-for-your-organization/displaying-ip-addresses-in-the-audit-log-for-your-organization" + type = "alert" + severity = "High" + priority = "High" + platform = "GitHub" + data_source = "github" + mitre_attack_tactic = "Persistence, Privilege Escalation" + mitre_attack_technique = "Account Manipulation: Additional Cloud Credentials" + mitre_attack_url = "https://attack.mitre.org/versions/v14/techniques/T1098/001/" + mitre_attack_version = "v14" + reference = "https://docs.github.com/en/enterprise-cloud@latest/admin/monitoring-activity-in-your-enterprise/reviewing-audit-logs-for-your-enterprise/audit-log-events-for-your-enterprise" + tags = "tor" + + events: + $github.metadata.vendor_name = "GITHUB" + $github.metadata.product_name = "GITHUB" + $github.metadata.product_event_type = "personal_access_token.request_created" + $github.principal.ip = $ip + + // Tor IP address list is provided by Google Cloud Threat Intelligence (GCTI) feed + $gcti_feed.graph.entity.artifact.ip = $ip + $gcti_feed.graph.metadata.entity_type = "IP_ADDRESS" + $gcti_feed.graph.metadata.threat.threat_feed_name = "Tor Exit Nodes" + $gcti_feed.graph.metadata.product_name = "GCTI Feed" + $gcti_feed.graph.metadata.source_type = "GLOBAL_CONTEXT" + + match: + $ip over 30m + + outcome: + $risk_score = max(85) + $mitre_attack_tactic = "Persistence, Privilege Escalation" + $mitre_attack_technique = "Account Manipulation: Additional Cloud Credentials" + $mitre_attack_technique_id = "T1098.001" + $event_count = count_distinct($github.metadata.id) + $principal_ip = array_distinct($github.principal.ip) + $principal_user_userid = array_distinct($github.principal.user.userid) + $principal_ip_country = array_distinct($github.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($github.principal.ip_geo_artifact.location.state) + $principal_ip_city = array_distinct($github.principal.location.city) + $security_result_summary = array_distinct($github.security_result.summary) + + condition: + $github and $gcti_feed +} +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule github_repository_archived_or_deleted { + + meta: + author = "Google Cloud Security" + description = "Detects when a GitHub repository is archived or deleted." + rule_id = "mr_8c515a63-1e2e-4f9e-9150-93302b813315" + rule_name = "GitHub Repository Archived Or Deleted" + assumption = "Your GitHub enterprise audit log settings are configured to log the source IP address for events. Reference: https://docs.github.com/en/organizations/keeping-your-organization-secure/managing-security-settings-for-your-organization/displaying-ip-addresses-in-the-audit-log-for-your-organization" + type = "alert" + severity = "Low" + priority = "Low" + platform = "GitHub" + data_source = "github" + mitre_attack_tactic = "Impact" + mitre_attack_technique = "Data Destruction" + mitre_attack_url = "https://attack.mitre.org/versions/v14/techniques/T1485/" + mitre_attack_version = "v14" + reference = "https://docs.github.com/en/enterprise-cloud@latest/admin/monitoring-activity-in-your-enterprise/reviewing-audit-logs-for-your-enterprise/audit-log-events-for-your-enterprise" + + events: + $github.metadata.vendor_name = "GITHUB" + $github.metadata.product_name = "GITHUB" + ( + $github.metadata.product_event_type = "repo.archived" or + $github.metadata.product_event_type = "repo.destroy" + ) + $github.principal.user.userid = $user_id + $github.target.resource.name = $github_repo_name + + match: + $user_id, $github_repo_name over 30m + + outcome: + $risk_score = max(35) + $mitre_attack_tactic = "Impact" + $mitre_attack_technique = "Data Destruction" + $mitre_attack_technique_id = "T1485" + $event_count = count_distinct($github.metadata.id) + $principal_ip = array_distinct($github.principal.ip) + $principal_user_userid = array_distinct($github.principal.user.userid) + $principal_ip_country = array_distinct($github.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($github.principal.ip_geo_artifact.location.state) + $principal_ip_city = array_distinct($github.principal.location.city) + $security_result_summary = array_distinct($github.security_result.summary) + + condition: + $github +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule okta_multiple_failed_requests_to_access_applications { + + meta: + author = "Google Cloud Security" + description = "Detects multiple failed requests to access applications" + rule_id = "mr_171cce33-0367-4c46-918d-c9fe813b4418" + rule_name = "Okta Multiple Failed Requests To Access Applications" + reference = "https://sec.okta.com/sessioncookietheft" + mitre_attack_tactic = "Defense Evasion, Lateral Movement" + mitre_attack_technique = "Use Alternate Authentication Material: Web Session Cookie" + mitre_attack_url = "https://attack.mitre.org/techniques/T1550/004/" + mitre_attack_version = "v13.1" + type = "Hunt" + data_source = "Okta" + severity = "Medium" + priority = "Medium" + + events: + $login.metadata.product_name = "Okta" + $login.metadata.vendor_name = "Okta" + $login.metadata.event_type = "USER_UNCATEGORIZED" + $login.metadata.product_event_type = "policy.evaluate_sign_on" + $login.target.resource.resource_subtype = "AppInstance" + $login.security_result.action = "CHALLENGE" + $login.network.parent_session_id = $parentNetworkSessionId + + $sso.metadata.event_type = "USER_LOGIN" + $sso.metadata.product_event_type = "user.authentication.sso" + $sso.security_result.action = "ALLOW" + $sso.target.resource.resource_subtype = "AppInstance" + $sso.network.parent_session_id = $parentNetworkSessionId + + match: + $parentNetworkSessionId over 15m + + outcome: + $risk_score = max( + // Baseline + 35 + + // Based on Okta Behavior Detection pattern analysis + if($login.security_result.description = /New Geo-Location=POSITIVE/, 10) + + if($login.security_result.description = /New Device=POSITIVE/, 20) + + if($login.security_result.description = /New IP=POSITIVE/, 5) + + if($login.security_result.description = /New City=POSITIVE/, 5) + + if($login.security_result.description = /New State=POSITIVE/, 10) + + if($login.security_result.description = /New Country=POSITIVE/, 10) + + if($login.security_result.description = /Velocity=POSITIVE/, 10) + + // Unauthorized target geographies + if($login.target.ip_geo_artifact.location.country_or_region = "Cuba", 20) + + if($login.target.ip_geo_artifact.location.country_or_region = "Iran", 20) + + if($login.target.ip_geo_artifact.location.country_or_region = "North Korea", 20) + + if($login.target.ip_geo_artifact.location.country_or_region = "Russia", 20) + + if($login.target.ip_geo_artifact.location.country_or_region = "Syria", 20) + ) + $mitre_attack_tactic = "Defense Evasion, Lateral Movement" + $mitre_attack_technique = "Use Alternate Authentication Material: Web Session Cookie" + $principal_user_agent = array_distinct($login.network.http.user_agent) + $principal_ip = array_distinct($login.principal.ip) + $principal_ip_country = array_distinct($login.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($login.principal.ip_geo_artifact.location.state) + $principal_ip_city = array_distinct($login.principal.location.city) + $security_result_summary = array_distinct($login.security_result.summary) + $principal_user_managers_email_addresses = array_distinct($login.principal.user.managers.email_addresses) + $principal_user_userid = array_distinct($login.principal.user.userid) + $app_names = array_distinct($login.target.resource.name) + $dc_app_name = count_distinct($login.target.resource.name) + $security_result_description = array_distinct($login.security_result.description) + + condition: + $login and $sso and $dc_app_name > 5 +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule okta_multiple_users_logins_with_invalid_credentials_from_the_same_ip { + + meta: + author = "Google Cloud Security" + description = "Detects multiple user logins with invalid credentials from a single IP." + rule_id = "mr_09e08430-0704-4411-b3a1-29d05bcd4e13" + rule_name = "Okta Multiple User's Logins With Invalid Credentials From The Same IP" + reference = "https://help.okta.com/en-us/Content/Topics/Security/threat-insight/configure-threatinsight-system-log.htm" + mitre_attack_tactic = "Defense Evasion, Persistence, Privilege Escalation, Initial Access" + mitre_attack_technique = "Valid Accounts" + mitre_attack_url = "https://attack.mitre.org/techniques/T1078/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "Okta" + severity = "Medium" + priority = "Medium" + + events: + $login.metadata.product_name = "Okta" + $login.metadata.vendor_name = "Okta" + $login.metadata.event_type = "USER_LOGIN" + $login.security_result.action = "BLOCK" + $login.security_result.category_details = "INVALID_CREDENTIALS" + $login.principal.ip = $ip + + match: + $ip over 1h + + outcome: + $risk_score = max( + // If the IP Address is marked as suspicious IP address by Okta ThreatInsight + if($login.security_result.detection_fields["threatSuspected"] = "true", 30) + + // Based on Okta Behavior Detection pattern analysis + if($login.security_result.description = /New Geo-Location=POSITIVE/, 10) + + if($login.security_result.description = /New Device=POSITIVE/, 20) + + if($login.security_result.description = /New IP=POSITIVE/, 5) + + if($login.security_result.description = /New City=POSITIVE/, 5) + + if($login.security_result.description = /New State=POSITIVE/, 10) + + if($login.security_result.description = /New Country=POSITIVE/, 10) + + if($login.security_result.description = /Velocity=POSITIVE/, 10) + + // Unauthorized target geographies + if($login.target.ip_geo_artifact.location.country_or_region = "Cuba", 20) + + if($login.target.ip_geo_artifact.location.country_or_region = "Iran", 20) + + if($login.target.ip_geo_artifact.location.country_or_region = "North Korea", 20) + + if($login.target.ip_geo_artifact.location.country_or_region = "Russia", 20) + + if($login.target.ip_geo_artifact.location.country_or_region = "Syria", 20) + ) + $mitre_attack_tactic = "Defense Evasion, Persistence, Privilege Escalation, Initial Access" + $mitre_attack_technique = "Valid Accounts" + $target_user_agent = array_distinct($login.network.http.user_agent) + $principal_ip = array_distinct($login.principal.ip) + $principal_ip_country = array_distinct($login.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($login.principal.ip_geo_artifact.location.state) + $principal_ip_city = array_distinct($login.principal.location.city) + $security_result_summary = array_distinct($login.security_result.summary) + $principal_user_managers_email_addresses = array_distinct($login.principal.user.managers.email_addresses) + $principal_user_userid = array_distinct($login.principal.user.userid) + $dc_principal_user_userid = count_distinct($login.principal.user.userid) + $target_user_email_addresses = array_distinct($login.target.user.email_addresses) + $target_user_userid = array_distinct($login.target.user.userid) + $security_result_description = array_distinct($login.security_result.description) + + condition: + $login and $dc_principal_user_userid > 5 +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule okta_new_api_token_created { + + meta: + author = "Google Cloud Security" + description = "Detects when a new API token is created." + rule_id = "mr_beca4f13-9526-4095-ab77-f0fc0610200c" + rule_name = "Okta New API Token Created" + reference = "https://developer.okta.com/docs/guides/tokens/" + mitre_attack_tactic = "Defense Evasion, Persistence, Privilege Escalation, Initial Access" + mitre_attack_technique = "Valid Accounts" + mitre_attack_url = "https://attack.mitre.org/techniques/T1078/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "Okta" + severity = "Medium" + priority = "Medium" + + events: + $token.metadata.product_name = "Okta" + $token.metadata.vendor_name = "Okta" + $token.metadata.product_event_type = "system.api_token.create" + $token.security_result.summary = "Create API token" + $token.security_result.action = "ALLOW" + $token.principal.user.userid = $userid + + match: + $userid over 1h + + outcome: + $risk_score = max(35) + $mitre_attack_tactic = "Defense Evasion, Persistence, Privilege Escalation, Initial Access" + $mitre_attack_technique = "Valid Accounts" + $target_user_agent = array_distinct($token.network.http.user_agent) + $principal_ip = array_distinct($token.principal.ip) + $principal_ip_country = array_distinct($token.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($token.principal.ip_geo_artifact.location.state) + $principal_ip_city = array_distinct($token.principal.location.city) + $principal_user_email_addresses = array_distinct ($token.principal.user.email_addresses) + $security_result_summary = array_distinct($token.security_result.summary) + + condition: + $token +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule okta_mfa_brute_force_attack { + + meta: + author = "Google Cloud Security" + description = "Detects a successful login after multiple failed MFA pushes" + rule_id = "mr_61d8d679-bf4d-4441-bbbb-65f82a37e3c5" + rule_name = "Okta MFA Bruteforce Attack" + reference = "https://sec.okta.com/pushfatigueworkflows" + mitre_attack_tactic = "Credential Access" + mitre_attack_technique = "Brute Force" + mitre_attack_url = "https://attack.mitre.org/techniques/T1110/" + mitre_attack_version = "v13.1" + type = "Hunt" + data_source = "Okta" + severity = "Medium" + priority = "Medium" + + events: + $push.metadata.product_name = "Okta" + $push.metadata.vendor_name = "Okta" + $push.metadata.event_type = "USER_UNCATEGORIZED" + $push.metadata.product_event_type = "system.push.send_factor_verify_push" + $push.network.parent_session_id = $parent_session_id + + $auth.metadata.event_type = "USER_LOGIN" + $auth.metadata.product_event_type = "user.authentication.auth_via_mfa" + $auth.metadata.product_name = "Okta" + $auth.metadata.vendor_name = "Okta" + $auth.security_result.action = "ALLOW" + $auth.network.parent_session_id = $parent_session_id + + $push.metadata.event_timestamp.seconds <= $auth.metadata.event_timestamp.seconds + + match: + $parent_session_id over 15m + + outcome: + $risk_score = max(35) + $mitre_attack_tactic = "Credential Access" + $mitre_attack_technique = "Brute Force" + $push_target_user_agent = array_distinct($push.network.http.user_agent) + $push_principal_ip = array_distinct($push.principal.ip) + $push_principal_ip_country = array_distinct($push.principal.ip_geo_artifact.location.country_or_region) + $push_principal_ip_state = array_distinct($push.principal.ip_geo_artifact.location.state) + //$push_principal_ip_city = array_distinct($push.principal.location.city) + $push_principal_user_email_addresses = array_distinct ($push.principal.user.email_addresses) + $push_security_result_summary = array_distinct($push.security_result.summary) + $push_target_user_email_addresses = array_distinct($push.target.user.email_addresses) + $push_target_user_userid = array_distinct($push.target.user.userid) + $push_security_result_risk_reason = array_distinct($push.security_result.detection_fields["Risk Reasons"]) + $dc_push_network_session_id = count_distinct($push.network.parent_session_id) + $auth_target_user_agent = array_distinct($auth.network.http.user_agent) + $auth_principal_ip = array_distinct($auth.principal.ip) + $auth_principal_ip_country = array_distinct($auth.principal.ip_geo_artifact.location.country_or_region) + //$auth_principal_ip_state = array_distinct($auth.principal.ip_geo_artifact.location.state) + //$auth_principal_ip_city = array_distinct($auth.principal.location.city) + $auth_principal_user_email_addresses = array_distinct ($auth.principal.user.email_addresses) + $auth_security_result_summary = array_distinct($auth.security_result.summary) + $auth_target_user_email_addresses = array_distinct($auth.target.user.email_addresses) + $auth_target_user_userid = array_distinct($auth.target.user.userid) + + condition: + #push > 4 and $auth +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule okta_user_suspicious_activity_reported { + + meta: + author = "Google Cloud Security" + description = "An Okta user reports suspicious activity in response to an end user security notification." + rule_id = "mr_09eaaa93-be5e-4b7f-9d6b-8675e63291a0" + rule_name = "Okta User Suspicious Activity Reported" + reference = "https://help.okta.com/en-us/Content/Topics/Security/suspicious-activity-reporting.htm" + mitre_attack_tactic = "Defense Evasion, Persistence, Privilege Escalation, Initial Access" + mitre_attack_technique = "Valid Accounts" + mitre_attack_url = "https://attack.mitre.org/techniques/T1078/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "Okta" + severity = "Medium" + priority = "Medium" + + events: + $suspicious.metadata.product_name = "Okta" + $suspicious.metadata.vendor_name = "Okta" + $suspicious.metadata.event_type = "USER_UNCATEGORIZED" + $suspicious.metadata.product_event_type = "user.account.report_suspicious_activity_by_enduser" + $suspicious.security_result.summary = "User report suspicious activity" + $suspicious.target.user.userid = $userid + + match: + $userid over 1h + + outcome: + $risk_score = max( + 35 + + // Increase Risk based on suspiciousActivityEventType + if($suspicious.security_result.detection_fields["suspiciousActivityEventType"] = "system.email.mfa_enroll_notification.sent_message", 30) + ) + $mitre_attack_tactic = "Defense Evasion, Persistence, Privilege Escalation, Initial Access" + $mitre_attack_technique = "Valid Accounts" + $target_user_agent = array_distinct($suspicious.network.http.user_agent) + $principal_ip = array_distinct($suspicious.principal.ip) + $principal_ip_country = array_distinct($suspicious.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($suspicious.principal.ip_geo_artifact.location.state) + $principal_ip_city = array_distinct($suspicious.principal.location.city) + $principal_user_email_addresses = array_distinct ($suspicious.principal.user.email_addresses) + $security_result_summary = array_distinct($suspicious.security_result.summary) + $target_user_email_addresses = array_distinct($suspicious.target.user.email_addresses) + $target_user_userid = array_distinct($suspicious.target.user.userid) + + condition: + $suspicious +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule okta_threatinsight_login_failure_with_high_unknown_users { + + meta: + author = "Google Cloud Security" + description = "Okta's ThreatInsight can identify multiple login failures with high unknown users count from the same IP across one or more Okta orgs." + rule_id = "mr_41bafd12-7b1d-4b73-adf6-621c0431b538" + rule_name = "Okta ThreatInsight Login Failure With High Unknown Users" + reference = "https://help.okta.com/en-us/Content/Topics/Security/threat-insight/configure-threatinsight-system-log.htm" + mitre_attack_tactic = "Credential Access" + mitre_attack_technique = "Brute Force: Credential Stuffing" + mitre_attack_url = "https://attack.mitre.org/techniques/T1110/004/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "Okta" + severity = "Medium" + priority = "Medium" + + events: + $login.metadata.product_name = "Okta" + $login.metadata.vendor_name = "Okta" + $login.metadata.event_type = "USER_UNCATEGORIZED" + $login.metadata.product_event_type = "security.threat.detected" + $login.security_result.category_details = /Login failures with high unknown users count/ + $login.principal.user.userid = $userid + $login.principal.ip = $ip + + match: + $userid, $ip over 1h + + outcome: + $risk_score = max( + // Baseline + 35 + + // If the IP Address is marked as suspicious IP address by Okta ThreatInsight + if($login.security_result.detection_fields["threatSuspected"] = "true", 30) + + // Unauthorized target geographies + if($login.principal.ip_geo_artifact.location.country_or_region = "Cuba", 20) + + if($login.principal.ip_geo_artifact.location.country_or_region = "Iran", 20) + + if($login.principal.ip_geo_artifact.location.country_or_region = "North Korea", 20) + + if($login.principal.ip_geo_artifact.location.country_or_region = "Russia", 20) + + if($login.principal.ip_geo_artifact.location.country_or_region = "Syria", 20) + ) + $mitre_attack_tactic = "Credential Access" + $mitre_attack_technique = "Brute Force: Credential Stuffing" + $target_user_agent = array_distinct($login.network.http.user_agent) + $principal_ip = array_distinct($login.principal.ip) + $principal_ip_country = array_distinct($login.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($login.principal.ip_geo_artifact.location.state) + $principal_ip_city = array_distinct($login.principal.location.city) + $security_result_summary = array_distinct($login.security_result.summary) + + condition: + $login +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule okta_user_account_lockout { + + meta: + author = "Google Cloud Security" + description = "Detects when a user's account is locked out or a user account has reached the lockout limit." + rule_id = "mr_b7d1d908-77db-4217-a170-44e0423c7fbe" + rule_name = "Okta User Account Lockout" + reference = "https://www.okta.com/resources/whitepaper/how-adaptive-mfa-helps-mitigate-brute-force-attacks/" + mitre_attack_tactic = "Defense Evasion, Persistence, Privilege Escalation, Initial Access" + mitre_attack_technique = "Valid Accounts" + mitre_attack_url = "https://attack.mitre.org/techniques/T1078/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "Okta" + severity = "Medium" + priority = "Medium" + + events: + $login.metadata.product_name = "Okta" + $login.metadata.vendor_name = "Okta" + ( + $login.metadata.product_event_type = "user.account.lock.limit" or + $login.metadata.product_event_type = "user.account.lock" + ) + $login.security_result.action = "BLOCK" + $login.principal.user.userid = $userid + + match: + $userid over 1h + + outcome: + $risk_score = max(35) + $mitre_attack_tactic = "Defense Evasion, Persistence, Privilege Escalation, Initial Access" + $mitre_attack_technique = "Valid Accounts" + $target_user_agent = array_distinct($login.network.http.user_agent) + $principal_ip = array_distinct($login.principal.ip) + $principal_ip_country = array_distinct($login.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($login.principal.ip_geo_artifact.location.state) + $principal_ip_city = array_distinct($login.principal.location.city) + $principal_user_email_addresses = array_distinct ($login.principal.user.email_addresses) + $security_result_summary = array_distinct($login.security_result.summary) + $security_result_category_details = array_distinct($login.security_result.category_details) + + condition: + $login +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule okta_user_rejected_multiple_push_notifications { + + meta: + author = "Google Cloud Security" + description = "Detects when an Okta user rejects more than 2 Push notifications in a 10 minute window." + rule_id = "mr_4d8ac05a-0d73-4d81-a5a1-470d2bd7d725" + rule_name = "Okta User Rejected Multiple Push Notifications" + reference = "https://sec.okta.com/pushfatigueworkflows" + mitre_attack_tactic = "Credential Access" + mitre_attack_technique = "Brute Force" + mitre_attack_url = "https://attack.mitre.org/techniques/T1110/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "Okta" + severity = "Medium" + priority = "Medium" + + events: + $login.metadata.product_name = "Okta" + $login.metadata.vendor_name = "Okta" + $login.metadata.event_type = "USER_UNCATEGORIZED" + ($login.metadata.product_event_type = "user.mfa.okta_verify.deny_push" and $login.security_result.summary = "User rejected Okta push verify") or + ($login.metadata.product_event_type = "user.authentication.auth_via_mfa" and $login.security_result.detection_fields["factor"] = "OKTA_VERIFY_PUSH") + $login.security_result.action = "BLOCK" + $login.principal.user.userid = $userid + + match: + $userid over 10m + + outcome: + $risk_score = max(35) + $mitre_attack_tactic = "Credential Access" + $mitre_attack_technique = "Brute Force" + $target_user_agent = array_distinct($login.network.http.user_agent) + $principal_ip = array_distinct($login.principal.ip) + $principal_ip_country = array_distinct($login.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($login.principal.ip_geo_artifact.location.state) + $principal_ip_city = array_distinct($login.principal.location.city) + $principal_user_email_addresses = array_distinct ($login.principal.user.email_addresses) + $security_result_summary = array_distinct($login.security_result.summary) + + condition: + #login >= 2 +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule okta_user_failed_number_challenge_during_push_notification { + + meta: + author = "Google Cloud Security" + description = "Detects when an Okta user failed a number challenge during push notification." + rule_id = "mr_c5542a92-03d7-463a-bab8-ad10a6cd42f0" + rule_name = "Okta User Failed Number Challenge During Push Notification" + reference = "https://support.okta.com/help/s/article/Number-Challenge-for-Okta-Verify" + mitre_attack_tactic = "Credential Access" + mitre_attack_technique = "Multi-Factor Authentication Request Generation" + mitre_attack_url = "https://attack.mitre.org/techniques/T1621/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "Okta" + severity = "Medium" + priority = "Medium" + + events: + $login.metadata.product_name = "Okta" + $login.metadata.vendor_name = "Okta" + $login.metadata.event_type = "USER_LOGIN" + $login.metadata.product_event_type = "user.authentication.auth_via_mfa" + $login.security_result.detection_fields["pushWithNumberChallengeResponseType"] = "OV_WITH_CHALLENGE_RESPONSE_INVALID" + $login.security_result.action = "BLOCK" + $login.target.user.userid = $userid + + match: + $userid over 1h + + outcome: + $risk_score = max(35) + $mitre_attack_tactic = "Credential Access" + $mitre_attack_technique = "Multi-Factor Authentication Request Generation" + $target_user_agent = array_distinct($login.network.http.user_agent) + $principal_ip = array_distinct($login.principal.ip) + $principal_ip_country = array_distinct($login.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($login.principal.ip_geo_artifact.location.state) + $principal_ip_city = array_distinct($login.principal.location.city) + $principal_user_email_addresses = array_distinct ($login.principal.user.email_addresses) + $security_result_summary = array_distinct($login.security_result.summary) + $target_user_email_addresses = array_distinct($login.target.user.email_addresses) + $target_user_userid = array_distinct($login.target.user.userid) + + condition: + $login +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule okta_phishing_detection_with_fastpass_origin_check { + + meta: + author = "Google Cloud Security" + description = "Okta provides a platform detection for when a user enrolled in FastPass fails to authenticate via a real-time AiTM phishing proxy." + rule_id = "mr_07d1a26d-1132-4228-bd49-c8dd899c7792" + rule_name = "Okta Phishing Detection With Fastpass Origin Check" + reference = "https://sec.okta.com/fastpassphishingdetection" + mitre_attack_tactic = "Initial Access" + mitre_attack_technique = "Phishing" + mitre_attack_url = "https://attack.mitre.org/techniques/T1566/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "Okta" + severity = "Medium" + priority = "Medium" + + events: + $login.metadata.product_name = "Okta" + $login.metadata.vendor_name = "Okta" + $login.metadata.event_type = "USER_LOGIN" + $login.metadata.product_event_type = "user.authentication.auth_via_mfa" + $login.security_result.action = "BLOCK" + $login.security_result.category_details = "FastPass declined phishing attempt" + $login.target.user.userid = $userid + + match: + $userid over 1h + + outcome: + $risk_score = max(35) + $mitre_attack_tactic = "Initial Access" + $mitre_attack_technique = "Phishing" + $target_user_agent = array_distinct($login.network.http.user_agent) + $principal_ip = array_distinct($login.principal.ip) + $principal_ip_country = array_distinct($login.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($login.principal.ip_geo_artifact.location.state) + $principal_ip_city = array_distinct($login.principal.location.city) + $principal_user_email_addresses = array_distinct ($login.principal.user.email_addresses) + $security_result_summary = array_distinct($login.security_result.summary) + $target_user_email_addresses = array_distinct($login.target.user.email_addresses) + $target_user_userid = array_distinct($login.target.user.userid) + $security_result_risk_reason = array_distinct($login.security_result.detection_fields["Risk Reasons"]) + + condition: + $login +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule okta_mismatch_between_source_and_response_for_verify_push_request { + + meta: + author = "Google Cloud Security" + description = "Okta Mismatch Between Source and Response for Verify Push Request" + rule_id = "mr_552008c0-c691-40b2-b7ce-5181570ba5c3" + rule_name = "Okta Mismatch Between Source And Response For Verify Push Request" + reference = "https://sec.okta.com/pushfatigueworkflows" + mitre_attack_tactic = "Credential Access" + mitre_attack_technique = "Multi-Factor Authentication Request Generation" + mitre_attack_url = "https://attack.mitre.org/techniques/T1621" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "Okta" + severity = "Medium" + priority = "Medium" + + events: + $push.metadata.product_name = "Okta" + $push.metadata.vendor_name = "Okta" + $push.metadata.event_type = "USER_UNCATEGORIZED" + $push.metadata.product_event_type = "system.push.send_factor_verify_push" + $push.security_result.description = /New Device=POSITIVE/ + $push.security_result.description = /New IP=POSITIVE/ + $push.security_result.action = "ALLOW" + $push.network.parent_session_id = $parent_session_id + + $auth.metadata.product_name = "Okta" + $auth.metadata.vendor_name = "Okta" + $auth.metadata.event_type = "USER_LOGIN" + $auth.metadata.product_event_type = "user.authentication.auth_via_mfa" + $auth.security_result.detection_fields["factor"] = "OKTA_VERIFY_PUSH" + $auth.security_result.action = "ALLOW" + $auth.network.parent_session_id = $parent_session_id + + $push.metadata.event_timestamp.seconds <= $auth.metadata.event_timestamp.seconds + + match: + $parent_session_id over 5m + + outcome: + $risk_score = max( + // Baseline + 35 + + // If the IP Address is marked as suspicious IP address by Okta ThreatInsight + if($push.security_result.detection_fields["threatSuspected"] = "true", 30) + + // Based on Okta Behavior Detection pattern analysis + if($push.security_result.description = /New Geo-Location=POSITIVE/, 10) + + if($push.security_result.description = /New Device=POSITIVE/, 20) + + if($push.security_result.description = /New IP=POSITIVE/, 5) + + if($push.security_result.description = /New City=POSITIVE/, 5) + + if($push.security_result.description = /New State=POSITIVE/, 10) + + if($push.security_result.description = /New Country=POSITIVE/, 10) + + if($push.security_result.description = /Velocity=POSITIVE/, 10) + + // Unauthorized target geographies + if($push.target.ip_geo_artifact.location.country_or_region = "Cuba", 20) + + if($push.target.ip_geo_artifact.location.country_or_region = "Iran", 20) + + if($push.target.ip_geo_artifact.location.country_or_region = "North Korea", 20) + + if($push.target.ip_geo_artifact.location.country_or_region = "Russia", 20) + + if($push.target.ip_geo_artifact.location.country_or_region = "Syria", 20) + ) + $mitre_attack_tactic = "Credential Access" + $mitre_attack_technique = "Multi-Factor Authentication Request Generation" + $push_principal_ip_country = array_distinct($push.principal.ip_geo_artifact.location.country_or_region) + $push_principal_ip_state = array_distinct($push.principal.ip_geo_artifact.location.state) + $push_principal_ip_city = array_distinct($push.principal.location.city) + $push_principal_user_email_addresses = array_distinct ($push.principal.user.email_addresses) + $push_security_result_summary = array_distinct($push.security_result.summary) + $push_target_user_email_addresses = array_distinct($push.target.user.email_addresses) + $push_target_user_userid = array_distinct($push.target.user.userid) + $auth_target_user_agent = array_distinct($auth.network.http.user_agent) + $auth_principal_ip = array_distinct($auth.principal.ip) + $auth_principal_ip_country = array_distinct($auth.principal.ip_geo_artifact.location.country_or_region) + $auth_principal_ip_state = array_distinct($auth.principal.ip_geo_artifact.location.state) + $auth_principal_ip_city = array_distinct($auth.principal.location.city) + $auth_principal_user_email_addresses = array_distinct ($auth.principal.user.email_addresses) + $auth_security_result_summary = array_distinct($auth.security_result.summary) + $auth_target_user_email_addresses = array_distinct($auth.target.user.email_addresses) + $auth_target_user_userid = array_distinct($auth.target.user.userid) + + condition: + $push and $auth +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule okta_suspicious_use_of_a_session_cookie { + + meta: + author = "Google Cloud Security" + description = "Detects when an adversary attempts to reuse a stolen web session cookie in a different device that has a different OS, IP, Browser or User Agent." + rule_id = "mr_913cbc7a-86c9-46a4-b822-023b4aa17106" + rule_name = "Okta Suspicious Use Of A Session Cookie" + reference = "https://sec.okta.com/sessioncookietheft" + mitre_attack_tactic = "Credential Access" + mitre_attack_technique = "Steal Web Session Cookie" + mitre_attack_url = "https://attack.mitre.org/techniques/T1539/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "Okta" + severity = "Medium" + priority = "Medium" + + events: + $login.metadata.product_name = "Okta" + $login.metadata.vendor_name = "Okta" + $login.metadata.event_type = "USER_UNCATEGORIZED" + $login.metadata.product_event_type = "policy.evaluate_sign_on" + ( + $login.security_result.action = "ALLOW" or + $login.security_result.action = "ALLOW_WITH_MODIFICATION" or + $login.security_result.action = "CHALLENGE" + ) + $login.principal.user.userid = $userid + $login.security_result.detection_fields["dtHash"] = $dtHash + + match: + $userid, $dtHash over 1h + + outcome: + $risk_score = max(35) + $mitre_attack_tactic = "Credential Access" + $mitre_attack_technique = "Steal Web Session Cookie" + $target_os = array_distinct($login.network.http.parsed_user_agent.os) + $dc_target_os = count_distinct($login.network.http.parsed_user_agent.os) + $target_browser = array_distinct($login.network.http.parsed_user_agent.browser) + $dc_target_browser = count_distinct($login.network.http.parsed_user_agent.browser) + $target_user_agent = array_distinct($login.network.http.user_agent) + $principal_ip = array_distinct($login.principal.ip) + $dc_principal_ip = count_distinct($login.principal.ip) + $principal_ip_country = array_distinct($login.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($login.principal.ip_geo_artifact.location.state) + $principal_ip_city = array_distinct($login.principal.location.city) + $dc_principal_ip_city = count_distinct($login.principal.location.city) + $security_result_summary = array_distinct($login.security_result.summary) + $principal_user_managers_email_addresses = array_distinct($login.principal.user.managers.email_addresses) + $principal_user_userid = array_distinct($login.principal.user.userid) + + condition: + $login and $dc_principal_ip > 1 and ($dc_target_browser > 1 or $dc_target_os > 1) +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule okta_threatinsight_targeted_brute_force_attack { + + meta: + author = "Google Cloud Security" + description = "Okta ThreatInsight detects access requests from known malicious IPs targeting a specific org." + rule_id = "mr_ce576f12-ee6d-4282-9f7b-f955af183eb7" + rule_name = "Okta ThreatInsight Targeted Bruteforce Attack" + reference = "https://help.okta.com/en-us/Content/Topics/Security/threat-insight/configure-threatinsight-system-log.htm" + mitre_attack_tactic = "Credential Access" + mitre_attack_technique = "Brute Force" + mitre_attack_url = "https://attack.mitre.org/techniques/T1110/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "Okta" + severity = "Medium" + priority = "Medium" + + events: + $bruteforce.metadata.product_name = "Okta" + $bruteforce.metadata.vendor_name = "Okta" + $bruteforce.metadata.event_type = "USER_UNCATEGORIZED" + $bruteforce.metadata.product_event_type = "security.attack.start" + $bruteforce.principal.user.userid = $userid + + match: + $userid over 1h + + outcome: + $risk_score = max(35) + $mitre_attack_tactic = "Credential Access" + $mitre_attack_technique = "Brute Force" + $principal_user_userid = array_distinct($bruteforce.principal.user.userid) + $principal_user_email_addresses = array_distinct($bruteforce.principal.user.email_addresses) + $security_result_summary = array_distinct($bruteforce.security_result.summary) + $security_result_severity = array_distinct($bruteforce.security_result.severity) + + condition: + $bruteforce +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule okta_successful_high_risk_user_logins { + + meta: + author = "Google Cloud Security" + description = "Detects successfully authenticated user logins based on Okta's Behavior Detection pattern analysis." + rule_id = "mr_ef123f09-f2ae-4d29-bb69-896d708f6a27" + rule_name = "Okta Successful High Risk User Logins" + reference = "https://help.okta.com/en-us/Content/Topics/Security/behavior-detection/logs-behavior-detection.htm" + mitre_attack_tactic = "Defense Evasion, Persistence, Privilege Escalation, Initial Access" + mitre_attack_technique = "Valid Accounts" + mitre_attack_url = "https://attack.mitre.org/techniques/T1078/" + mitre_attack_version = "v13.1" + type = "Hunt" + false_positives = "This rule causes False Positives if the user is a net new user." + data_source = "Okta" + severity = "Medium" + priority = "Medium" + + events: + $login.metadata.product_name = "Okta" + $login.metadata.vendor_name = "Okta" + $login.metadata.event_type = "USER_LOGIN" + $login.metadata.product_event_type = "user.session.start" + $login.security_result.summary = "User login to Okta" + $login.security_result.action = "ALLOW" + $login.principal.user.userid = $userid + + // Detect only for existing users and not net new users + $first_seen.graph.metadata.entity_type = "USER" + $first_seen.graph.entity.user.first_seen_time.seconds < $login.metadata.event_timestamp.seconds + $first_seen.graph.entity.user.userid = $userid + + match: + $userid over 5m + + outcome: + $risk_score = max( + // Based on Okta's Behavior Detection pattern analysis + if($login.security_result.description = /New Geo-Location=POSITIVE/, 10) + + if($login.security_result.description = /New Device=POSITIVE/, 20) + + if($login.security_result.description = /New IP=POSITIVE/, 5) + + if($login.security_result.description = /New City=POSITIVE/, 5) + + if($login.security_result.description = /New State=POSITIVE/, 10) + + if($login.security_result.description = /New Country=POSITIVE/, 10) + + if($login.security_result.description = /Velocity=POSITIVE/, 10) + + // Unauthorized target geographies + if($login.principal.ip_geo_artifact.location.country_or_region = "Cuba", 20) + + if($login.principal.ip_geo_artifact.location.country_or_region = "Iran", 20) + + if($login.principal.ip_geo_artifact.location.country_or_region = "North Korea", 20) + + if($login.principal.ip_geo_artifact.location.country_or_region = "Russia", 20) + + if($login.principal.ip_geo_artifact.location.country_or_region = "Syria", 20) + ) + $mitre_attack_tactic = "Defense Evasion, Persistence, Privilege Escalation, Initial Access" + $mitre_attack_technique = "Valid Accounts" + $target_user_agent = array_distinct($login.network.http.user_agent) + $principal_ip = array_distinct($login.principal.ip) + $principal_ip_country = array_distinct($login.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($login.principal.ip_geo_artifact.location.state) + $principal_ip_city = array_distinct($login.principal.location.city) + $security_result_summary = array_distinct($login.security_result.summary) + $principal_user_managers_email_addresses = array_distinct($login.principal.user.managers.email_addresses) + $principal_user_userid = array_distinct($login.principal.user.userid) + $target_user_email_addresses = array_distinct($login.target.user.email_addresses) + $target_user_userid = array_distinct($login.target.user.userid) + $security_result_description = array_distinct($login.security_result.description) + + condition: + $login and $first_seen and $risk_score >= 50 +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule okta_user_login_out_of_hours { + + meta: + author = "Google Cloud Security" + description = "Detects out of hours successful authentication." + rule_id = "mr_36840037-a41c-47d0-b0eb-4096f28855e1" + rule_name = "Okta User Login Out Of Hours" + reference = "https://support.okta.com/help/s/article/User-Signin-and-Recovery-Events-in-the-Okta-System-Log" + mitre_attack_tactic = "Defense Evasion, Persistence, Privilege Escalation, Initial Access" + mitre_attack_technique = "Valid Accounts" + mitre_attack_url = "https://attack.mitre.org/techniques/T1078/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "Okta" + severity = "Low" + priority = "Low" + + events: + $login.metadata.product_name = "Okta" + $login.metadata.vendor_name = "Okta" + $login.metadata.event_type = "USER_LOGIN" + $login.target.user.email_addresses = $user + $login.security_result.action = "ALLOW" + $login.metadata.event_timestamp.seconds = $timestamp + + ( + 01 = timestamp.get_day_of_week($timestamp, "UTC") or //Sunday + 07 = timestamp.get_day_of_week($timestamp, "UTC") //Saturday + ) + + match: + $user over 1h + + outcome: + $risk_score = max( + if (01 = timestamp.get_day_of_week($timestamp, "UTC"), 10) + + if (07 = timestamp.get_day_of_week($timestamp, "UTC"), 15) + + if ( ( timestamp.get_hour($timestamp, "UTC") >= 0 and timestamp.get_hour($timestamp,"UTC")<= 7) or timestamp.get_hour($timestamp,"UTC") > 20, 50) + ) + $mitre_attack_tactic = "Defense Evasion, Persistence, Privilege Escalation, Initial Access" + $mitre_attack_technique = "Valid Accounts" + $principal_ip = array_distinct($login.principal.ip) + $principal_ip_country = array_distinct($login.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($login.principal.ip_geo_artifact.location.state) + $principal_ip_city = array_distinct($login.principal.location.city) + $security_result_summary = array_distinct($login.security_result.summary) + $principal_user_managers_email_addresses = array_distinct($login.principal.user.managers.email_addresses) + $principal_user_userid = array_distinct($login.principal.user.userid) + $dc_principal_user_userid = count_distinct($login.principal.user.userid) + $target_user_email_addresses = array_distinct($login.target.user.email_addresses) + $target_user_userid = array_distinct($login.target.user.userid) + $target_user_agent = array_distinct($login.network.http.user_agent) + $security_result_description = array_distinct($login.security_result.description) + + condition: + $login +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule okta_threatinsight_suspected_password_spray_attack { + + meta: + author = "Google Cloud Security" + description = "Okta's ThreatInsight can identify Password Spray attacks." + rule_id = "mr_4d081db5-7ea3-4300-8e0f-d7c7fcc1f662" + rule_name = "Okta ThreatInsight Suspected Password Spray Attack" + reference = "https://help.okta.com/en-us/Content/Topics/Security/threat-insight/configure-threatinsight-system-log.htm" + mitre_attack_tactic = "Credential Access" + mitre_attack_technique = "Brute Force: Password Spraying" + mitre_attack_url = "https://attack.mitre.org/techniques/T1110/003/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "Okta" + severity = "Medium" + priority = "Medium" + + events: + $login.metadata.product_name = "Okta" + $login.metadata.vendor_name = "Okta" + $login.metadata.event_type = "USER_UNCATEGORIZED" + $login.metadata.product_event_type = "security.threat.detected" + $login.security_result.category_details = "Password Spray" + + outcome: + $risk_score = max( + // Baseline + 35 + + // If the IP Address is marked as suspicious IP address by Okta ThreatInsight + if($login.security_result.detection_fields["threatSuspected"] = "true", 30) + + // Unauthorized target geographies + if($login.principal.ip_geo_artifact.location.country_or_region = "Cuba", 20) + + if($login.principal.ip_geo_artifact.location.country_or_region = "Iran", 20) + + if($login.principal.ip_geo_artifact.location.country_or_region = "North Korea", 20) + + if($login.principal.ip_geo_artifact.location.country_or_region = "Russia", 20) + + if($login.principal.ip_geo_artifact.location.country_or_region = "Syria", 20) + ) + $mitre_attack_tactic = "Credential Access" + $mitre_attack_technique = "Brute Force: Password Spraying" + $target_user_agent = $login.network.http.user_agent + $principal_ip = array_distinct($login.principal.ip) + $principal_ip_country = array_distinct($login.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($login.principal.ip_geo_artifact.location.state) + $principal_ip_city = $login.principal.location.city + $security_result_summary = array_distinct($login.security_result.summary) + + condition: + $login +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule okta_threatinsight_suspected_brute_force_attack { + + meta: + author = "Google Cloud Security" + description = "Okta ThreatInsight detects multiple login failures from the same IP across one or more Okta orgs." + rule_id = "mr_9537e888-7af7-491f-a5e2-3623e1798aba" + rule_name = "Okta ThreatInsight Suspected Bruteforce Attack" + reference = "https://help.okta.com/en-us/Content/Topics/Security/threat-insight/configure-threatinsight-system-log.htm" + mitre_attack_tactic = "Credential Access" + mitre_attack_technique = "Brute Force: Password Guessing" + mitre_attack_url = "https://attack.mitre.org/techniques/T1110/001/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "Okta" + severity = "Medium" + priority = "Medium" + + events: + $bruteforce.metadata.product_name = "Okta" + $bruteforce.metadata.vendor_name = "Okta" + $bruteforce.metadata.event_type = "USER_UNCATEGORIZED" + $bruteforce.metadata.product_event_type = "security.threat.detected" + $bruteforce.security_result.category_details = "Login Failures" + $bruteforce.principal.user.userid = $userid + + match: + $userid over 1h + + outcome: + $risk_score = max( + 35 + + // If the IP Address is marked as suspicious IP address by Okta ThreatInsight + if($bruteforce.security_result.detection_fields["threatSuspected"] = "true", 30) + + // Unauthorized target geographies + if($bruteforce.principal.ip_geo_artifact.location.country_or_region = "Cuba", 20) + + if($bruteforce.principal.ip_geo_artifact.location.country_or_region = "Iran", 20) + + if($bruteforce.principal.ip_geo_artifact.location.country_or_region = "North Korea", 20) + + if($bruteforce.principal.ip_geo_artifact.location.country_or_region = "Russia", 20) + + if($bruteforce.principal.ip_geo_artifact.location.country_or_region = "Syria", 20) + ) + $mitre_attack_tactic = "Credential Access" + $mitre_attack_technique = "Brute Force: Password Guessing" + $target_user_agent = array_distinct($bruteforce.network.http.user_agent) + $principal_ip = array_distinct($bruteforce.principal.ip) + $principal_ip_country = array_distinct($bruteforce.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($bruteforce.principal.ip_geo_artifact.location.state) + $principal_ip_city = array_distinct($bruteforce.principal.location.city) + $security_result_summary = array_distinct($bruteforce.security_result.summary) + + condition: + $bruteforce +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule okta_user_logins_from_multiple_cities { + + meta: + author = "Google Cloud Security" + description = "Detects user logins for same user from different cities within 24 hours." + rule_id = "mr_b607de8a-7988-4f4f-8ecf-e8754de6bbae" + rule_name = "Okta User Logins From Multiple Cities" + reference = "https://help.okta.com/en-us/Content/Topics/Security/behavior-detection/logs-behavior-detection.htm" + mitre_attack_tactic = "Defense Evasion, Persistence, Privilege Escalation, Initial Access" + mitre_attack_technique = "Valid Accounts" + mitre_attack_url = "https://attack.mitre.org/techniques/T1078/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "Okta" + severity = "Medium" + priority = "Medium" + + events: + $login.metadata.product_name = "Okta" + $login.metadata.vendor_name = "Okta" + $login.metadata.event_type = "USER_LOGIN" + $login.metadata.product_event_type = "user.session.start" + $login.security_result.summary = "User login to Okta" + $login.principal.user.userid = $userid + $login.principal.location.city = $city + + match: + $userid over 24h + + outcome: + $risk_score = max( + 35 + + // If the IP Address is marked as suspicious IP address by Okta ThreatInsight + if($login.security_result.detection_fields["threatSuspected"] = "true", 30) + + // Unauthorized target geographies + if($login.principal.ip_geo_artifact.location.country_or_region = "Cuba", 20) + + if($login.principal.ip_geo_artifact.location.country_or_region = "Iran", 20) + + if($login.principal.ip_geo_artifact.location.country_or_region = "North Korea", 20) + + if($login.principal.ip_geo_artifact.location.country_or_region = "Russia", 20) + + if($login.principal.ip_geo_artifact.location.country_or_region = "Syria", 20) + ) + $mitre_attack_tactic = "Defense Evasion, Persistence, Privilege Escalation, Initial Access" + $mitre_attack_technique = "Valid Accounts" + $target_user_agent = array_distinct($login.network.http.user_agent) + $principal_ip = array_distinct($login.principal.ip) + $principal_ip_country = array_distinct($login.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($login.principal.ip_geo_artifact.location.state) + $principal_ip_city = array_distinct($login.principal.location.city) + $dc_principal_ip_city = count_distinct($login.principal.location.city) + $security_result_summary = array_distinct($login.security_result.summary) + $principal_user_managers_email_addresses = array_distinct($login.principal.user.managers.email_addresses) + $principal_user_userid = array_distinct($login.principal.user.userid) + $target_user_email_addresses = array_distinct($login.target.user.email_addresses) + $target_user_userid = array_distinct($login.target.user.userid) + + condition: + $login and $dc_principal_ip_city > 1 +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule aws_iam_compromised_key_quarantine_policy_attached { + + meta: + author = "Google Cloud Security" + description = "Detect when the AWS managed policy AWSCompromisedKeyQuarantine has been attached to a user, role, or group. It is applied by the AWS team in the event that the credentials of an IAM user has been compromised or publicly exposed." + rule_id = "mr_3ac90268-e8bd-41b7-8fc1-e10ee165df8e" + rule_name = "AWS IAM Compromised Key Quarantine Policy Attached" + mitre_attack_tactic = "Credential Access" + mitre_attack_technique = "Unsecured Credentials" + mitre_attack_url = "https://attack.mitre.org/techniques/T1552/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "AWS CloudTrail" + platform = "AWS" + severity = "High" + priority = "High" + + events: + $cloudtrail.metadata.vendor_name = "AMAZON" + $cloudtrail.metadata.product_name = "AWS CloudTrail" + ( + $cloudtrail.metadata.product_event_type = "AttachUserPolicy" or + $cloudtrail.metadata.product_event_type = "AttachGroupPolicy" or + $cloudtrail.metadata.product_event_type = "AttachRolePolicy" + ) + $cloudtrail.target.resource.name = /AWSCompromisedKeyQuarantine/ + $cloudtrail.security_result.action = "ALLOW" + + outcome: + $risk_score = max(75) + $mitre_attack_tactic = "Credential Access" + $mitre_attack_technique = "Unsecured Credentials" + $mitre_attack_technique_id = "T1552" + $event_count = count_distinct($cloudtrail.metadata.id) + $network_http_user_agent = $cloudtrail.network.http.user_agent + $principal_ip = array_distinct($cloudtrail.principal.ip) + $principal_ip_country = array_distinct($cloudtrail.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($cloudtrail.principal.ip_geo_artifact.location.state) + $principal_user_display_name = $cloudtrail.principal.user.user_display_name + $recipient_aws_account_id = $cloudtrail.additional.fields["recipientAccountId"] + $aws_region = $cloudtrail.principal.location.name + $target_resource_name = $cloudtrail.target.resource.name + $target_resource_product_object_id = $cloudtrail.target.resource.product_object_id + + condition: + $cloudtrail +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule aws_iam_administrator_access_policy_attached { + + meta: + author = "Google Cloud Security" + description = "Detects when AWS IAM AdministratorAccess policy is attached to a user, group or role which can be used for privilege escalation." + rule_id = "mr_52c6643b-f6ce-4299-9fb6-05554901800c" + rule_name = "AWS IAM Administrator Access Policy Attached" + mitre_attack_tactic = "Defense Evasion, Persistence, Privilege Escalation, Initial Access" + mitre_attack_technique = "Valid Accounts: Cloud Accounts" + mitre_attack_url = "https://attack.mitre.org/techniques/T1078/004/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "AWS CloudTrail" + platform = "AWS" + severity = "High" + priority = "High" + + events: + $cloudtrail.metadata.vendor_name = "AMAZON" + $cloudtrail.metadata.product_name = "AWS CloudTrail" + ( + $cloudtrail.metadata.product_event_type = "AttachUserPolicy" or + $cloudtrail.metadata.product_event_type = "AttachGroupPolicy" or + $cloudtrail.metadata.product_event_type = "AttachRolePolicy" + ) + $cloudtrail.target.resource.name = "arn:aws:iam::aws:policy/AdministratorAccess" + $cloudtrail.security_result.action = "ALLOW" + + outcome: + $risk_score = max(75) + $mitre_attack_tactic = "Defense Evasion, Persistence, Privilege Escalation, Initial Access" + $mitre_attack_technique = "Valid Accounts: Cloud Accounts" + $mitre_attack_technique_id = "T1078.004" + $event_count = count_distinct($cloudtrail.metadata.id) + $network_http_user_agent = $cloudtrail.network.http.user_agent + $principal_ip = array_distinct($cloudtrail.principal.ip) + $principal_ip_country = array_distinct($cloudtrail.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($cloudtrail.principal.ip_geo_artifact.location.state) + $principal_user_display_name = $cloudtrail.principal.user.user_display_name + $recipient_aws_account_id = $cloudtrail.additional.fields["recipientAccountId"] + $aws_region = $cloudtrail.principal.location.name + $target_resource_name = $cloudtrail.target.resource.name + $target_resource_product_object_id = $cloudtrail.target.resource.product_object_id + + condition: + $cloudtrail +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule aws_guardduty_trusted_or_threat_ip_lists_tampered { + + meta: + author = "Google Cloud Security" + description = "Detects when a GuardDuty Detector's trusted or threat intel IP lists are deleted or disabled." + rule_id = "mr_bdf03398-6341-4f2a-a8ce-9056c82fda2e" + rule_name = "AWS GuardDuty Trusted Or Threat IP Lists Tampered" + mitre_attack_tactic = "Defense Evasion" + mitre_attack_technique = "Impair Defenses" + mitre_attack_url = "https://attack.mitre.org/techniques/T1562/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "AWS CloudTrail" + platform = "AWS" + severity = "High" + priority = "High" + + events: + $cloudtrail.metadata.vendor_name = "AMAZON" + $cloudtrail.metadata.product_name = "AWS CloudTrail" + $cloudtrail.metadata.product_event_type = "DeleteIPSet" or $cloudtrail.metadata.product_event_type = "DeleteThreatIntelSet" or + ( + ( + $cloudtrail.metadata.product_event_type = "UpdateIPSet" or + $cloudtrail.metadata.product_event_type = "UpdateThreatIntelSet" + ) + and $cloudtrail.target.resource.attribute.labels["activate"] = "false" + ) + $cloudtrail.security_result.action = "ALLOW" + + outcome: + $risk_score = max( + // Unauthorized geographies + if($cloudtrail.principal.ip_geo_artifact.location.country_or_region = "Cuba", 40) + + if($cloudtrail.principal.ip_geo_artifact.location.country_or_region = "Iran", 40) + + if($cloudtrail.principal.ip_geo_artifact.location.country_or_region = "North Korea" , 40) + + if($cloudtrail.principal.ip_geo_artifact.location.country_or_region = "Russia", 40) + + if($cloudtrail.principal.ip_geo_artifact.location.country_or_region = "Syria", 40) + ) + $mitre_attack_tactic = "Defense Evasion" + $mitre_attack_technique = "Impair Defenses" + $mitre_attack_technique_id = "T1562" + $event_count = count_distinct($cloudtrail.metadata.id) + $network_http_user_agent = $cloudtrail.network.http.user_agent + $principal_ip = array_distinct($cloudtrail.principal.ip) + $principal_ip_country = array_distinct($cloudtrail.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($cloudtrail.principal.ip_geo_artifact.location.state) + $principal_user_display_name = $cloudtrail.principal.user.user_display_name + $recipient_aws_account_id = $cloudtrail.additional.fields["recipientAccountId"] + $aws_region = $cloudtrail.principal.location.name + $target_resource_name = $cloudtrail.target.resource.name + $target_resource_product_object_id = $cloudtrail.target.resource.product_object_id + + condition: + $cloudtrail +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule aws_console_login_without_mfa { + + meta: + author = "Google Cloud Security" + description = "Detect when a user logs into AWS console without MFA." + rule_id = "mr_b03d1e57-7ed0-49e7-b125-6c18b364ae8c" + rule_name = "AWS Console Login Without MFA" + mitre_attack_tactic = "Initial Access" + mitre_attack_technique = "Valid Accounts: Cloud Accounts" + mitre_attack_url = "https://attack.mitre.org/techniques/T1078/004/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "AWS CloudTrail" + platform = "AWS" + severity = "Low" + priority = "Low" + + events: + + $login.metadata.vendor_name = "AMAZON" + $login.metadata.product_name = "AWS CloudTrail" + $login.metadata.event_type = "USER_LOGIN" + $login.metadata.product_event_type = "ConsoleLogin" + $login.security_result.action= "ALLOW" + $login.extensions.auth.auth_details = "MFAUsed: No" + $login.additional.fields["recipientAccountId"] = $account_id + + match: + $account_id over 1h + + outcome: + $risk_score = max( + //Baseline + 35 + + if($login.principal.resource.type = "Root", 50) + ) + $mitre_attack_tactic = "Initial Access" + $mitre_attack_technique = "Valid Accounts: Cloud Accounts" + $mitre_attack_technique_id = "T1078.004" + $event_count = count_distinct($login.metadata.id) + $network_http_user_agent = array_distinct($login.network.http.user_agent) + $principal_ip = array_distinct($login.principal.ip) + $principal_ip_country = array_distinct($login.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($login.principal.ip_geo_artifact.location.state) + $target_user_display_name = array_distinct($login.target.user.user_display_name) + $target_user_userid = array_distinct($login.target.user.userid) + $is_mfa_used = array_distinct($login.extensions.auth.auth_details) + $target_resource_name = array_distinct($login.target.resource.name) + $target_resource_product_object_id = array_distinct($login.target.resource.product_object_id) + + condition: + $login +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule aws_iam_activity_from_ec2_instance { + + meta: + author = "Google Cloud Security" + description = "Detect AWS IAM activities made by AWS EC2 instances to retain access or escalate privileges." + rule_id = "mr_60c7bb2f-2f02-4ac5-bbe0-ba8be871f3fb" + rule_name = "AWS IAM Activity From EC2 Instance" + mitre_attack_tactic = "Persistence" + mitre_attack_technique = "Account Manipulation" + mitre_attack_url = "https://attack.mitre.org/techniques/T1098/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "AWS CloudTrail" + platform = "AWS" + severity = "High" + priority = "High" + + events: + $cloudtrail.metadata.vendor_name = "AMAZON" + $cloudtrail.metadata.product_name = "AWS CloudTrail" + $cloudtrail.target.application = "iam.amazonaws.com" + ( + $cloudtrail.metadata.product_event_type = "CreateUser" or + $cloudtrail.metadata.product_event_type = "AttachUserPolicy" or + $cloudtrail.metadata.product_event_type = "CreateLoginProfile" or + $cloudtrail.metadata.product_event_type = "UpdateLoginProfile" or + $cloudtrail.metadata.product_event_type = "CreateAccessKey" or + $cloudtrail.metadata.product_event_type = "CreateGroup" or + $cloudtrail.metadata.product_event_type = "AttachGroupPolicy" or + $cloudtrail.metadata.product_event_type = "CreateRole" or + $cloudtrail.metadata.product_event_type = "AttachRolePolicy" + ) + $cloudtrail.security_result.action = "ALLOW" + $cloudtrail.principal.ip = $ip + $cloudtrail.principal.resource.type = "AssumedRole" + $cloudtrail.principal.user.userid = /\/i-.*$/ //regex to be improved + re.capture($cloudtrail.principal.user.userid, ":assumed-role/.*/(.*)$") = $instanceId + + match: + $ip over 1h + + outcome: + $risk_score = max(35) + $mitre_attack_tactic = "Persistence" + $mitre_attack_technique = "Account Manipulation" + $mitre_attack_technique_id = "T1098" + $event_count = count_distinct($cloudtrail.metadata.id) + $network_http_user_agent = array_distinct($cloudtrail.network.http.user_agent) + $principal_ip = array_distinct($cloudtrail.principal.ip) + $principal_ip_country = array_distinct($cloudtrail.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($cloudtrail.principal.ip_geo_artifact.location.state) + $principal_user_display_name = array_distinct($cloudtrail.principal.user.user_display_name) + $recipient_aws_account_id = array_distinct($cloudtrail.additional.fields["recipientAccountId"]) + $aws_region = array_distinct($cloudtrail.principal.location.name) + $target_resource_name = array_distinct($cloudtrail.target.resource.name) + $target_resource_product_object_id = array_distinct($cloudtrail.target.resource.product_object_id) + $ec2_instance_id = array_distinct($instanceId) + + condition: + $cloudtrail +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule aws_successful_api_from_tor_exit_node { + + meta: + author = "Google Cloud Security" + description = "Detects successful API executions from a Tor exit node." + rule_id = "mr_17232c2a-188e-4d6e-85b6-836cdc779655" + rule_name = "AWS Successful API From Tor Exit Node" + mitre_attack_tactic = "Execution" + mitre_attack_technique = "User Execution" + mitre_attack_url = "https://attack.mitre.org/techniques/T1204/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "AWS CloudTrail" + platform = "AWS" + severity = "High" + priority = "High" + + events: + $api.metadata.vendor_name = "AMAZON" + $api.metadata.product_name = "AWS CloudTrail" + $api.security_result.action = "ALLOW" + $api.principal.ip = $ip + + // Tor IP listing provided by GCTI Feed + $gcti_feed.graph.entity.artifact.ip = $ip + $gcti_feed.graph.metadata.entity_type = "IP_ADDRESS" + $gcti_feed.graph.metadata.threat.threat_feed_name = "Tor Exit Nodes" + $gcti_feed.graph.metadata.product_name = "GCTI Feed" + $gcti_feed.graph.metadata.source_type = "GLOBAL_CONTEXT" + + match: + $ip over 5m + + outcome: + $risk_score = max( + //Baseline + 35 + + // Unauthorized geographies + if($api.principal.ip_geo_artifact.location.country_or_region = "Cuba", 40) + + if($api.principal.ip_geo_artifact.location.country_or_region = "Iran", 40) + + if($api.principal.ip_geo_artifact.location.country_or_region = "North Korea" , 40) + + if($api.principal.ip_geo_artifact.location.country_or_region = "Russia", 40) + + if($api.principal.ip_geo_artifact.location.country_or_region = "Syria", 40) + ) + $mitre_attack_tactic = "Execution" + $mitre_attack_technique = "User Execution" + $mitre_attack_technique_id = "T1204" + $event_count = count_distinct($api.metadata.id) + $network_http_user_agent = array_distinct($api.network.http.user_agent) + $principal_ip = array_distinct($api.principal.ip) + $principal_ip_country = array_distinct($api.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($api.principal.ip_geo_artifact.location.state) + $principal_user_display_name = array_distinct($api.principal.user.user_display_name) + $dc_principal_user_display_name = count_distinct($api.principal.user.user_display_name) + $is_mfa_used = array_distinct($api.extensions.auth.auth_details) + $target_resource_name = array_distinct($api.target.resource.name) + $target_resource_product_object_id = array_distinct($api.target.resource.product_object_id) + + condition: + $api and $gcti_feed +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule aws_ec2_high_number_of_api_calls { + + meta: + author = "Google Cloud Security" + description = "Detect when an EC2 instance makes high number of API calls." + rule_id = "mr_d19289e1-4385-4757-bf54-0f61e7a789a4" + rule_name = "AWS EC2 High Number Of API Calls" + mitre_attack_tactic = "Discovery" + mitre_attack_technique = "Cloud Infrastructure Discovery" + mitre_attack_url = "https://attack.mitre.org/techniques/T1580/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "AWS CloudTrail" + platform = "AWS" + severity = "Low" + priority = "Low" + + events: + $api.metadata.vendor_name = "AMAZON" + $api.metadata.product_name = "AWS CloudTrail" + $api.principal.resource.type = "AssumedRole" + $api.principal.user.userid = /\/i-.*$/ //regex to be improved + re.capture($api.principal.user.userid, ":assumed-role/.*/(.*)$") = $instanceId + $api.principal.ip = $ip + + match: + $ip, $instanceId over 5m + + outcome: + $risk_score = max(35) + $mitre_attack_tactic = "Discovery" + $mitre_attack_technique = "Cloud Infrastructure Discovery" + $mitre_attack_technique_id = "T1580" + $event_count = count_distinct($api.metadata.id) + $network_http_user_agent = array_distinct($api.network.http.user_agent) + $principal_ip = array_distinct($api.principal.ip) + $principal_ip_country = array_distinct($api.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($api.principal.ip_geo_artifact.location.state) + $principal_user_display_name = array_distinct($api.principal.user.user_display_name) + $dc_product_event_type = count_distinct($api.metadata.product_event_type) + $aws_region = array_distinct($api.principal.location.name) + $target_resource_name = array_distinct($api.target.resource.name) + $target_resource_product_object_id = array_distinct($api.target.resource.product_object_id) + + condition: + $api and $dc_product_event_type > 7 +} +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule aws_api_gateway_get_keys { + + meta: + author = "Google Cloud Security" + description = "Detects when AWS API Gateway keys are accessed." + rule_id = "mr_1d8ffb2e-ca26-4f8f-8ca1-3dd4694776f5" + rule_name = "AWS API Gateway Keys Accessed" + mitre_attack_tactic = "Credential Access" + mitre_attack_technique = "Credentials from Password Stores" + mitre_attack_url = "https://attack.mitre.org/techniques/T1555/" + mitre_attack_version = "v15.1" + type = "Alert" + data_source = "AWS CloudTrail" + platform = "AWS" + severity = "Low" + priority = "Low" + + events: + $cloudtrail.metadata.vendor_name = "AMAZON" + $cloudtrail.metadata.product_name = "AWS CloudTrail" + ( + ($cloudtrail.metadata.product_event_type = "GetApiKey" and $cloudtrail.target.resource.attribute.labels["requestParameters.includeValue"] = "true") or + ($cloudtrail.metadata.product_event_type = "GetApiKeys" and $cloudtrail.target.resource.attribute.labels["requestParameters.includeValues"] = "true") + ) + $cloudtrail.security_result.action = "ALLOW" + $cloudtrail.principal.ip = $ip + + match: + $ip over 1h + + outcome: + $risk_score = max(35) + $mitre_attack_tactic = "Credential Access" + $mitre_attack_technique = "Credentials from Password Stores" + $mitre_attack_technique_id = "T1555" + $event_count = count_distinct($cloudtrail.metadata.id) + $network_http_user_agent = array_distinct($cloudtrail.network.http.user_agent) + $principal_ip = array_distinct($cloudtrail.principal.ip) + $principal_ip_country = array_distinct($cloudtrail.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($cloudtrail.principal.ip_geo_artifact.location.state) + $principal_user_display_name = array_distinct($cloudtrail.principal.user.user_display_name) + $recipient_aws_account_id = array_distinct($cloudtrail.additional.fields["recipientAccountId"]) + $aws_region = array_distinct($cloudtrail.principal.location.name) + $target_api_key = array_distinct($cloudtrail.target.resource.attribute.labels["requestParameters.apiKey"]) + $accessed_via_console = array_distinct($cloudtrail.target.resource.attribute.labels["sessionCredentialFromConsole"]) + + condition: + $cloudtrail +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule aws_enable_disable_region { + + meta: + author = "Google Cloud Security" + description = "Detects when an AWS region is enabled or disabled." + rule_id = "mr_905d6ae2-4acc-4969-a85d-707c78db687f" + rule_name = "AWS Enable Or Disable Region" + mitre_attack_tactic = "Defense Evasion" + mitre_attack_technique = "Unused/Unsupported Cloud Regions" + mitre_attack_url = "https://attack.mitre.org/techniques/T1535/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "AWS CloudTrail" + platform = "AWS" + severity = "Medium" + priority = "Medium" + + events: + $cloudtrail.metadata.vendor_name = "AMAZON" + $cloudtrail.metadata.product_name = "AWS CloudTrail" + ( + $cloudtrail.metadata.product_event_type = "EnableRegion" or + $cloudtrail.metadata.product_event_type = "DisableRegion" + ) + $cloudtrail.security_result.action = "ALLOW" + + outcome: + $risk_score = max(50) + $mitre_attack_tactic = "Defense Evasion" + $mitre_attack_technique = "Unused/Unsupported Cloud Regions" + $mitre_attack_technique_id = "T1037" + $event_count = count_distinct($cloudtrail.metadata.id) + $network_http_user_agent = $cloudtrail.network.http.user_agent + $principal_ip = array_distinct($cloudtrail.principal.ip) + $principal_ip_country = array_distinct($cloudtrail.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($cloudtrail.principal.ip_geo_artifact.location.state) + $principal_user_display_name = $cloudtrail.principal.user.user_display_name + $recipient_aws_account_id = $cloudtrail.additional.fields["recipientAccountId"] + $aws_region = $cloudtrail.principal.location.name + $target_resource_name = $cloudtrail.target.resource.name + $target_resource_product_object_id = $cloudtrail.target.resource.product_object_id + + condition: + $cloudtrail +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule aws_user_creates_permanent_access_key { + + meta: + author = "Google Cloud Security" + description = "Detects when an AWS IAM user creates an AWS Access Key for programmatic calls." + rule_id = "mr_ebe72ce0-1e54-4251-afca-ed3fc403cd1f" + rule_name = "AWS User Creates Permanent Access Key" + mitre_attack_tactic = "Defense Evasion, Persistence, Privilege Escalation, Initial Access" + mitre_attack_technique = "Valid Accounts: Cloud Accounts" + mitre_attack_url = "https://attack.mitre.org/techniques/T1078/004/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "AWS CloudTrail" + platform = "AWS" + severity = "Medium" + priority = "Medium" + + events: + $cloudtrail.metadata.vendor_name = "AMAZON" + $cloudtrail.metadata.product_name = "AWS CloudTrail" + $cloudtrail.metadata.product_event_type = "CreateAccessKey" + $cloudtrail.security_result.action = "ALLOW" + + outcome: + $risk_score = max(50) + $mitre_attack_tactic = "Defense Evasion, Persistence, Privilege Escalation, Initial Access" + $mitre_attack_technique = "Valid Accounts: Cloud Accounts" + $mitre_attack_technique_id = "T1078.004" + $event_count = count_distinct($cloudtrail.metadata.id) + $network_http_user_agent = $cloudtrail.network.http.user_agent + $principal_ip = array_distinct($cloudtrail.principal.ip) + $principal_ip_country = array_distinct($cloudtrail.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($cloudtrail.principal.ip_geo_artifact.location.state) + $principal_user_display_name = $cloudtrail.principal.user.user_display_name + $recipient_aws_account_id = $cloudtrail.additional.fields["recipientAccountId"] + $aws_region = $cloudtrail.principal.location.name + $target_resource_name = $cloudtrail.target.resource.name + $target_resource_product_object_id = $cloudtrail.target.resource.product_object_id + + condition: + $cloudtrail +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule aws_delete_cloudwatch_log_group { + + meta: + author = "Google Cloud Security" + description = "Detects when a CloudWatch log group is deleted." + rule_id = "mr_e1e4e137-341a-4302-af26-3bfe599bcc98" + rule_name = "AWS Delete CloudWatch Log Group" + mitre_attack_tactic = "Defense Evasion" + mitre_attack_technique = "Impair Defenses: Disable Cloud Logs" + mitre_attack_url = "https://attack.mitre.org/techniques/T1562/008/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "AWS CloudTrail" + platform = "AWS" + severity = "High" + priority = "High" + + events: + $cloudtrail.metadata.vendor_name = "AMAZON" + $cloudtrail.metadata.product_name = "AWS CloudTrail" + ($cloudtrail.metadata.product_event_type = "DeleteLogGroup") + $cloudtrail.security_result.action = "ALLOW" + $cloudtrail.principal.user.user_display_name = $user_id + + match: + $user_id over 1h + + outcome: + $risk_score = max(75) + $mitre_attack_tactic = "Defense Evasion" + $mitre_attack_technique = "Impair Defenses: Disable Cloud Logs" + $mitre_attack_technique_id = "T1562.008" + $event_count = count_distinct($cloudtrail.metadata.id) + $network_http_user_agent = array_distinct($cloudtrail.network.http.user_agent) + $principal_ip = array_distinct($cloudtrail.principal.ip) + $principal_ip_country = array_distinct($cloudtrail.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($cloudtrail.principal.ip_geo_artifact.location.state) + $principal_user_display_name = array_distinct($cloudtrail.principal.user.user_display_name) + $recipient_aws_account_id = array_distinct($cloudtrail.additional.fields["recipientAccountId"]) + $aws_region = array_distinct($cloudtrail.principal.location.name) + $target_resource_name = array_distinct($cloudtrail.target.resource.name) + $target_resource_product_object_id = array_distinct($cloudtrail.target.resource.product_object_id) + + condition: + $cloudtrail +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule aws_cloudtrail_logging_tampered { + + meta: + author = "Google Cloud Security" + description = "Detects when CloudTrail logging is updated, stopped or deleted." + rule_id = "mr_86f08675-4130-4b47-8978-067c18c8cb55" + rule_name = "AWS CloudTrail Logging Tampered" + mitre_attack_tactic = "Defense Evasion" + mitre_attack_technique = "Impair Defenses: Disable Cloud Logs" + mitre_attack_url = "https://attack.mitre.org/techniques/T1562/008/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "AWS CloudTrail" + platform = "AWS" + severity = "High" + priority = "High" + + events: + $cloudtrail.metadata.vendor_name = "AMAZON" + $cloudtrail.metadata.product_name = "AWS CloudTrail" + ( + $cloudtrail.metadata.product_event_type = "UpdateTrail" or + $cloudtrail.metadata.product_event_type = "StopLogging" or + $cloudtrail.metadata.product_event_type = "DeleteTrail" or + $cloudtrail.metadata.product_event_type = "PutEventSelectors" + ) + $cloudtrail.security_result.action = "ALLOW" + $cloudtrail.principal.user.user_display_name = $user_id + + match: + $user_id over 1h + + outcome: + $risk_score = max(75) + $mitre_attack_tactic = "Defense Evasion" + $mitre_attack_technique = "Impair Defenses: Disable Cloud Logs" + $mitre_attack_technique_id = "T1562.008" + $event_count = count_distinct($cloudtrail.metadata.id) + $network_http_user_agent = array_distinct($cloudtrail.network.http.user_agent) + $principal_ip = array_distinct($cloudtrail.principal.ip) + $principal_ip_country = array_distinct($cloudtrail.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($cloudtrail.principal.ip_geo_artifact.location.state) + $principal_user_display_name = array_distinct($cloudtrail.principal.user.user_display_name) + $recipient_aws_account_id = array_distinct($cloudtrail.additional.fields["recipientAccountId"]) + $aws_region = array_distinct($cloudtrail.principal.location.name) + $target_resource_name = array_distinct($cloudtrail.target.resource.name) + $target_resource_product_object_id = array_distinct($cloudtrail.target.resource.product_object_id) + + condition: + $cloudtrail +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule aws_ec2_get_windows_admin_password { + + meta: + author = "Google Cloud Security" + description = "Detects a successful attempt to retrieve the encrypted Administrator password for a Windows EC2 instance." + rule_id = "mr_92364192-b3c7-4e5d-a1a1-eb7b3adbd0e4" + rule_name = "AWS EC2 Get Windows Admin Password" + mitre_attack_tactic = "Credential Access" + mitre_attack_technique = "Credentials from Password Stores" + mitre_attack_url = "https://attack.mitre.org/techniques/T1555/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "AWS CloudTrail" + platform = "AWS" + severity = "High" + priority = "High" + + events: + $cloudtrail.metadata.vendor_name = "AMAZON" + $cloudtrail.metadata.product_name = "AWS CloudTrail" + $cloudtrail.metadata.product_event_type = "GetPasswordData" + $cloudtrail.security_result.action = "ALLOW" + $cloudtrail.principal.ip = $ip + + match: + $ip over 1h + + outcome: + $risk_score = max(75) + $mitre_attack_tactic = "Credential Access" + $mitre_attack_technique = "Credentials from Password Stores" + $mitre_attack_technique_id = "T1555" + $event_count = count_distinct($cloudtrail.metadata.id) + $network_http_user_agent = array_distinct($cloudtrail.network.http.user_agent) + $principal_ip = array_distinct($cloudtrail.principal.ip) + $principal_ip_country = array_distinct($cloudtrail.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($cloudtrail.principal.ip_geo_artifact.location.state) + $principal_user_display_name = array_distinct($cloudtrail.principal.user.user_display_name) + $recipient_aws_account_id = array_distinct($cloudtrail.additional.fields["recipientAccountId"]) + $aws_region = array_distinct($cloudtrail.principal.location.name) + $target_resource_ancestors_product_object_id = array_distinct($cloudtrail.target.resource_ancestors.product_object_id) + + condition: + $cloudtrail +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule aws_high_number_of_unknown_user_authentication_attempts { + + meta: + author = "Google Cloud Security" + description = "Detects when a high number of failed authentication attempts happen for unknown users." + rule_id = "mr_3ddfee11-c959-4283-8fb4-1f57bdaaf2b1" + rule_name = "AWS High Number Of Unknown User Authentication Attempts" + mitre_attack_tactic = "Credential Access" + mitre_attack_technique = "Brute Force: Credential Stuffing" + mitre_attack_url = "https://attack.mitre.org/techniques/T1110/004/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "AWS CloudTrail" + platform = "AWS" + severity = "Low" + priority = "Low" + + events: + $fail.metadata.vendor_name = "AMAZON" + $fail.metadata.product_name = "AWS CloudTrail" + $fail.metadata.event_type = "USER_LOGIN" + $fail.metadata.product_event_type = "ConsoleLogin" + $fail.security_result.action = "BLOCK" + $fail.security_result.description = "Reason: No username found in supplied account" + $fail.principal.ip = $ip + + match: + $ip over 10m + + outcome: + $risk_score = max(35) + $mitre_attack_tactic = "Credential Access" + $mitre_attack_technique = "Brute Force: Credential Stuffing" + $mitre_attack_technique_id = "T1110.004" + $event_count = count_distinct($fail.metadata.id) + $network_http_user_agent = array_distinct($fail.network.http.user_agent) + $principal_ip = array_distinct($fail.principal.ip) + $principal_ip_country = array_distinct($fail.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($fail.principal.ip_geo_artifact.location.state) + $target_user_display_name = array_distinct($fail.target.user.user_display_name) + $recipient_aws_account_id = array_distinct($fail.additional.fields["recipientAccountId"]) + $target_resource_name = array_distinct($fail.target.resource.name) + $target_resource_product_object_id = array_distinct($fail.target.resource.product_object_id) + $security_result_description = array_distinct($fail.security_result.description) + + condition: + #fail >= 10 +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule aws_s3_made_public_by_acl { + meta: + author = "Google Cloud Security" + description = "Detect when an AWS S3 bucket is made public using ACL." + rule_id = "mr_f0255a99-d90c-4640-a56e-0145f2672c2c" + rule_name = "AWS S3 Bucket Made Public By ACL" + mitre_attack_tactic = "Defense Evasion" + mitre_attack_technique = "Impair Defenses" + mitre_attack_url = "https://attack.mitre.org/techniques/T1562/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "AWS CloudTrail" + platform = "AWS" + severity = "High" + priority = "High" + + events: + $cloudtrail.metadata.vendor_name = "AMAZON" + $cloudtrail.metadata.product_name = "AWS CloudTrail" + $cloudtrail.metadata.product_event_type = "PutBucketAcl" + ( + $cloudtrail.target.resource.attribute.labels["AccessControlList Grantee URI"] = "http://acs.amazonaws.com/groups/global/AuthenticatedUsers" or + $cloudtrail.target.resource.attribute.labels["AccessControlList Grantee URI"] = "http://acs.amazonaws.com/groups/global/AllUsers" + ) + $cloudtrail.security_result.action = "ALLOW" + $cloudtrail.principal.user.userid = $user_id + + match: + $user_id over 1h + + outcome: + $risk_score = max(75) + $mitre_attack_tactic = "Defense Evasion" + $mitre_attack_technique = "Impair Defenses" + $mitre_attack_technique_id = "T1562" + $event_count = count_distinct($cloudtrail.metadata.id) + $network_http_user_agent = array_distinct($cloudtrail.network.http.user_agent) + $principal_ip = array_distinct($cloudtrail.principal.ip) + $principal_ip_country = array_distinct($cloudtrail.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($cloudtrail.principal.ip_geo_artifact.location.state) + $principal_user_display_name = array_distinct($cloudtrail.principal.user.user_display_name) + $recipient_aws_account_id = array_distinct($cloudtrail.additional.fields["recipientAccountId"]) + $aws_region = array_distinct($cloudtrail.principal.location.name) + $target_resource_name = array_distinct($cloudtrail.target.resource.name) + $target_resource_product_object_id = array_distinct($cloudtrail.target.resource.product_object_id) + + condition: + $cloudtrail +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule aws_rds_snapshot_shared_publicly { + + meta: + author = "Google Cloud Security" + description = "Detects when an Amazon RDS Snapshot is shared publicly." + rule_id = "mr_d87cf718-8a9c-4f1d-bcf0-20f4f5f59d02" + rule_name = "AWS RDS Snapshot Shared Publicly" + mitre_attack_tactic = "Exfiltration" + mitre_attack_technique = "Transfer Data to Cloud Account" + mitre_attack_url = "https://attack.mitre.org/techniques/T1537/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "AWS CloudTrail" + platform = "AWS" + severity = "High" + priority = "High" + + events: + $cloudtrail.metadata.vendor_name = "AMAZON" + $cloudtrail.metadata.product_name = "AWS CloudTrail" + ( + $cloudtrail.metadata.product_event_type = "ModifyDBSnapshotAttribute" or + $cloudtrail.metadata.product_event_type = "ModifyDBClusterSnapshotAttribute" + ) + $cloudtrail.target.resource.attribute.labels["Request Parameters Values To Add"] = "all" + $cloudtrail.target.resource.attribute.labels["Request Parameters Attribute Name"] = "restore" + $cloudtrail.security_result.action = "ALLOW" + $cloudtrail.principal.user.userid = $user_id + + match: + $user_id over 1h + + outcome: + $risk_score = max(75) + $mitre_attack_tactic = "Exfiltration" + $mitre_attack_technique = "Transfer Data to Cloud Account" + $mitre_attack_technique_id = "T1537" + $event_count = count_distinct($cloudtrail.metadata.id) + $network_http_user_agent = array_distinct($cloudtrail.network.http.user_agent) + $principal_ip = array_distinct($cloudtrail.principal.ip) + $principal_ip_country = array_distinct($cloudtrail.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($cloudtrail.principal.ip_geo_artifact.location.state) + $principal_user_display_name = array_distinct($cloudtrail.principal.user.user_display_name) + $recipient_aws_account_id = array_distinct($cloudtrail.additional.fields["recipientAccountId"]) + $aws_region = array_distinct($cloudtrail.principal.location.name) + $target_resource_name = array_distinct($cloudtrail.target.resource.name) + $target_resource_product_object_id = array_distinct($cloudtrail.target.resource.product_object_id) + + condition: + $cloudtrail +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule aws_lambda_update_function_code { + + meta: + author = "Google Cloud Security" + description = "Detects an IAM user attempting to update/modify AWS lambda code." + rule_id = "mr_046e8bc7-2d48-4118-ae38-eb095a4333e3" + rule_name = "AWS Lambda Update Function Code" + mitre_attack_tactic = "Execution" + mitre_attack_technique = "Serverless Execution" + mitre_attack_url = "https://attack.mitre.org/techniques/T1648/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "AWS CloudTrail" + platform = "AWS" + severity = "Low" + priority = "Low" + + events: + $cloudtrail.metadata.vendor_name = "AMAZON" + $cloudtrail.metadata.product_name = "AWS CloudTrail" + $cloudtrail.metadata.product_event_type = /UpdateFunctionCode/ + $cloudtrail.security_result.action = "ALLOW" + $cloudtrail.principal.user.userid = $user_id + + match: + $user_id over 1h + + outcome: + $risk_score = max(35) + $mitre_attack_tactic = "Execution" + $mitre_attack_technique = "Serverless Execution" + $mitre_attack_technique_id = "T1648" + $event_count = count_distinct($cloudtrail.metadata.id) + $network_http_user_agent = array_distinct($cloudtrail.network.http.user_agent) + $principal_ip = array_distinct($cloudtrail.principal.ip) + $principal_ip_country = array_distinct($cloudtrail.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($cloudtrail.principal.ip_geo_artifact.location.state) + $principal_user_display_name = array_distinct($cloudtrail.principal.user.user_display_name) + $recipient_aws_account_id = array_distinct($cloudtrail.additional.fields["recipientAccountId"]) + $aws_region = array_distinct($cloudtrail.principal.location.name) + $target_resource_name = array_distinct($cloudtrail.target.resource.name) + $target_resource_product_object_id = array_distinct($cloudtrail.target.resource.product_object_id) + + condition: + $cloudtrail +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule aws_config_service_modified { + + meta: + author = "Google Cloud Security" + description = "Detects when AWS Config Service is updated, stopped or deleted." + rule_id = "mr_9a5af6d7-5119-46db-ad24-72d7e873a56b" + rule_name = "AWS Config Service Modified" + mitre_attack_tactic = "Defense Evasion" + mitre_attack_technique = "Impair Defenses: Disable Cloud Logs" + mitre_attack_url = "https://attack.mitre.org/techniques/T1562/008/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "AWS CloudTrail" + platform = "AWS" + severity = "High" + priority = "High" + + events: + $cloudtrail.metadata.vendor_name = "AMAZON" + $cloudtrail.metadata.product_name = "AWS CloudTrail" + ( + $cloudtrail.metadata.product_event_type = "StopConfigurationRecorder" or + $cloudtrail.metadata.product_event_type = "DeleteConfigurationRecorder" or + $cloudtrail.metadata.product_event_type = "DeleteDeliveryChannel" or + $cloudtrail.metadata.product_event_type = "PutDeliveryChannel" or + $cloudtrail.metadata.product_event_type = "PutConfigurationRecorder" + ) + $cloudtrail.security_result.action = "ALLOW" + $cloudtrail.principal.user.user_display_name = $user_id + + match: + $user_id over 1h + + outcome: + $risk_score = max(75) + $mitre_attack_tactic = "Defense Evasion" + $mitre_attack_technique = "Impair Defenses: Disable Cloud Logs" + $mitre_attack_technique_id = "T1562.008" + $event_count = count_distinct($cloudtrail.metadata.id) + $network_http_user_agent = array_distinct($cloudtrail.network.http.user_agent) + $principal_ip = array_distinct($cloudtrail.principal.ip) + $principal_ip_country = array_distinct($cloudtrail.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($cloudtrail.principal.ip_geo_artifact.location.state) + $principal_user_display_name = array_distinct($cloudtrail.principal.user.user_display_name) + $recipient_aws_account_id = array_distinct($cloudtrail.additional.fields["recipientAccountId"]) + $aws_region = array_distinct($cloudtrail.principal.location.name) + $target_resource_name = array_distinct($cloudtrail.target.resource.name) + $target_resource_product_object_id = array_distinct($cloudtrail.target.resource.product_object_id) + + condition: + $cloudtrail +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule aws_privilege_escalation_using_iam_login_profile { + + meta: + author = "Google Cloud Security" + description = "Detect when a user creates or updates a login profile for another user and escalates privileges using this new user from the same IP." + rule_id = "mr_b0d13079-dbe7-4c19-a8e9-23f98655a29b" + rule_name = "AWS Privilege Escalation Using IAM Login Profile" + mitre_attack_tactic = "Persistence" + mitre_attack_technique = "Cloud Account" + mitre_attack_url = "https://attack.mitre.org/techniques/T1136/003/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "AWS CloudTrail" + platform = "AWS" + severity = "Low" + priority = "Low" + + events: + $profile.metadata.vendor_name = "AMAZON" + $profile.metadata.product_name = "AWS CloudTrail" + $profile.metadata.product_event_type = "CreateLoginProfile" or $profile.metadata.product_event_type = "UpdateLoginProfile" + $profile.security_result.action= "ALLOW" + $profile.principal.user.userid = $p_userid + $profile.target.user.userid = $t_userid + + $login.metadata.vendor_name = "AMAZON" + $login.metadata.product_name = "AWS CloudTrail" + $login.metadata.event_type = "USER_LOGIN" + $login.metadata.product_event_type = "ConsoleLogin" + $login.security_result.action= "ALLOW" + + //Same IP address + $login.principal.ip = $profile.principal.ip + + //User created and logged in + $profile.principal.user.user_display_name != $profile.target.user.userid + $login.target.user.user_display_name = $profile.target.user.userid + + $profile.metadata.event_timestamp.seconds < $login.metadata.event_timestamp.seconds + + match: + $p_userid over 1h + + outcome: + $risk_score = max(35) + $mitre_attack_tactic = "Persistence" + $mitre_attack_technique = "Cloud Account" + $mitre_attack_technique_id = "T1136.003" + $event_count = count_distinct($login.metadata.id) + $network_http_user_agent = array_distinct($login.network.http.user_agent) + $principal_ip = array_distinct($login.principal.ip) + $principal_ip_country = array_distinct($login.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($login.principal.ip_geo_artifact.location.state) + $principal_user_display_name = array_distinct($login.principal.user.user_display_name) + $dc_principal_user_display_name = count_distinct($login.principal.user.user_display_name) + $is_mfa_used = array_distinct($login.principal.user.attribute.labels["mfaAuthenticated"]) + $target_resource_name = array_distinct($login.target.resource.name) + $target_resource_product_object_id = array_distinct($login.target.resource.product_object_id) + + condition: + $profile and $login +} +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule aws_cloudfront_insecure_ssl_policy { + + meta: + author = "Google Cloud Security" + description = "Detects when an insecure SSL policy is configured for an AWS CloudFront distribution." + rule_id = "mr_dc0d66a6-121c-4b01-9370-3bf7fd25de1e" + rule_name = "AWS CloudFront Insecure SSL Policy" + mitre_attack_tactic = "Defense Evasion" + mitre_attack_technique = "Weaken Encryption: Reduce Key Space" + mitre_attack_url = "https://attack.mitre.org/techniques/T1600/001/" + mitre_attack_version = "v15.1" + type = "Alert" + data_source = "AWS CloudTrail" + platform = "AWS" + severity = "Low" + priority = "Low" + + events: + $cloudtrail.metadata.vendor_name = "AMAZON" + $cloudtrail.metadata.product_name = "AWS CloudTrail" + ($cloudtrail.metadata.product_event_type = "CreateDistribution" or $cloudtrail.metadata.product_event_type = "UpdateDistribution") + $cloudtrail.target.resource.attribute.labels["requestParameters.distributionConfig.viewerCertificate.minimumProtocolVersion"] = "TLSv1" or + $cloudtrail.target.resource.attribute.labels["requestParameters.distributionConfig.viewerCertificate.minimumProtocolVersion"] = "SSLv3" or + $cloudtrail.target.resource.attribute.labels["requestParameters.distributionConfig.viewerCertificate.minimumProtocolVersion"] = "TLSv1_2016" or + $cloudtrail.target.resource.attribute.labels["requestParameters.distributionConfig.viewerCertificate.minimumProtocolVersion"] = "TLSv1.1_2016" + + outcome: + $risk_score = max(35) + $mitre_attack_tactic = "Defense Evasion" + $mitre_attack_technique = "Weaken Encryption: Reduce Key Space" + $mitre_attack_technique_id = "T1600.001" + $event_count = count_distinct($cloudtrail.metadata.id) + $network_http_user_agent = array_distinct($cloudtrail.network.http.user_agent) + $principal_ip = array_distinct($cloudtrail.principal.ip) + $principal_ip_country = array_distinct($cloudtrail.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($cloudtrail.principal.ip_geo_artifact.location.state) + $principal_user_display_name = array_distinct($cloudtrail.principal.user.user_display_name) + $recipient_aws_account_id = array_distinct($cloudtrail.additional.fields["recipientAccountId"]) + $aws_region = array_distinct($cloudtrail.principal.location.name) + $accessed_via_console = array_distinct($cloudtrail.target.resource.attribute.labels["sessionCredentialFromConsole"]) + $cloudfront_distribution = array_distinct($cloudtrail.target.resource.attribute.labels["responseElements.distribution.aRN"]) + $ssl_security_policy = array_distinct($cloudtrail.target.resource.attribute.labels["requestParameters.distributionConfig.viewerCertificate.minimumProtocolVersion"]) + + condition: + $cloudtrail +} +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule aws_iam_access_analyzer_deleted { + + meta: + author = "Google Cloud Security" + description = "Detects when AWS IAM Access Analyzer is deleted." + rule_id = "mr_c1c8c5e4-ad04-40de-b42e-9d1086360796" + rule_name = "AWS IAM Access Analyzer Deleted" + mitre_attack_tactic = "Defense Evasion" + mitre_attack_technique = "Impair Defenses: Disable Cloud Logs" + mitre_attack_url = "https://attack.mitre.org/techniques/T1562/008/" + mitre_attack_version = "v15.1" + type = "Alert" + data_source = "AWS CloudTrail" + platform = "AWS" + severity = "Low" + priority = "Low" + + events: + $cloudtrail.metadata.vendor_name = "AMAZON" + $cloudtrail.metadata.product_name = "AWS CloudTrail" + $cloudtrail.metadata.event_type = "RESOURCE_DELETION" + $cloudtrail.metadata.product_event_type = "DeleteAnalyzer" + $cloudtrail.security_result.action = "ALLOW" + + outcome: + $risk_score = max(35) + $mitre_attack_tactic = "Defense Evasion" + $mitre_attack_technique = "Impair Defenses: Disable Cloud Logs" + $mitre_attack_technique_id = "T1562.008" + $event_count = count_distinct($cloudtrail.metadata.id) + $network_http_user_agent = array_distinct($cloudtrail.network.http.user_agent) + $principal_ip = array_distinct($cloudtrail.principal.ip) + $principal_ip_country = array_distinct($cloudtrail.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($cloudtrail.principal.ip_geo_artifact.location.state) + $principal_user_display_name = array_distinct($cloudtrail.principal.user.user_display_name) + $recipient_aws_account_id = array_distinct($cloudtrail.additional.fields["recipientAccountId"]) + $aws_region = array_distinct($cloudtrail.principal.location.name) + $target_resource_name = array_distinct($cloudtrail.target.resource.name) + + condition: + $cloudtrail +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule aws_security_group_open_to_world { + + meta: + author = "Google Cloud Security" + description = "Detect when an AWS security group is opened to the world (0.0.0.0/0) or (::/0)" + rule_id = "mr_51e7e8c9-f460-4207-8aa9-70a58d3d1ee3" + rule_name = "AWS Security Group Open To The World" + mitre_attack_tactic = "Defense Evasion" + mitre_attack_technique = "Impair Defenses" + mitre_attack_url = "https://attack.mitre.org/techniques/T1562/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "AWS CloudTrail" + platform = "AWS" + severity = "High" + priority = "High" + + events: + $cloudtrail.metadata.vendor_name = "AMAZON" + $cloudtrail.metadata.product_name = "AWS CloudTrail" + $cloudtrail.metadata.product_event_type = "AuthorizeSecurityGroupIngress" + ( + $cloudtrail.target.resource.attribute.labels["ipPermissions cidrIp"] = "0.0.0.0/0" or + $cloudtrail.target.resource.attribute.labels["ipPermissions cidrIpv6"] = "::/0" + ) + $cloudtrail.security_result.action = "ALLOW" + $cloudtrail.additional.fields["recipientAccountId"] = $accountId + + match: + $accountId over 1h + + outcome: + $risk_score = max(75) + $mitre_attack_tactic = "Defense Evasion" + $mitre_attack_technique = "Impair Defenses" + $mitre_attack_technique_id = "T1562" + $event_count = count_distinct($cloudtrail.metadata.id) + $network_http_user_agent = array_distinct($cloudtrail.network.http.user_agent) + $principal_ip = array_distinct($cloudtrail.principal.ip) + $principal_ip_country = array_distinct($cloudtrail.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($cloudtrail.principal.ip_geo_artifact.location.state) + $principal_user_display_name = array_distinct($cloudtrail.principal.user.user_display_name) + $recipient_aws_account_id = array_distinct($cloudtrail.additional.fields["recipientAccountId"]) + $aws_region = array_distinct($cloudtrail.principal.location.name) + $target_resource_name = array_distinct($cloudtrail.target.resource.name) + $target_resource_product_object_id = array_distinct($cloudtrail.target.resource.product_object_id) + + condition: + $cloudtrail +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule aws_privilege_escalation_using_iam_access_key { + + meta: + author = "Google Cloud Security" + description = "Detect when a user creates a new access key for another user and escalates privileges using this newly created access key from the same IP." + rule_id = "mr_a28c56ea-b5e6-4e23-8cb8-f306587b832b" + rule_name = "AWS Privilege Escalation Using IAM Access Key" + mitre_attack_tactic = "Persistence" + mitre_attack_technique = "Cloud Account" + mitre_attack_url = "https://attack.mitre.org/techniques/T1136/003/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "AWS CloudTrail" + platform = "AWS" + severity = "Low" + priority = "Low" + + events: + $accesskey.metadata.vendor_name = "AMAZON" + $accesskey.metadata.product_name = "AWS CloudTrail" + $accesskey.metadata.product_event_type = "CreateAccessKey" + $accesskey.security_result.action= "ALLOW" + $accesskey.principal.user.user_display_name != $accesskey.target.user.userid + $accesskey.principal.user.userid = $p_userid + $accesskey.target.user.userid = $t_userid + + $privesc.metadata.vendor_name = "AMAZON" + $privesc.metadata.product_name = "AWS CloudTrail" + + //Same IP address and Access Key used + $accesskey.principal.ip = $privesc.principal.ip + $accesskey.target.resource.product_object_id = $privesc.additional.fields["accessKeyId"] + $accesskey.metadata.event_timestamp.seconds < $privesc.metadata.event_timestamp.seconds + + match: + $p_userid over 1h + + outcome: + $risk_score = max(35) + $mitre_attack_tactic = "Persistence" + $mitre_attack_technique = "Cloud Account" + $mitre_attack_technique_id = "T1136.003" + $event_count = count_distinct($privesc.metadata.id) + $network_http_user_agent = array_distinct($privesc.network.http.user_agent) + $principal_ip = array_distinct($privesc.principal.ip) + $principal_ip_country = array_distinct($privesc.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($privesc.principal.ip_geo_artifact.location.state) + $principal_user_display_name = array_distinct($privesc.principal.user.user_display_name) + $dc_principal_user_display_name = count_distinct($privesc.principal.user.user_display_name) + $is_mfa_used = array_distinct($privesc.principal.user.attribute.labels["mfaAuthenticated"]) + $target_resource_name = array_distinct($privesc.target.resource.name) + $target_resource_product_object_id = array_distinct($privesc.target.resource.product_object_id) + $product_event_types = array_distinct($privesc.metadata.product_event_type) + + condition: + $accesskey and $privesc +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule aws_excessive_successful_discovery_events { + + meta: + author = "Google Cloud Security" + description = "Detects excessive successful events within a 5 minute timeframe from an IAM User." + rule_id = "mr_087edc70-9943-498b-b579-aa6017026e39" + rule_name = "AWS Excessive Successful Discovery Events" + mitre_attack_tactic = "Discovery" + mitre_attack_technique = "Cloud Infrastructure Discovery" + mitre_attack_url = "https://attack.mitre.org/techniques/T1580/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "AWS CloudTrail" + platform = "AWS" + severity = "Low" + priority = "Low" + + events: + $cloudtrail.metadata.vendor_name = "AMAZON" + $cloudtrail.metadata.product_name = "AWS CloudTrail" + $cloudtrail.metadata.product_event_type = /^Describe.*|^List.*|^Get.*/ + $cloudtrail.security_result.action = "ALLOW" + $cloudtrail.principal.user.userid = $user_id + $cloudtrail.target.application = $target_application + + match: + $user_id over 5m + + outcome: + $risk_score = max(35) + $mitre_attack_tactic = "Discovery" + $mitre_attack_technique = "Cloud Infrastructure Discovery" + $mitre_attack_technique_id = "T1580" + $event_count = count_distinct($cloudtrail.metadata.id) + $network_http_user_agent = array_distinct($cloudtrail.network.http.user_agent) + $principal_ip = array_distinct($cloudtrail.principal.ip) + $principal_ip_country = array_distinct($cloudtrail.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($cloudtrail.principal.ip_geo_artifact.location.state) + $principal_user_display_name = array_distinct($cloudtrail.principal.user.user_display_name) + $recipient_aws_account_id = array_distinct($cloudtrail.additional.fields["recipientAccountId"]) + $aws_region = array_distinct($cloudtrail.principal.location.name) + $target_resource_name = array_distinct($cloudtrail.target.resource.name) + $target_resource_product_object_id = array_distinct($cloudtrail.target.resource.product_object_id) + $dc_product_event_type = count_distinct($cloudtrail.metadata.product_event_type) + + condition: + $cloudtrail and $dc_product_event_type > 10 +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule aws_delete_vpc_flow_logs { + + meta: + author = "Google Cloud Security" + description = "Detects when AWS VPC FLow Logs are deleted." + rule_id = "mr_b833ecbb-a3fb-4ea6-97dd-2c861c92620b" + rule_name = "AWS Delete VPC Flow Logs" + mitre_attack_tactic = "Defense Evasion" + mitre_attack_technique = "Impair Defenses: Disable Cloud Logs" + mitre_attack_url = "https://attack.mitre.org/techniques/T1562/008/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "AWS CloudTrail" + platform = "AWS" + severity = "Low" + priority = "Low" + + events: + $cloudtrail.metadata.vendor_name = "AMAZON" + $cloudtrail.metadata.product_name = "AWS CloudTrail" + $cloudtrail.metadata.product_event_type = "DeleteFlowLogs" + $cloudtrail.security_result.action = "ALLOW" + $cloudtrail.principal.user.user_display_name = $user_id + + match: + $user_id over 1h + + outcome: + $risk_score = max(75) + $mitre_attack_tactic = "Defense Evasion" + $mitre_attack_technique = "Impair Defenses: Disable Cloud Logs" + $mitre_attack_technique_id = "T1562.008" + $event_count = count_distinct($cloudtrail.metadata.id) + $network_http_user_agent = array_distinct($cloudtrail.network.http.user_agent) + $principal_ip = array_distinct($cloudtrail.principal.ip) + $principal_ip_country = array_distinct($cloudtrail.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($cloudtrail.principal.ip_geo_artifact.location.state) + $principal_user_display_name = array_distinct($cloudtrail.principal.user.user_display_name) + $recipient_aws_account_id = array_distinct($cloudtrail.additional.fields["recipientAccountId"]) + $aws_region = array_distinct($cloudtrail.principal.location.name) + $target_resource_name = array_distinct($cloudtrail.target.resource.name) + $target_resource_product_object_id = array_distinct($cloudtrail.target.resource.product_object_id) + + condition: + $cloudtrail +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule aws_iam_activity_by_s3_browser_utility { + + meta: + author = "Google Cloud Security" + description = "Detect AWS IAM activities associated with the S3 Browser utility." + rule_id = "mr_003e618f-e099-4c72-a170-03d2e03836f9" + rule_name = "AWS IAM Activity By S3 Browser Utility" + reference = "https://permiso.io/blog/s/unmasking-guivil-new-cloud-threat-actor/" + mitre_attack_tactic = "Persistence" + mitre_attack_technique = "Account Manipulation" + mitre_attack_url = "https://attack.mitre.org/techniques/T1098/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "AWS CloudTrail" + platform = "AWS" + severity = "High" + priority = "High" + + events: + $cloudtrail.metadata.vendor_name = "AMAZON" + $cloudtrail.metadata.product_name = "AWS CloudTrail" + $cloudtrail.target.application = "iam.amazonaws.com" + ( + $cloudtrail.metadata.product_event_type = "CreateUser" or + $cloudtrail.metadata.product_event_type = "CreateLoginProfile" or + $cloudtrail.metadata.product_event_type = "CreateAccessKey" or + $cloudtrail.metadata.product_event_type = "PutUserPolicy" + ) + $cloudtrail.network.http.user_agent = /S3 Browser/ + $cloudtrail.security_result.action = "ALLOW" + $cloudtrail.principal.ip = $ip + + match: + $ip over 1h + + outcome: + $risk_score = max(75) + $mitre_attack_tactic = "Persistence" + $mitre_attack_technique = "Account Manipulation" + $mitre_attack_technique_id = "T1098" + $event_count = count_distinct($cloudtrail.metadata.id) + $network_http_user_agent = array_distinct($cloudtrail.network.http.user_agent) + $principal_ip = array_distinct($cloudtrail.principal.ip) + $principal_ip_country = array_distinct($cloudtrail.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($cloudtrail.principal.ip_geo_artifact.location.state) + $target_user_display_name = array_distinct($cloudtrail.target.user.user_display_name) + $recipient_aws_account_id = array_distinct($cloudtrail.additional.fields["recipientAccountId"]) + $aws_region = array_distinct($cloudtrail.principal.location.name) + $target_resource_name = array_distinct($cloudtrail.target.resource.name) + $target_resource_product_object_id = array_distinct($cloudtrail.target.resource.product_object_id) + + condition: + $cloudtrail +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule aws_saml_identity_provider_changes { + + meta: + author = "Google Cloud Security" + description = "Detects create, update or delete events of a SAML provider in AWS." + rule_id = "mr_2f36760a-241d-4ace-9142-db0ccf1992b7" + rule_name = "AWS SAML Identity Provider Changes" + mitre_attack_tactic = "Defense Evasion, Persistence, Privilege Escalation, Initial Access" + mitre_attack_technique = "Valid Accounts" + mitre_attack_url = "https://attack.mitre.org/techniques/T1078/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "AWS CloudTrail" + platform = "AWS" + severity = "Medium" + priority = "Medium" + + events: + $cloudtrail.metadata.vendor_name = "AMAZON" + $cloudtrail.metadata.product_name = "AWS CloudTrail" + ( + $cloudtrail.metadata.product_event_type = "CreateSAMLProvider" or + $cloudtrail.metadata.product_event_type = "UpdateSAMLProvider" or + $cloudtrail.metadata.product_event_type = "DeleteSAMLProvider" + ) + $cloudtrail.security_result.action = "ALLOW" + + outcome: + $risk_score = max(50) + $mitre_attack_tactic = "Defense Evasion, Persistence, Privilege Escalation, Initial Access" + $mitre_attack_technique = "Valid Accounts" + $mitre_attack_technique_id = "T1078" + $event_count = count_distinct($cloudtrail.metadata.id) + $network_http_user_agent = $cloudtrail.network.http.user_agent + $principal_ip = array_distinct($cloudtrail.principal.ip) + $principal_ip_country = array_distinct($cloudtrail.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($cloudtrail.principal.ip_geo_artifact.location.state) + $principal_user_display_name = $cloudtrail.principal.user.user_display_name + $recipient_aws_account_id = $cloudtrail.additional.fields["recipientAccountId"] + $aws_region = $cloudtrail.principal.location.name + $target_resource_name = $cloudtrail.target.resource.name + $target_resource_product_object_id = $cloudtrail.target.resource.product_object_id + + condition: + $cloudtrail +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule aws_api_call_outside_of_organization { + + meta: + author = "Google Cloud Security" + description = "Detects API Calls from AWS accounts that are not part of the organization." + rule_id = "mr_205120b7-6654-410a-ab6d-e40484e2fafb" + rule_name = "AWS API Call Outside Of Organization" + mitre_attack_tactic = "Defense Evasion, Persistence, Privilege Escalation, Initial Access" + mitre_attack_technique = "Valid Accounts: Cloud Accounts" + mitre_attack_url = "https://attack.mitre.org/techniques/T1078/004/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "AWS CloudTrail" + platform = "AWS" + severity = "High" + priority = "High" + + events: + $cloudtrail.metadata.vendor_name = "AMAZON" + $cloudtrail.metadata.product_name = "AWS CloudTrail" + // Requires a Reference List named aws_accounts with a list of approved and known AWS Account IDs + not $cloudtrail.principal.user.group_identifiers in %aws_accounts + not $cloudtrail.target.user.group_identifiers in %aws_accounts + $cloudtrail.additional.fields["recipientAccountId"] = $accountId + + match: + $accountId over 1h + + outcome: + $risk_score = max(75) + $mitre_attack_tactic = "Defense Evasion, Persistence, Privilege Escalation, Initial Access" + $mitre_attack_technique = "Valid Accounts: Cloud Accounts" + $mitre_attack_technique_id = "T1078.004" + $event_count = count_distinct($cloudtrail.metadata.id) + $network_http_user_agent = array_distinct($cloudtrail.network.http.user_agent) + $principal_ip = array_distinct($cloudtrail.principal.ip) + $principal_ip_country = array_distinct($cloudtrail.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($cloudtrail.principal.ip_geo_artifact.location.state) + $principal_user_display_name = array_distinct($cloudtrail.principal.user.user_display_name) + $recipient_aws_account_id = array_distinct($cloudtrail.additional.fields["recipientAccountId"]) + $aws_region = array_distinct($cloudtrail.principal.location.name) + $product_event_type = array_distinct($cloudtrail.metadata.product_event_type) + $target_resource_name = array_distinct($cloudtrail.target.resource.name) + $target_resource_product_object_id = array_distinct($cloudtrail.target.resource.product_object_id) + + condition: + $cloudtrail +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule aws_ec2_ami_or_snapshot_shared_publicly { + + meta: + author = "Google Cloud Security" + description = "Detects when an Amazon EC2 AMI or Snapshot is shared publicly." + rule_id = "mr_843a37db-dcd5-40b2-8b55-a00397fd5c0d" + rule_name = "AWS EC2 AMI Or Snapshot Shared Publicly" + mitre_attack_tactic = "Exfiltration" + mitre_attack_technique = "Transfer Data to Cloud Account" + mitre_attack_url = "https://attack.mitre.org/techniques/T1537/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "AWS CloudTrail" + platform = "AWS" + severity = "High" + priority = "High" + + events: + $cloudtrail.metadata.vendor_name = "AMAZON" + $cloudtrail.metadata.product_name = "AWS CloudTrail" + ( + $cloudtrail.metadata.product_event_type = "ModifyImageAttribute" or + $cloudtrail.metadata.product_event_type = "ModifySnapshotAttribute" + ) + $cloudtrail.target.resource.attribute.labels["Add Items Group"] = "all" + $cloudtrail.security_result.action = "ALLOW" + $cloudtrail.principal.user.userid = $user_id + + match: + $user_id over 1h + + outcome: + $risk_score = max(75) + $mitre_attack_tactic = "Exfiltration" + $mitre_attack_technique = "Transfer Data to Cloud Account" + $mitre_attack_technique_id = "T1537" + $event_count = count_distinct($cloudtrail.metadata.id) + $network_http_user_agent = array_distinct($cloudtrail.network.http.user_agent) + $principal_ip = array_distinct($cloudtrail.principal.ip) + $principal_ip_country = array_distinct($cloudtrail.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($cloudtrail.principal.ip_geo_artifact.location.state) + $principal_user_display_name = array_distinct($cloudtrail.principal.user.user_display_name) + $recipient_aws_account_id = array_distinct($cloudtrail.additional.fields["recipientAccountId"]) + $aws_region = array_distinct($cloudtrail.principal.location.name) + $target_resource_name = array_distinct($cloudtrail.target.resource.name) + $target_resource_product_object_id = array_distinct($cloudtrail.target.resource.product_object_id) + + condition: + $cloudtrail +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule aws_account_leaving_or_removed_from_organization { + + meta: + author = "Google Cloud Security" + description = "Detect an AWS account attempting to leave or being removed from an AWS organization." + rule_id = "mr_eb9b7a74-0ad2-43e1-bf93-376844fe62b6" + rule_name = "AWS Account Leaving Or Removed From The Organization" + mitre_attack_tactic = "Defense Evasion" + mitre_attack_technique = "Impair Defenses" + mitre_attack_url = "https://attack.mitre.org/techniques/T1562/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "AWS CloudTrail" + platform = "AWS" + severity = "Low" + priority = "Low" + + events: + $cloudtrail.metadata.vendor_name = "AMAZON" + $cloudtrail.metadata.product_name = "AWS CloudTrail" + ( + $cloudtrail.metadata.product_event_type = "LeaveOrganization" or + $cloudtrail.metadata.product_event_type = "RemoveAccountFromOrganization" + ) + + outcome: + $risk_score = max(35) + $mitre_attack_tactic = "Defense Evasion" + $mitre_attack_technique = "Impair Defenses" + $mitre_attack_technique_id = "T1562" + $event_count = count_distinct($cloudtrail.metadata.id) + $network_http_user_agent = $cloudtrail.network.http.user_agent + $principal_ip = array_distinct($cloudtrail.principal.ip) + $principal_ip_country = array_distinct($cloudtrail.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($cloudtrail.principal.ip_geo_artifact.location.state) + $principal_user_display_name = $cloudtrail.principal.user.user_display_name + $recipient_aws_account_id = $cloudtrail.additional.fields["recipientAccountId"] + $aws_region = $cloudtrail.principal.location.name + $target_resource_name = $cloudtrail.target.resource.name + $target_resource_product_object_id = $cloudtrail.target.resource.product_object_id + + condition: + $cloudtrail +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule aws_guardduty_disabled { + + meta: + author = "Google Cloud Security" + description = "Detects when a GuardDuty Detector is disabled or suspended." + rule_id = "mr_22495d55-4177-425f-9a4e-8d836b01e976" + rule_name = "AWS GuardDuty Disabled" + mitre_attack_tactic = "Defense Evasion" + mitre_attack_technique = "Impair Defenses" + mitre_attack_url = "https://attack.mitre.org/techniques/T1562/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "AWS CloudTrail" + platform = "AWS" + severity = "High" + priority = "High" + + events: + $cloudtrail.metadata.vendor_name = "AMAZON" + $cloudtrail.metadata.product_name = "AWS CloudTrail" + $cloudtrail.metadata.product_event_type = "DeleteDetector" or + ($cloudtrail.metadata.product_event_type = "UpdateDetector" and $cloudtrail.target.resource.attribute.labels["enable"] = "false") + $cloudtrail.security_result.action = "ALLOW" + + outcome: + $risk_score = max(75) + $mitre_attack_tactic = "Defense Evasion" + $mitre_attack_technique = "Impair Defenses" + $mitre_attack_technique_id = "T1562" + $event_count = count_distinct($cloudtrail.metadata.id) + $network_http_user_agent = $cloudtrail.network.http.user_agent + $principal_ip = array_distinct($cloudtrail.principal.ip) + $principal_ip_country = array_distinct($cloudtrail.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($cloudtrail.principal.ip_geo_artifact.location.state) + $principal_user_display_name = $cloudtrail.principal.user.user_display_name + $recipient_aws_account_id = $cloudtrail.additional.fields["recipientAccountId"] + $aws_region = $cloudtrail.principal.location.name + $target_resource_name = $cloudtrail.target.resource.name + $target_resource_product_object_id = $cloudtrail.target.resource.product_object_id + + condition: + $cloudtrail +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule aws_unusual_number_of_failed_authentications_from_the_same_ip { + + meta: + author = "Google Cloud Security" + description = "Detects unusual number of failed authentications from the same IP for valid users." + rule_id = "mr_cf1787a4-0145-4093-ad35-2de17f1980ce" + rule_name = "AWS Unusual Number Of Failed Authentication Attempts From The Same IP" + mitre_attack_tactic = "Credential Access" + mitre_attack_technique = "Brute Force: Credential Stuffing" + mitre_attack_url = "https://attack.mitre.org/techniques/T1110/004/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "AWS CloudTrail" + platform = "AWS" + severity = "Medium" + priority = "Medium" + + events: + $fail.metadata.vendor_name = "AMAZON" + $fail.metadata.product_name = "AWS CloudTrail" + $fail.metadata.event_type = "USER_LOGIN" + $fail.metadata.product_event_type = "ConsoleLogin" + $fail.security_result.action = "BLOCK" + $fail.security_result.description = "Reason: Failed authentication" + $fail.principal.ip = $ip + + match: + $ip over 5m + + outcome: + $risk_score = max( + // Unauthorized geographies + if($fail.principal.ip_geo_artifact.location.country_or_region = "Cuba", 40) + + if($fail.principal.ip_geo_artifact.location.country_or_region = "Iran", 40) + + if($fail.principal.ip_geo_artifact.location.country_or_region = "North Korea" , 40) + + if($fail.principal.ip_geo_artifact.location.country_or_region = "Russia", 40) + + if($fail.principal.ip_geo_artifact.location.country_or_region = "Syria", 40) + ) + $mitre_attack_tactic = "Credential Access" + $mitre_attack_technique = "Brute Force: Credential Stuffing" + $mitre_attack_technique_id = "T1110.004" + $event_count = count_distinct($fail.metadata.id) + $network_http_user_agent = array_distinct($fail.network.http.user_agent) + $principal_ip = array_distinct($fail.principal.ip) + $principal_ip_country = array_distinct($fail.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($fail.principal.ip_geo_artifact.location.state) + $principal_user_display_name = array_distinct($fail.principal.user.user_display_name) + $dc_target_user_display_name = count_distinct($fail.target.user.user_display_name) + $is_mfa_used = array_distinct($fail.extensions.auth.auth_details) + $target_resource_name = array_distinct($fail.target.resource.name) + $target_resource_product_object_id = array_distinct($fail.target.resource.product_object_id) + + condition: + $fail and $dc_target_user_display_name > 5 +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule aws_kms_key_disabled_or_scheduled_for_deletion { + + meta: + author = "Google Cloud Security" + description = "Detect when a KMS (Key Management Service) key is disabled or scheduled for deletion." + rule_id = "mr_b1947fef-7b98-4c10-8303-d6c9c032d84e" + rule_name = "AWS KMS Key Disabled Or Scheduled For Deletion" + mitre_attack_tactic = "Impact" + mitre_attack_technique = "Data Destruction" + mitre_attack_url = "https://attack.mitre.org/techniques/T1485/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "AWS CloudTrail" + platform = "AWS" + severity = "High" + priority = "High" + + events: + $cloudtrail.metadata.vendor_name = "AMAZON" + $cloudtrail.metadata.product_name = "AWS CloudTrail" + $cloudtrail.metadata.product_event_type = "DisableKey" or $cloudtrail.metadata.product_event_type = "ScheduleKeyDeletion" + $cloudtrail.security_result.action = "ALLOW" + + outcome: + $risk_score = max(75) + $mitre_attack_tactic = "Impact" + $mitre_attack_technique = "Data Destruction" + $mitre_attack_technique_id = "T1485" + $event_count = count_distinct($cloudtrail.metadata.id) + $network_http_user_agent = $cloudtrail.network.http.user_agent + $principal_ip = array_distinct($cloudtrail.principal.ip) + $principal_ip_country = array_distinct($cloudtrail.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($cloudtrail.principal.ip_geo_artifact.location.state) + $principal_user_display_name = $cloudtrail.principal.user.user_display_name + $recipient_aws_account_id = $cloudtrail.additional.fields["recipientAccountId"] + $aws_region = $cloudtrail.principal.location.name + $target_resource_name = $cloudtrail.target.resource.name + $target_resource_product_object_id = $cloudtrail.target.resource.product_object_id + + condition: + $cloudtrail +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule aws_successful_console_authentication_from_multiple_ips { + + meta: + author = "Google Cloud Security" + description = "Detects when an AWS user successfully authenticating from more than one unique IP address within 5 minutes." + rule_id = "mr_4a221c43-1059-4247-a7a6-69d8ce4dca2c" + rule_name = "AWS Successful Console Authentication From Multiple IPs" + mitre_attack_tactic = "Resource Development" + mitre_attack_technique = "Compromise Accounts" + mitre_attack_url = "https://attack.mitre.org/techniques/T1586/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "AWS CloudTrail" + platform = "AWS" + severity = "Medium" + priority = "Medium" + + events: + $login.metadata.vendor_name = "AMAZON" + $login.metadata.product_name = "AWS CloudTrail" + $login.metadata.event_type = "USER_LOGIN" + $login.metadata.product_event_type = "ConsoleLogin" + $login.security_result.action = "ALLOW" + $login.principal.ip = $ip + $login.target.user.userid = $user_id + + match: + $user_id over 5m + + outcome: + $risk_score = max( + // Unauthorized geographies + if($login.principal.ip_geo_artifact.location.country_or_region = "Cuba", 40) + + if($login.principal.ip_geo_artifact.location.country_or_region = "Iran", 40) + + if($login.principal.ip_geo_artifact.location.country_or_region = "North Korea" , 40) + + if($login.principal.ip_geo_artifact.location.country_or_region = "Russia", 40) + + if($login.principal.ip_geo_artifact.location.country_or_region = "Syria", 40) + ) + $mitre_attack_tactic = "Resource Development" + $mitre_attack_technique = "Compromise Accounts" + $mitre_attack_technique_id = "T1586" + $event_count = count_distinct($login.metadata.id) + $network_http_user_agent = array_distinct($login.network.http.user_agent) + $principal_ip = array_distinct($login.principal.ip) + $principal_ip_country = array_distinct($login.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($login.principal.ip_geo_artifact.location.state) + $target_user_userid = array_distinct($login.target.user.userid) + $is_mfa_used = array_distinct($login.extensions.auth.auth_details) + $target_resource_name = array_distinct($login.target.resource.name) + $target_resource_product_object_id = array_distinct($login.target.resource.product_object_id) + + condition: + $login and #ip > 1 +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule aws_ec2_user_data_modified { + + meta: + author = "Google Cloud Security" + description = "Detect modifications to user data script on an EC2 instance." + rule_id = "mr_3167a29e-abbb-4d72-9f33-93df151d0224" + rule_name = "AWS EC2 User Data Modified" + mitre_attack_tactic = "Privilege Escalation" + mitre_attack_technique = "Boot or Logon Initialization Scripts" + mitre_attack_url = "https://attack.mitre.org/techniques/T1037/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "AWS CloudTrail" + platform = "AWS" + severity = "High" + priority = "High" + + events: + $cloudtrail.metadata.vendor_name = "AMAZON" + $cloudtrail.metadata.product_name = "AWS CloudTrail" + $cloudtrail.metadata.product_event_type = "ModifyInstanceAttribute" + $cloudtrail.target.resource.attribute.labels["Request Parameters User Data"] != "" + $cloudtrail.security_result.action = "ALLOW" + $cloudtrail.target.resource_ancestors.product_object_id = $instanceId + + match: + $instanceId over 1h + + outcome: + $risk_score = max(75) + $mitre_attack_tactic = "Privilege Escalation" + $mitre_attack_technique = "Boot or Logon Initialization Scripts" + $mitre_attack_technique_id = "T1037" + $event_count = count_distinct($cloudtrail.metadata.id) + $network_http_user_agent = array_distinct($cloudtrail.network.http.user_agent) + $principal_ip = array_distinct($cloudtrail.principal.ip) + $principal_ip_country = array_distinct($cloudtrail.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($cloudtrail.principal.ip_geo_artifact.location.state) + $principal_user_display_name = array_distinct($cloudtrail.principal.user.user_display_name) + $recipient_aws_account_id = array_distinct($cloudtrail.additional.fields["recipientAccountId"]) + $aws_region = array_distinct($cloudtrail.principal.location.name) + $target_resource_name = array_distinct($cloudtrail.target.resource.name) + $target_resource_product_object_id = array_distinct($cloudtrail.target.resource.product_object_id) + + condition: + $cloudtrail +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule aws_password_policy_change { + + meta: + author = "Google Cloud Security" + description = "Detects when an existing password policy is updated or deleted in an AWS account." + rule_id = "mr_2e66b918-acfc-46ea-b625-58732558005d" + rule_name = "AWS Password Policy Change" + mitre_attack_tactic = "Discovery" + mitre_attack_technique = "Password Policy Discovery" + mitre_attack_url = "https://attack.mitre.org/techniques/T1201/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "AWS CloudTrail" + platform = "AWS" + severity = "Medium" + priority = "Medium" + + events: + $cloudtrail.metadata.vendor_name = "AMAZON" + $cloudtrail.metadata.product_name = "AWS CloudTrail" + ( + $cloudtrail.metadata.product_event_type = "UpdateAccountPasswordPolicy" or + $cloudtrail.metadata.product_event_type = "DeleteAccountPasswordPolicy" + ) + $cloudtrail.security_result.action = "ALLOW" + + outcome: + $risk_score = max(50) + $mitre_attack_tactic = "Discovery" + $mitre_attack_technique = "Password Policy Discovery" + $mitre_attack_technique_id = "T1201" + $event_count = count_distinct($cloudtrail.metadata.id) + $network_http_user_agent = $cloudtrail.network.http.user_agent + $principal_ip = array_distinct($cloudtrail.principal.ip) + $principal_ip_country = array_distinct($cloudtrail.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($cloudtrail.principal.ip_geo_artifact.location.state) + $principal_user_display_name = $cloudtrail.principal.user.user_display_name + $recipient_aws_account_id = $cloudtrail.additional.fields["recipientAccountId"] + $aws_region = $cloudtrail.principal.location.name + + condition: + $cloudtrail +} +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule aws_alb_insecure_ssl_policy { + + meta: + author = "Google Cloud Security" + description = "Detects when an insecure SSL policy is configured for an AWS Application Load Balancer." + rule_id = "mr_8aace83b-f9f0-45b8-95c5-a4b0bb2cbb85" + rule_name = "AWS Application Load Balancer Insecure SSL Policy" + mitre_attack_tactic = "Defense Evasion" + mitre_attack_technique = "Weaken Encryption: Reduce Key Space" + mitre_attack_url = "https://attack.mitre.org/techniques/T1600/001/" + mitre_attack_version = "v15.1" + type = "Alert" + data_source = "AWS CloudTrail" + platform = "AWS" + severity = "Low" + priority = "Low" + + events: + $cloudtrail.metadata.vendor_name = "AMAZON" + $cloudtrail.metadata.product_name = "AWS CloudTrail" + ($cloudtrail.metadata.product_event_type = "ModifyListener" or $cloudtrail.metadata.product_event_type = "CreateListener") + $cloudtrail.target.resource.attribute.labels["requestParameters.sslPolicy"] = "ELBSecurityPolicy-2016-08" or + $cloudtrail.target.resource.attribute.labels["requestParameters.sslPolicy"] = "ELBSecurityPolicy-TLS13-1-1-2021-06" or + $cloudtrail.target.resource.attribute.labels["requestParameters.sslPolicy"] = "ELBSecurityPolicy-TLS13-1-0-2021-06" or + $cloudtrail.target.resource.attribute.labels["requestParameters.sslPolicy"] = "ELBSecurityPolicy-TLS13-1-1-FIPS-2023-04" or + $cloudtrail.target.resource.attribute.labels["requestParameters.sslPolicy"] = "ELBSecurityPolicy-TLS13-1-0-FIPS-2023-04" or + $cloudtrail.target.resource.attribute.labels["requestParameters.sslPolicy"] = "ELBSecurityPolicy-TLS-1-1-2017-01" or + $cloudtrail.target.resource.attribute.labels["requestParameters.sslPolicy"] = "ELBSecurityPolicy-FS-2018-06" or + $cloudtrail.target.resource.attribute.labels["requestParameters.sslPolicy"] = "ELBSecurityPolicy-2015-05" or + $cloudtrail.target.resource.attribute.labels["requestParameters.sslPolicy"] = "ELBSecurityPolicy-TLS-1-0-2015-04" or + $cloudtrail.target.resource.attribute.labels["requestParameters.sslPolicy"] = "ELBSecurityPolicy-FS-1-1-2019-08" + + outcome: + $risk_score = max(35) + $mitre_attack_tactic = "Defense Evasion" + $mitre_attack_technique = "Weaken Encryption: Reduce Key Space" + $mitre_attack_technique_id = "T1600.001" + $event_count = count_distinct($cloudtrail.metadata.id) + $network_http_user_agent = array_distinct($cloudtrail.network.http.user_agent) + $principal_ip = array_distinct($cloudtrail.principal.ip) + $principal_ip_country = array_distinct($cloudtrail.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($cloudtrail.principal.ip_geo_artifact.location.state) + $principal_user_display_name = array_distinct($cloudtrail.principal.user.user_display_name) + $recipient_aws_account_id = array_distinct($cloudtrail.additional.fields["recipientAccountId"]) + $aws_region = array_distinct($cloudtrail.principal.location.name) + $accessed_via_console = array_distinct($cloudtrail.target.resource.attribute.labels["sessionCredentialFromConsole"]) + $target_resource_name = array_distinct($cloudtrail.target.resource.name) + $ssl_security_policy = array_distinct($cloudtrail.target.resource.attribute.labels["requestParameters.sslPolicy"]) + + condition: + $cloudtrail +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule aws_ses_service_modification { + + meta: + author = "Google Cloud Security" + description = "Detect when the Amazon Simple Email Service (SES) has been modified where an attacker can modify Amazon SES service to propagate phishing emails campaigns." + rule_id = "mr_223bad6a-9c6a-4038-9990-18d3545598aa" + rule_name = "AWS SES Service Modification" + mitre_attack_tactic = "Impact" + mitre_attack_technique = "Resource Hijacking" + mitre_attack_url = "https://attack.mitre.org/techniques/T1496/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "AWS CloudTrail" + platform = "AWS" + severity = "Medium" + priority = "Medium" + + events: + $cloudtrail.metadata.vendor_name = "AMAZON" + $cloudtrail.metadata.product_name = "AWS CloudTrail" + ( + $cloudtrail.metadata.product_event_type = "CreateEmailIdentity" or + $cloudtrail.metadata.product_event_type = "DeleteEmailIdentity" or + $cloudtrail.metadata.product_event_type = "VerifyEmailIdentity" or + $cloudtrail.metadata.product_event_type = "VerifyDomainIdentity" or + $cloudtrail.metadata.product_event_type = "VerifyDomainDkim" + ) + or + ( + ( + $cloudtrail.metadata.product_event_type = "UpdateAccountSendingEnabled" or + $cloudtrail.metadata.product_event_type = "UpdateConfigurationSetSendingEnabled" + ) + and $cloudtrail.target.resource.attribute.labels["enabled"] = "true" + ) + or + ( + ( + $cloudtrail.metadata.product_event_type = "PutAccountSendingAttributes" or + $cloudtrail.metadata.product_event_type = "PutConfigurationSetSendingOptions" + ) + and $cloudtrail.target.resource.attribute.labels["sendingEnabled"] = "true" + ) + $cloudtrail.security_result.action = "ALLOW" + $cloudtrail.principal.user.userid = $user_id + + match: + $user_id over 1h + + outcome: + $risk_score = max(50) + $mitre_attack_tactic = "Impact" + $mitre_attack_technique = "Resource Hijacking" + $mitre_attack_technique_id = "T1496" + $event_count = count_distinct($cloudtrail.metadata.id) + $network_http_user_agent = array_distinct($cloudtrail.network.http.user_agent) + $principal_ip = array_distinct($cloudtrail.principal.ip) + $principal_ip_country = array_distinct($cloudtrail.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($cloudtrail.principal.ip_geo_artifact.location.state) + $principal_user_display_name = array_distinct($cloudtrail.principal.user.user_display_name) + $recipient_aws_account_id = array_distinct($cloudtrail.additional.fields["recipientAccountId"]) + $aws_region = array_distinct($cloudtrail.principal.location.name) + $target_resource_name = array_distinct($cloudtrail.target.resource.name) + $target_resource_product_object_id = array_distinct($cloudtrail.target.resource.product_object_id) + + condition: + $cloudtrail +} +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule aws_backup_plan_deleted { + + meta: + author = "Google Cloud Security" + description = "Detects when AWS Backup Plan is deleted." + rule_id = "mr_ac4b93af-f166-44fa-951d-83f08ded6fd8" + rule_name = "AWS Backup Plan Deleted" + mitre_attack_tactic = "Impact" + mitre_attack_technique = "Inhibit System Recovery" + mitre_attack_url = "https://attack.mitre.org/techniques/T1490/" + mitre_attack_version = "v15.1" + type = "Alert" + data_source = "AWS CloudTrail" + platform = "AWS" + severity = "Low" + priority = "Low" + + events: + $cloudtrail.metadata.vendor_name = "AMAZON" + $cloudtrail.metadata.product_name = "AWS CloudTrail" + $cloudtrail.metadata.event_type = "RESOURCE_DELETION" + ($cloudtrail.metadata.product_event_type = "DeleteBackupPlan" or + $cloudtrail.metadata.product_event_type = "DeleteBackupSelection") + $cloudtrail.security_result.action = "ALLOW" + + outcome: + $risk_score = max(35) + $mitre_attack_tactic = "Impact" + $mitre_attack_technique = "Inhibit System Recovery" + $mitre_attack_technique_id = "T1490" + $event_count = count_distinct($cloudtrail.metadata.id) + $network_http_user_agent = array_distinct($cloudtrail.network.http.user_agent) + $principal_ip = array_distinct($cloudtrail.principal.ip) + $principal_ip_country = array_distinct($cloudtrail.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($cloudtrail.principal.ip_geo_artifact.location.state) + $principal_user_display_name = array_distinct($cloudtrail.principal.user.user_display_name) + $recipient_aws_account_id = array_distinct($cloudtrail.additional.fields["recipientAccountId"]) + $aws_region = array_distinct($cloudtrail.principal.location.name) + + condition: + $cloudtrail +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule aws_s3_public_access_block_removed { + meta: + author = "Google Cloud Security" + description = "Detect when the S3 Public Access Block configuration has been removed from a bucket or an account." + rule_id = "mr_07638aec-6719-467b-9fee-8de4993087fa" + rule_name = "AWS S3 Public Access Block Removed" + mitre_attack_tactic = "Defense Evasion" + mitre_attack_technique = "Impair Defenses" + mitre_attack_url = "https://attack.mitre.org/techniques/T1562/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "AWS CloudTrail" + platform = "AWS" + severity = "High" + priority = "High" + + events: + $cloudtrail.metadata.vendor_name = "AMAZON" + $cloudtrail.metadata.product_name = "AWS CloudTrail" + ( + $cloudtrail.metadata.product_event_type = "DeleteAccountPublicAccessBlock" or + $cloudtrail.metadata.product_event_type = "DeleteBucketPublicAccessBlock" or + ( + ( + $cloudtrail.metadata.product_event_type = "PutBucketPublicAccessBlock" or + $cloudtrail.metadata.product_event_type = "PutAccountPublicAccessBlock" + ) + and + ( + $cloudtrail.target.resource.attribute.labels["RestrictPublicBuckets"] = "true" or + $cloudtrail.target.resource.attribute.labels["BlockPublicPolicy"] = "true" or + $cloudtrail.target.resource.attribute.labels["BlockPublicAcls"] = "true" or + $cloudtrail.target.resource.attribute.labels["IgnorePublicAcls"] = "true" + ) + ) + ) + $cloudtrail.security_result.action = "ALLOW" + $cloudtrail.principal.user.userid = $user_id + + match: + $user_id over 1h + + outcome: + $risk_score = max(75) + $mitre_attack_tactic = "Defense Evasion" + $mitre_attack_technique = "Impair Defenses" + $mitre_attack_technique_id = "T1562" + $event_count = count_distinct($cloudtrail.metadata.id) + $network_http_user_agent = array_distinct($cloudtrail.network.http.user_agent) + $principal_ip = array_distinct($cloudtrail.principal.ip) + $principal_ip_country = array_distinct($cloudtrail.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($cloudtrail.principal.ip_geo_artifact.location.state) + $principal_user_display_name = array_distinct($cloudtrail.principal.user.user_display_name) + $recipient_aws_account_id = array_distinct($cloudtrail.additional.fields["recipientAccountId"]) + $aws_region = array_distinct($cloudtrail.principal.location.name) + $target_resource_name = array_distinct($cloudtrail.target.resource.name) + $target_resource_product_object_id = array_distinct($cloudtrail.target.resource.product_object_id) + + condition: + $cloudtrail +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule aws_new_mfa_method_registered_for_user { + + meta: + author = "Google Cloud Security" + description = "Detects the registration of a new Multi Factor authentication method for an AWS user." + rule_id = "mr_bee2a210-111a-478a-a1a2-caeb9077eca2" + rule_name = "AWS New MFA Method Registered For User" + mitre_attack_tactic = "Credential Access, Defense Evasion, Persistence" + mitre_attack_technique = "Modify Authentication Process: Multi-Factor Authentication" + mitre_attack_url = "https://attack.mitre.org/techniques/T1556/006/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "AWS CloudTrail" + platform = "AWS" + severity = "Medium" + priority = "Medium" + + events: + $cloudtrail.metadata.vendor_name = "AMAZON" + $cloudtrail.metadata.product_name = "AWS CloudTrail" + ( + $cloudtrail.metadata.product_event_type = "CreateVirtualMFADevice" or + $cloudtrail.metadata.product_event_type = "EnableMFADevice" + ) + $cloudtrail.security_result.action = "ALLOW" + $cloudtrail.principal.user.user_display_name = $user_id + + match: + $user_id over 1h + + outcome: + $risk_score = max( + //Baseline + 35 + + // High Risk for AWS Root User + if($cloudtrail.src.user.user_display_name = "AWS Root User", 50) + ) + $mitre_attack_tactic = "Credential Access, Defense Evasion, Persistence" + $mitre_attack_technique = "Modify Authentication Process: Multi-Factor Authentication" + $mitre_attack_technique_id = "T1556.006" + $event_count = count_distinct($cloudtrail.metadata.id) + $network_http_user_agent = array_distinct($cloudtrail.network.http.user_agent) + $principal_ip = array_distinct($cloudtrail.principal.ip) + $principal_ip_country = array_distinct($cloudtrail.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($cloudtrail.principal.ip_geo_artifact.location.state) + $principal_user_display_name = array_distinct($cloudtrail.principal.user.user_display_name) + $recipient_aws_account_id = array_distinct($cloudtrail.additional.fields["recipientAccountId"]) + $aws_region = array_distinct($cloudtrail.principal.location.name) + $target_resource_name = array_distinct($cloudtrail.target.resource.name) + $target_resource_product_object_id = array_distinct($cloudtrail.target.resource.product_object_id) + + condition: + $cloudtrail +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule aws_iam_access_denied_discovery_events { + + meta: + author = "Google Cloud Security" + description = "Detects excessive AccessDenied events within an hour timeframe from an IAM User" + rule_id = "mr_a175b0d9-4488-46cc-880a-2408cb301f41" + rule_name = "AWS IAM Access Denied Discovery Events" + mitre_attack_tactic = "Discovery" + mitre_attack_technique = "Cloud Infrastructure Discovery" + mitre_attack_url = "https://attack.mitre.org/techniques/T1580/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "AWS CloudTrail" + platform = "AWS" + severity = "Low" + priority = "Low" + + events: + $cloudtrail.metadata.vendor_name = "AMAZON" + $cloudtrail.metadata.product_name = "AWS CloudTrail" + $cloudtrail.security_result.rule_id = "AccessDenied" + $cloudtrail.security_result.action = "BLOCK" + $cloudtrail.principal.user.userid = $user_id + $cloudtrail.target.application = $target_application + $cloudtrail.metadata.product_event_type = $product_event_type + + match: + $user_id over 1h + + outcome: + $risk_score = max(35) + $mitre_attack_tactic = "Discovery" + $mitre_attack_technique = "Cloud Infrastructure Discovery" + $mitre_attack_technique_id = "T1580" + $event_count = count_distinct($cloudtrail.metadata.id) + $network_http_user_agent = array_distinct($cloudtrail.network.http.user_agent) + $principal_ip = array_distinct($cloudtrail.principal.ip) + $principal_ip_country = array_distinct($cloudtrail.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($cloudtrail.principal.ip_geo_artifact.location.state) + $principal_user_display_name = array_distinct($cloudtrail.principal.user.user_display_name) + $recipient_aws_account_id = array_distinct($cloudtrail.additional.fields["recipientAccountId"]) + $aws_region = array_distinct($cloudtrail.principal.location.name) + $target_resource_name = array_distinct($cloudtrail.target.resource.name) + $target_resource_product_object_id = array_distinct($cloudtrail.target.resource.product_object_id) + $security_result_description = array_distinct($cloudtrail.security_result.description) + $target_applications = array_distinct($cloudtrail.target.application) + $product_event_types = array_distinct($cloudtrail.metadata.product_event_type) + + condition: + #cloudtrail > 5 and #target_application > 1 and #product_event_type > 1 +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule aws_lateral_movement_using_iam_session_token { + + meta: + author = "Google Cloud Security" + description = "Detect when an IAM session token is created and used from a different IP." + rule_id = "mr_ac0df875-fe5b-49af-bf2a-3da341177754" + rule_name = "AWS Lateral Movement Using IAM Session Token" + mitre_attack_tactic = "Lateral Movement" + mitre_attack_technique = "Use Alternate Authentication Material" + mitre_attack_url = "https://attack.mitre.org/techniques/T1550/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "AWS CloudTrail" + platform = "AWS" + severity = "Low" + priority = "Low" + + events: + $accesskey.metadata.vendor_name = "AMAZON" + $accesskey.metadata.product_name = "AWS CloudTrail" + $accesskey.metadata.product_event_type = "GetSessionToken" + $accesskey.security_result.action= "ALLOW" + $accesskey.principal.user.userid = $p_userid + + $latmove.metadata.vendor_name = "AMAZON" + $latmove.metadata.product_name = "AWS CloudTrail" + + //Different IP address and Same Temp Session Token used + $accesskey.principal.ip != $latmove.principal.ip + $latmove.additional.fields["accessKeyId"] != "" + $accesskey.target.resource.product_object_id = $latmove.additional.fields["accessKeyId"] + $accesskey.metadata.event_timestamp.seconds < $latmove.metadata.event_timestamp.seconds + + match: + $p_userid over 1h + + outcome: + $risk_score = max(35) + $mitre_attack_tactic = "Lateral Movement" + $mitre_attack_technique = "Use Alternate Authentication Material" + $mitre_attack_technique_id = "T1550" + $event_count = count_distinct($latmove.metadata.id) + $network_http_user_agent = array_distinct($latmove.network.http.user_agent) + $principal_ip = array_distinct($latmove.principal.ip) + $principal_ip_country = array_distinct($latmove.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($latmove.principal.ip_geo_artifact.location.state) + $principal_user_display_name = array_distinct($latmove.principal.user.user_display_name) + $dc_principal_user_display_name = count_distinct($latmove.principal.user.user_display_name) + $is_mfa_used = array_distinct($latmove.extensions.auth.auth_details) + $target_resource_name = array_distinct($latmove.target.resource.name) + $target_resource_product_object_id = array_distinct($latmove.target.resource.product_object_id) + $product_event_types = array_distinct($latmove.metadata.product_event_type) + + condition: + $accesskey and $latmove +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule aws_guardduty_publishing_destination_deleted { + + meta: + author = "Google Cloud Security" + description = "Detects when a GuardDuty Detector's publishing destination has been deleted which will prevent the exporting of findings." + rule_id = "mr_630cd3d0-d22f-4e8a-9065-425bdbe1ab32" + rule_name = "AWS GuardDuty Publishing Destination Deleted" + mitre_attack_tactic = "Defense Evasion" + mitre_attack_technique = "Impair Defenses" + mitre_attack_url = "https://attack.mitre.org/techniques/T1562/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "AWS CloudTrail" + platform = "AWS" + severity = "High" + priority = "High" + + events: + $cloudtrail.metadata.vendor_name = "AMAZON" + $cloudtrail.metadata.product_name = "AWS CloudTrail" + $cloudtrail.metadata.product_event_type = "DeletePublishingDestination" + $cloudtrail.security_result.action = "ALLOW" + + outcome: + $risk_score = max(75) + $mitre_attack_tactic = "Defense Evasion" + $mitre_attack_technique = "Impair Defenses" + $mitre_attack_technique_id = "T1562" + $event_count = count_distinct($cloudtrail.metadata.id) + $network_http_user_agent = $cloudtrail.network.http.user_agent + $principal_ip = array_distinct($cloudtrail.principal.ip) + $principal_ip_country = array_distinct($cloudtrail.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($cloudtrail.principal.ip_geo_artifact.location.state) + $principal_user_display_name = $cloudtrail.principal.user.user_display_name + $recipient_aws_account_id = $cloudtrail.additional.fields["recipientAccountId"] + $aws_region = $cloudtrail.principal.location.name + $target_resource_name = $cloudtrail.target.resource.name + $target_resource_product_object_id = $cloudtrail.target.resource.product_object_id + + condition: + $cloudtrail +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule aws_multi_factor_authentication_disabled { + + meta: + author = "Google Cloud Security" + description = "Detects attempts to disable multi-factor authentication for an AWS IAM user." + rule_id = "mr_0d6bd993-c80b-4367-a921-5a542ab826b3" + rule_name = "AWS MultiFactor Authentication Disabled" + mitre_attack_tactic = "Credential Access, Defense Evasion, Persistence" + mitre_attack_technique = "Modify Authentication Process: Multi-Factor Authentication" + mitre_attack_url = "https://attack.mitre.org/techniques/T1556/006/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "AWS CloudTrail" + platform = "AWS" + severity = "Medium" + priority = "Medium" + + events: + $cloudtrail.metadata.vendor_name = "AMAZON" + $cloudtrail.metadata.product_name = "AWS CloudTrail" + ( + $cloudtrail.metadata.product_event_type = "DeleteVirtualMFADevice" or + $cloudtrail.metadata.product_event_type = "DeactivateMFADevice" + ) + $cloudtrail.security_result.action = "ALLOW" + $cloudtrail.principal.user.user_display_name = $user_id + + match: + $user_id over 1h + + outcome: + $risk_score = max( + //Baseline + 35 + + // High Risk for AWS Root User + if($cloudtrail.src.user.user_display_name = "AWS Root User", 50) + ) + $mitre_attack_tactic = "Credential Access, Defense Evasion, Persistence" + $mitre_attack_technique = "Modify Authentication Process: Multi-Factor Authentication" + $mitre_attack_technique_id = "T1556.006" + $event_count = count_distinct($cloudtrail.metadata.id) + $network_http_user_agent = array_distinct($cloudtrail.network.http.user_agent) + $principal_ip = array_distinct($cloudtrail.principal.ip) + $principal_ip_country = array_distinct($cloudtrail.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($cloudtrail.principal.ip_geo_artifact.location.state) + $principal_user_display_name = array_distinct($cloudtrail.principal.user.user_display_name) + $recipient_aws_account_id = array_distinct($cloudtrail.additional.fields["recipientAccountId"]) + $aws_region = array_distinct($cloudtrail.principal.location.name) + $target_resource_name = array_distinct($cloudtrail.target.resource.name) + $target_resource_product_object_id = array_distinct($cloudtrail.target.resource.product_object_id) + + condition: + $cloudtrail +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule aws_successful_login_after_multiple_failed_attempts { + + meta: + author = "Google Cloud Security" + description = "Detects successful login after multiple failed attempts" + rule_id = "mr_8ba028b6-98e3-4983-92e9-c0fe50419a20" + rule_name = "AWS Successful Login After Multiple Failed Attempts" + mitre_attack_tactic = "Defense Evasion, Persistence, Privilege Escalation, Initial Access" + mitre_attack_technique = "Valid Accounts" + mitre_attack_url = "https://attack.mitre.org/techniques/T1078/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "AWS CloudTrail" + platform = "AWS" + severity = "Medium" + priority = "Medium" + + events: + $fail.metadata.vendor_name = "AMAZON" + $fail.metadata.product_name = "AWS CloudTrail" + $fail.metadata.event_type = "USER_LOGIN" + $fail.metadata.product_event_type = "ConsoleLogin" + $fail.security_result.action = "BLOCK" + $fail.security_result.description = "Reason: Failed authentication" + $fail.target.user.user_display_name = $user + + $success.metadata.vendor_name = "AMAZON" + $success.metadata.product_name = "AWS CloudTrail" + $success.metadata.event_type = "USER_LOGIN" + $success.metadata.product_event_type = "ConsoleLogin" + $success.security_result.action = "ALLOW" + $success.security_result.summary = "Login to AWS Console succeeded." + $success.target.user.user_display_name = $user + + $success.metadata.event_timestamp.seconds > $fail.metadata.event_timestamp.seconds + + match: + $user over 15m + + outcome: + $risk_score = max( + // Country mismatch + if($fail.principal.ip_geo_artifact.location.country_or_region = $success.principal.ip_geo_artifact.location.country_or_region, 40) + + // Unauthorized geographies + if($success.principal.ip_geo_artifact.location.country_or_region = "Cuba", 10) + + if($success.principal.ip_geo_artifact.location.country_or_region = "Iran", 10) + + if($success.principal.ip_geo_artifact.location.country_or_region = "North Korea" , 10) + + if($success.principal.ip_geo_artifact.location.country_or_region = "Russia", 10) + + if($success.principal.ip_geo_artifact.location.country_or_region = "Syria", 10) + ) + $mitre_attack_tactic = "Defense Evasion, Persistence, Privilege Escalation, Initial Access" + $mitre_attack_technique = "Valid Accounts" + $mitre_attack_technique_id = "T1078" + $event_count = count_distinct($success.metadata.id) + count_distinct($fail.metadata.id) + $principal_ip = array_distinct($success.principal.ip) + $principal_ip_country = array_distinct($success.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($success.principal.ip_geo_artifact.location.state) + $target_user_userid = array_distinct($success.target.user.userid) + $is_mfa_used = array_distinct($success.extensions.auth.auth_details) + $target_resource_name = array_distinct($success.target.resource.name) + $target_resource_product_object_id = array_distinct($success.target.resource.product_object_id) + + condition: + #fail > 3 and $success +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule aws_guardduty_black_hole_traffic_detected { + + meta: + author = "Google Cloud Security" + description = "Amazon GuardDuty detects an Amazon EC2 instance or a container attempting to communicate with a black hole IP address." + rule_id = "mr_8ac55f38-9c11-4f51-89cd-c40e9b6238b3" + rule_name = "AWS GuardDuty Black Hole Traffic Detected" + mitre_attack_tactic = "Command and Control" + mitre_attack_technique = "Application Layer Protocol" + mitre_attack_url = "https://attack.mitre.org/techniques/T1071/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "AWS GuardDuty" + platform = "AWS" + severity = "High" + priority = "High" + + events: + $guardduty.metadata.vendor_name = "AMAZON" + $guardduty.metadata.product_name = "AWS GuardDuty" + $guardduty.metadata.product_event_type = /BlackholeTraffic/ + //Filter out sample findings + $guardduty.security_result.about.labels["Sample"] != "true" + + outcome: + $risk_score = max(35) + $mitre_attack_tactic = "Command and Control" + $mitre_attack_technique = "Application Layer Protocol" + $mitre_attack_technique_id = "T1071" + $event_count = count_distinct($guardduty.metadata.id) + $principal_ip = array_distinct($guardduty.principal.ip) + $principal_ip_country = array_distinct($guardduty.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($guardduty.principal.ip_geo_artifact.location.state) + $principal_user_display_name = $guardduty.principal.user.user_display_name + $aws_region = $guardduty.target.location.name + $target_resource_name = $guardduty.target.resource.name + $target_resource_product_object_id = $guardduty.target.resource.product_object_id + $security_result_summary = array_distinct($guardduty.security_result.summary) + $security_result_description = array_distinct($guardduty.security_result.description) + $security_result_severity = array_distinct($guardduty.security_result.severity) + $security_result_severity_details = array_distinct($guardduty.security_result.severity_details) + $metadata_product_event_type = array_distinct($guardduty.metadata.product_event_type) + + condition: + $guardduty +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule aws_guardduty_brute_force_activity_detected { + + meta: + author = "Google Cloud Security" + description = "Amazon GuardDuty detects a brute force activity in an Amazon EC2 or Amazon RDS instance." + rule_id = "mr_33197748-cb9d-451f-8135-4b61cc5e4ca5" + rule_name = "AWS GuardDuty Bruteforce Activity Detected" + mitre_attack_tactic = "Credential Access" + mitre_attack_technique = "Brute Force" + mitre_attack_url = "https://attack.mitre.org/techniques/T1110/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "AWS GuardDuty" + platform = "AWS" + severity = "High" + priority = "High" + + events: + $guardduty.metadata.vendor_name = "AMAZON" + $guardduty.metadata.product_name = "AWS GuardDuty" + $guardduty.metadata.product_event_type = /BruteForce/ + //Filter out sample findings + $guardduty.security_result.about.labels["Sample"] != "true" + + outcome: + $risk_score = max(35) + $mitre_attack_tactic = "Credential Access" + $mitre_attack_technique = "Brute Force" + $mitre_attack_technique_id = "T1110" + $event_count = count_distinct($guardduty.metadata.id) + $principal_ip = array_distinct($guardduty.principal.ip) + $principal_ip_country = array_distinct($guardduty.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($guardduty.principal.ip_geo_artifact.location.state) + $principal_user_display_name = $guardduty.principal.user.user_display_name + $aws_region = $guardduty.target.location.name + $target_resource_name = $guardduty.target.resource.name + $target_resource_product_object_id = $guardduty.target.resource.product_object_id + $security_result_summary = array_distinct($guardduty.security_result.summary) + $security_result_description = array_distinct($guardduty.security_result.description) + $security_result_severity = array_distinct($guardduty.security_result.severity) + $security_result_severity_details = array_distinct($guardduty.security_result.severity_details) + $metadata_product_event_type = array_distinct($guardduty.metadata.product_event_type) + + condition: + $guardduty +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule aws_guardduty_command_and_control_activity_detected { + + meta: + author = "Google Cloud Security" + description = "Amazon GuardDuty detects Command and control activity in Amazon EC2, AWS Lambda or Amazon EKS Runtimes." + rule_id = "mr_dc0c33c7-35e3-44e2-b149-99212f3e54c6" + rule_name = "AWS GuardDuty Command And Control Activity Detected" + mitre_attack_tactic = "Command and Control" + mitre_attack_technique = "Application Layer Protocol" + mitre_attack_url = "https://attack.mitre.org/techniques/T1071/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "AWS GuardDuty" + platform = "AWS" + severity = "High" + priority = "High" + + events: + $guardduty.metadata.vendor_name = "AMAZON" + $guardduty.metadata.product_name = "AWS GuardDuty" + $guardduty.metadata.product_event_type = /C&CActivity/ + //Filter out sample findings + $guardduty.security_result.about.labels["Sample"] != "true" + + outcome: + $risk_score = max(35) + $mitre_attack_tactic = "Command and Control" + $mitre_attack_technique = "Application Layer Protocol" + $mitre_attack_technique_id = "T1071" + $event_count = count_distinct($guardduty.metadata.id) + $principal_ip = array_distinct($guardduty.principal.ip) + $principal_ip_country = array_distinct($guardduty.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($guardduty.principal.ip_geo_artifact.location.state) + $principal_user_display_name = $guardduty.principal.user.user_display_name + $aws_region = $guardduty.target.location.name + $target_resource_name = $guardduty.target.resource.name + $target_resource_product_object_id = $guardduty.target.resource.product_object_id + $security_result_summary = array_distinct($guardduty.security_result.summary) + $security_result_description = array_distinct($guardduty.security_result.description) + $security_result_severity = array_distinct($guardduty.security_result.severity) + $security_result_severity_details = array_distinct($guardduty.security_result.severity_details) + $metadata_product_event_type = array_distinct($guardduty.metadata.product_event_type) + + condition: + $guardduty +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule aws_guardduty_denial_of_service_activity_detected { + + meta: + author = "Google Cloud Security" + description = "Amazon GuardDuty detects a Denial of Service (DoS) activity in an Amazon EC2 instance." + rule_id = "mr_63e3f20f-95f5-4caa-b471-ec53d5de2d28" + rule_name = "AWS GuardDuty Denial Of Service Activity Detected" + mitre_attack_tactic = "Impact" + mitre_attack_technique = "Network Denial of Service" + mitre_attack_url = "https://attack.mitre.org/techniques/T1498/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "AWS GuardDuty" + platform = "AWS" + severity = "High" + priority = "High" + + events: + $guardduty.metadata.vendor_name = "AMAZON" + $guardduty.metadata.product_name = "AWS GuardDuty" + $guardduty.metadata.product_event_type = /DenialOfService/ + //Filter out sample findings + $guardduty.security_result.about.labels["Sample"] != "true" + + outcome: + $risk_score = max(35) + $mitre_attack_tactic = "Command and Control" + $mitre_attack_technique = "Network Denial of Service" + $mitre_attack_technique_id = "T1498" + $event_count = count_distinct($guardduty.metadata.id) + $principal_ip = array_distinct($guardduty.principal.ip) + $principal_ip_country = array_distinct($guardduty.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($guardduty.principal.ip_geo_artifact.location.state) + $principal_user_display_name = $guardduty.principal.user.user_display_name + $aws_region = $guardduty.target.location.name + $target_resource_name = $guardduty.target.resource.name + $target_resource_product_object_id = $guardduty.target.resource.product_object_id + $security_result_summary = array_distinct($guardduty.security_result.summary) + $security_result_description = array_distinct($guardduty.security_result.description) + $security_result_severity = array_distinct($guardduty.security_result.severity) + $security_result_severity_details = array_distinct($guardduty.security_result.severity_details) + $metadata_product_event_type = array_distinct($guardduty.metadata.product_event_type) + + condition: + $guardduty +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule aws_guardduty_tor_network_activity_detected { + + meta: + author = "Google Cloud Security" + description = "Amazon GuardDuty detects Tor Network activity in an AWS account." + rule_id = "mr_abbc8f85-d4a3-4579-b444-19e6944f49d1" + rule_name = "AWS GuardDuty Tor Network Activity Detected" + mitre_attack_tactic = "Command and Control" + mitre_attack_technique = "Proxy: Multi-hop Proxy" + mitre_attack_url = "https://attack.mitre.org/techniques/T1090/003/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "AWS GuardDuty" + platform = "AWS" + severity = "High" + priority = "High" + + events: + $guardduty.metadata.vendor_name = "AMAZON" + $guardduty.metadata.product_name = "AWS GuardDuty" + $guardduty.metadata.product_event_type = /TorIPCaller|TorRelay|TorClient/ + //Filter out sample findings + $guardduty.security_result.about.labels["Sample"] != "true" + + outcome: + $risk_score = max(35) + $mitre_attack_tactic = "Command and Control" + $mitre_attack_technique = "Proxy: Multi-hop Proxy" + $mitre_attack_technique_id = "T1090.003" + $event_count = count_distinct($guardduty.metadata.id) + $principal_ip = array_distinct($guardduty.principal.ip) + $principal_ip_country = array_distinct($guardduty.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($guardduty.principal.ip_geo_artifact.location.state) + $principal_user_display_name = $guardduty.principal.user.user_display_name + $aws_region = $guardduty.target.location.name + $target_resource_name = $guardduty.target.resource.name + $target_resource_product_object_id = $guardduty.target.resource.product_object_id + $security_result_summary = array_distinct($guardduty.security_result.summary) + $security_result_description = array_distinct($guardduty.security_result.description) + $security_result_severity = array_distinct($guardduty.security_result.severity) + $security_result_severity_details = array_distinct($guardduty.security_result.severity_details) + $metadata_product_event_type = array_distinct($guardduty.metadata.product_event_type) + + condition: + $guardduty +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule aws_guardduty_malicious_or_suspicious_file_executed { + + meta: + author = "Google Cloud Security" + description = "Amazon GuardDuty detects a malicious or suspicious file on an Amazon EC2 instance or a container workload." + rule_id = "mr_a5d8f51c-d0de-4169-99e2-d3eaa02b266c" + rule_name = "AWS GuardDuty Malicious Or Suspicious File Executed" + mitre_attack_tactic = "Execution" + mitre_attack_technique = "User Execution: Malicious File" + mitre_attack_url = "https://attack.mitre.org/techniques/T1204/002/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "AWS GuardDuty" + platform = "AWS" + severity = "High" + priority = "High" + + events: + $guardduty.metadata.vendor_name = "AMAZON" + $guardduty.metadata.product_name = "AWS GuardDuty" + $guardduty.metadata.product_event_type = /MaliciousFile|SuspiciousFile/ + //Filter out sample findings + $guardduty.security_result.about.labels["Sample"] != "true" + + outcome: + $risk_score = max(35) + $mitre_attack_tactic = "Execution" + $mitre_attack_technique = "User Execution: Malicious File" + $mitre_attack_technique_id = "T1204.002" + $event_count = count_distinct($guardduty.metadata.id) + $principal_ip = array_distinct($guardduty.principal.ip) + $principal_ip_country = array_distinct($guardduty.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($guardduty.principal.ip_geo_artifact.location.state) + $principal_user_display_name = $guardduty.principal.user.user_display_name + $aws_region = $guardduty.target.location.name + $target_resource_name = $guardduty.target.resource.name + $target_resource_product_object_id = $guardduty.target.resource.product_object_id + $security_result_summary = array_distinct($guardduty.security_result.summary) + $security_result_description = array_distinct($guardduty.security_result.description) + $security_result_severity = array_distinct($guardduty.security_result.severity) + $security_result_severity_details = array_distinct($guardduty.security_result.severity_details) + $metadata_product_event_type = array_distinct($guardduty.metadata.product_event_type) + + condition: + $guardduty +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule aws_guardduty_penetration_testing_activity_detected { + + meta: + author = "Google Cloud Security" + description = "Amazon GuardDuty detects penetration testing activity from known offensive security distros such as KaliLinux, ParrotLinux or PentooLinux." + rule_id = "mr_7dac6e7c-9d35-4093-9b85-4b0175e8bee7" + rule_name = "AWS GuardDuty Penetration Testing Activity Detected" + mitre_attack_tactic = "Resource Development" + mitre_attack_technique = "Obtain Capabilities" + mitre_attack_url = "https://attack.mitre.org/techniques/T1588/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "AWS GuardDuty" + platform = "AWS" + severity = "High" + priority = "High" + + events: + $guardduty.metadata.vendor_name = "AMAZON" + $guardduty.metadata.product_name = "AWS GuardDuty" + $guardduty.metadata.product_event_type = /PenTest/ + //Filter out sample findings + $guardduty.security_result.about.labels["Sample"] != "true" + + outcome: + $risk_score = max(35) + $mitre_attack_tactic = "Resource Development" + $mitre_attack_technique = "Obtain Capabilities" + $mitre_attack_technique_id = "T1588" + $event_count = count_distinct($guardduty.metadata.id) + $principal_ip = array_distinct($guardduty.principal.ip) + $principal_ip_country = array_distinct($guardduty.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($guardduty.principal.ip_geo_artifact.location.state) + $principal_user_display_name = $guardduty.principal.user.user_display_name + $aws_region = $guardduty.target.location.name + $target_resource_name = $guardduty.target.resource.name + $target_resource_product_object_id = $guardduty.target.resource.product_object_id + $security_result_summary = array_distinct($guardduty.security_result.summary) + $security_result_description = array_distinct($guardduty.security_result.description) + $security_result_severity = array_distinct($guardduty.security_result.severity) + $security_result_severity_details = array_distinct($guardduty.security_result.severity_details) + $metadata_product_event_type = array_distinct($guardduty.metadata.product_event_type) + + condition: + $guardduty +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule aws_guardduty_crypto_currency_activity_detected { + + meta: + author = "Google Cloud Security" + description = "Amazon GuardDuty detects CryptoCurrency activity in Amazon EC2, AWS Lambda or Amazon EKS Runtimes." + rule_id = "mr_be21d1ff-4d2b-4d0b-a928-0fa5d534cba5" + rule_name = "AWS GuardDuty Cryptocurrency Activity Detected" + mitre_attack_tactic = "Impact" + mitre_attack_technique = "Resource Hijacking" + mitre_attack_url = "https://attack.mitre.org/techniques/T1496/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "AWS GuardDuty" + platform = "AWS" + severity = "High" + priority = "High" + + events: + $guardduty.metadata.vendor_name = "AMAZON" + $guardduty.metadata.product_name = "AWS GuardDuty" + $guardduty.metadata.product_event_type = /CryptoCurrency|CryptoMinerExecuted|BitcoinDomainRequest/ + //Filter out sample findings + $guardduty.security_result.about.labels["Sample"] != "true" + + outcome: + $risk_score = max(35) + $mitre_attack_tactic = "Impact" + $mitre_attack_technique = "Resource Hijacking" + $mitre_attack_technique_id = "T1496" + $event_count = count_distinct($guardduty.metadata.id) + $principal_ip = array_distinct($guardduty.principal.ip) + $principal_ip_country = array_distinct($guardduty.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($guardduty.principal.ip_geo_artifact.location.state) + $principal_user_display_name = $guardduty.principal.user.user_display_name + $aws_region = $guardduty.target.location.name + $target_resource_name = $guardduty.target.resource.name + $target_resource_product_object_id = $guardduty.target.resource.product_object_id + $security_result_summary = array_distinct($guardduty.security_result.summary) + $security_result_description = array_distinct($guardduty.security_result.description) + $security_result_severity = array_distinct($guardduty.security_result.severity) + $security_result_severity_details = array_distinct($guardduty.security_result.severity_details) + $metadata_product_event_type = array_distinct($guardduty.metadata.product_event_type) + + condition: + $guardduty +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule aws_guardduty_dga_domain_activity_detected { + + meta: + author = "Google Cloud Security" + description = "Amazon GuardDuty detects an Amazon EC2 instance or a container querying algorithmically generated domains (DGA)." + rule_id = "mr_52851fd2-be35-4eda-82b3-541edc5c2196" + rule_name = "AWS GuardDuty DGA Domain Activity Detected" + mitre_attack_tactic = "Command and Control" + mitre_attack_technique = "Dynamic Resolution: Domain Generation Algorithms" + mitre_attack_url = "https://attack.mitre.org/techniques/T1568/002/" + mitre_attack_version = "v13.1" + type = "Alert" + data_source = "AWS GuardDuty" + platform = "AWS" + severity = "High" + priority = "High" + + events: + $guardduty.metadata.vendor_name = "AMAZON" + $guardduty.metadata.product_name = "AWS GuardDuty" + $guardduty.metadata.product_event_type = /DGADomainRequest/ + //Filter out sample findings + $guardduty.security_result.about.labels["Sample"] != "true" + + outcome: + $risk_score = max(35) + $mitre_attack_tactic = "Command and Control" + $mitre_attack_technique = "Dynamic Resolution: Domain Generation Algorithms" + $mitre_attack_technique_id = "T1568.002" + $event_count = count_distinct($guardduty.metadata.id) + $principal_ip = array_distinct($guardduty.principal.ip) + $principal_ip_country = array_distinct($guardduty.principal.ip_geo_artifact.location.country_or_region) + $principal_ip_state = array_distinct($guardduty.principal.ip_geo_artifact.location.state) + $principal_user_display_name = $guardduty.principal.user.user_display_name + $aws_region = $guardduty.target.location.name + $target_resource_name = $guardduty.target.resource.name + $target_resource_product_object_id = $guardduty.target.resource.product_object_id + $security_result_summary = array_distinct($guardduty.security_result.summary) + $security_result_description = array_distinct($guardduty.security_result.description) + $security_result_severity = array_distinct($guardduty.security_result.severity) + $security_result_severity_details = array_distinct($guardduty.security_result.severity_details) + $metadata_product_event_type = array_distinct($guardduty.metadata.product_event_type) + + condition: + $guardduty +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule logins_from_terminated_employees { + + meta: + author = "Google Cloud Security" + description = "Allowed Logins from Terminated Employees" + rule_id = "mr_69178541-285b-45cb-b723-e2b5d88f22d3" + rule_name = "Logins From Terminated Employees" + assumptions = "This rule requires a context data source such as AzureAD AD Context or Workday to demonstrate the correlation of context logs with event logs" + type = "alert" + tags = "user enrichment" + data_source = "microsoft windows events" + mitre_attack_tactic = "Defense Evasion, Persistence, Privilege Escalation, Initial Access" + mitre_attack_technique = "Valid Accounts" + mitre_attack_url = "https://attack.mitre.org/techniques/T1078/" + mitre_attack_version = "v13.1" + severity = "Medium" + priority = "Medium" + + events: + $login.metadata.event_type = "USER_LOGIN" + $login.security_result.action = "ALLOW" + $login.target.user.userid = $user + $login.target.user.termination_date.seconds > 0 + $login.target.user.termination_date.seconds < $login.metadata.event_timestamp.seconds + + match: + $user over 1d + + outcome: + $risk_score = max(65) + $mitre_attack_tactic = array_distinct("Defense Evasion, Persistence, Privilege Escalation, Initial Access") + $mitre_attack_technique = array_distinct("Valid Accounts") + $mitre_attack_technique_id = array_distinct("T1078") + $event_count = count_distinct($login.metadata.id) + $employee_last_login = max($login.target.user.termination_date.seconds) + $total_distinct_ips = count_distinct($login.principal.ip) + // added to populate alert graph with additional context + $principal_hostname = array_distinct($login.principal.hostname) + $target_hostname = array_distinct($login.target.hostname) + $principal_user_userid = array_distinct($login.principal.user.userid) + // Commented out target.user.userid because it is already represented in graph as match variable. If match changes, can uncomment to add to results + //$target_user_userid = array_distinct($login.target.user.userid) + $principal_resource_name = array_distinct($login.principal.resource.name) + $target_resource_name = array_distinct($login.target.resource.name) + $target_url = array_distinct($login.target.url) + + condition: + $login +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule geoip_user_login_from_multiple_states_or_countries { + + meta: + author = "Google Cloud Security" + description = "Detect multiple user logins from multiple states or countries using Chronicle GeoIP enrichment." + rule_id = "mr_3fa832e4-1ac0-42cd-9f0a-357d6b8fb12f" + rule_name = "GeoIP User Login From Multiple States Or Countries" + type = "alert" + data_source = "microsoft ad, azure ad, okta, aws cloudtrail, google scc" + tags = "geoip enrichment" + severity = "Low" + priority = "Low" + + events: + $login.metadata.event_type = "USER_LOGIN" + $login.security_result.action = "ALLOW" + $login.principal.ip_geo_artifact.location.country_or_region != "" + + $login.principal.ip_geo_artifact.location.country_or_region = $country + $login.principal.ip_geo_artifact.location.state = $state + $login.metadata.product_name = $product + $login.target.user.userid = $user + + match: + $user, $product over 1h + + outcome: + $risk_score = max(35) + $event_count = count_distinct($login.metadata.id) + $state_login_threshold = max(2) + $dc_state = count_distinct($login.principal.ip_geo_artifact.location.state) + $array_state = array_distinct($login.principal.ip_geo_artifact.location.state) + $dc_country_or_region = count_distinct($login.principal.ip_geo_artifact.location.country_or_region) + $array_country_or_region = array_distinct($login.principal.ip_geo_artifact.location.country_or_region) + $array_asn = array_distinct($login.principal.ip_geo_artifact.network.asn) + $array_carrier_name = array_distinct($login.principal.ip_geo_artifact.network.carrier_name) + //added to populate alert graph with additional context + $principal_hostname = array_distinct($login.principal.hostname) + $principal_ip = array_distinct($login.principal.ip) + $target_hostname = array_distinct($login.target.hostname) + $target_ip = array_distinct($login.target.ip) + $principal_user_userid = array_distinct($login.principal.user.userid) + $target_user_userid = array_distinct($login.target.user.userid) + $principal_resource_name = array_distinct($login.principal.resource.name) + $target_resource_name = array_distinct($login.target.resource.name) + $target_url = array_distinct($login.target.url) + + condition: + #country >= 1 and #state >= 2 +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule vt_relationships_file_contacts_ip { + + meta: + author = "Google Cloud Security" + description = "Alert on known Hash contacting known IP with VT Relationships" + rule_id = "mr_d6011593-c864-40b2-b300-4275ed163f5d" + rule_name = "VT Relationships File Contacts IP" + type = "alert" + tags = "vt" + data_source = "microsoft defender atp" + severity = "High" + priority = "High" + + events: + $network.metadata.event_type = "NETWORK_CONNECTION" + $network.principal.process.file.sha256 = $file_hash + $network.target.ip = $ip + $network.principal.hostname = $hostname + + // Uses VirusTotal integration via entity graph, this section maps to principal process file hash + $vt.graph.metadata.entity_type = "FILE" + $vt.graph.metadata.source_type = "GLOBAL_CONTEXT" + $vt.graph.metadata.vendor_name = "VirusTotal" + $vt.graph.metadata.product_name = "VirusTotal Relationships" + $vt.graph.entity.file.sha256 = $file_hash + + // Uses VirusTotal integration via entity graph, this section maps the hash to the ip address it contacts + $vt.graph.relations.entity_type = "IP_ADDRESS" + $vt.graph.relations.relationship = "CONTACTS" + $vt.graph.relations.entity.ip = $ip + + match: + $hostname over 5m + + outcome: + $risk_score = max(85) + $event_count = count_distinct($network.metadata.id) + // added to populate alert graph with additional context + $principal_ip = array_distinct($network.principal.ip) + $target_ip = array_distinct($network.target.ip) + $principal_process_pid = array_distinct($network.principal.process.pid) + $principal_process_command_line = array_distinct($network.principal.process.command_line) + $principal_process_file_sha256 = array_distinct($network.principal.process.file.sha256) + $principal_process_file_full_path = array_distinct($network.principal.process.file.full_path) + $principal_process_product_specific_process_id = array_distinct($network.principal.process.product_specific_process_id) + $principal_process_parent_process_product_specific_process_id = array_distinct($network.principal.process.parent_process.product_specific_process_id) + $target_process_pid = array_distinct($network.target.process.pid) + $target_process_command_line = array_distinct($network.target.process.command_line) + $target_process_file_sha256 = array_distinct($network.target.process.file.sha256) + $target_process_file_full_path = array_distinct($network.target.process.file.full_path) + $target_process_product_specific_process_id = array_distinct($network.target.process.product_specific_process_id) + $target_process_parent_process_product_specific_process_id = array_distinct($network.target.process.parent_process.product_specific_process_id) + $principal_user_userid = array_distinct($network.principal.user.userid) + $target_user_userid = array_distinct($network.target.user.userid) + + condition: + $network and $vt +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule ioc_domain_C2 { + + meta: + author = "Google Cloud Security" + description = "Detect DNS events that indicate communication to a C2 domain in MISP" + rule_id = "mr_cb22c45e-b29d-487f-9cf5-1310bfed6d6c" + rule_name = "IOC Domain C2" + type = "alert" + tags = "threat indicators" + assumption = "Assumes MISP data has been ingested into entity graph; this rule can be modified to utilize other TI indicators" + data_source = "microsoft sysmon" + severity = "High" + priority = "High" + + events: + $dns.metadata.event_type = "NETWORK_DNS" + $dns.network.dns.questions.name = $dns_query + + // Correlates with MISP data; can be modified based on your MISP parser or other TI + $ioc.graph.metadata.product_name = "MISP" + $ioc.graph.metadata.entity_type = "DOMAIN_NAME" + $ioc.graph.metadata.source_type = "ENTITY_CONTEXT" + //Summary is used to focus on a specific subset of MISP indicators, can modify as needed + $ioc.graph.metadata.threat.summary = "C2 domains" + $ioc.graph.entity.hostname = $dns_query + + match: + $dns_query over 5m + + outcome: + $risk_score = max(85) + $event_count = count_distinct($dns.metadata.id) + $network_dns_questions_name = array_distinct($dns.network.dns.questions.name) + $network_dns_answers_data = array_distinct($dns.network.dns.answers.data) + // added to populate alert graph with additional context + $principal_ip = array_distinct($dns.principal.ip) + $target_ip = array_distinct($dns.target.ip) + $principal_process_pid = array_distinct($dns.principal.process.pid) + $principal_process_file_full_path = array_distinct($dns.principal.process.file.full_path) + $principal_process_product_specific_process_id = array_distinct($dns.principal.process.product_specific_process_id) + $principal_user_userid = array_distinct($dns.principal.user.userid) + $principal_process_command_line = array_distinct($dns.principal.process.command_line) + $principal_process_file_sha256 = array_distinct($dns.principal.process.file.sha256) + $principal_process_parent_process_product_specific_process_id = array_distinct($dns.principal.process.parent_process.product_specific_process_id) + + + condition: + $dns and $ioc +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule vt_relationships_file_contacts_tor_ip { + + meta: + author = "Google Cloud Security" + description = "Alert on known Hash contacting Tor IP with VT Relationships." + rule_id = "mr_a6f8b114-8fdb-4f39-8820-8961dcbb1079" + rule_name = "VT Relationships File Contacts Tor IP" + mitre_attack_tactic = "Command and Control" + mitre_attack_technique = "Proxy: Multi-hop Proxy" + mitre_attack_url = "https://attack.mitre.org/techniques/T1090/003/" + mitre_attack_version = "v13.1" + type = "alert" + tags = "vt, tor" + data_source = "microsoft defender atp" + severity = "Critical" + priority = "High" + + events: + $network.metadata.event_type = "NETWORK_CONNECTION" + $network.principal.process.file.sha256 = $file_hash + $network.target.ip = $ip + $network.principal.hostname = $hostname + + // Uses VirusTotal integration via entity graph, this section maps to principal process file hash + $vt.graph.metadata.entity_type = "FILE" + $vt.graph.metadata.source_type = "GLOBAL_CONTEXT" + $vt.graph.metadata.vendor_name = "VirusTotal" + $vt.graph.metadata.product_name = "VirusTotal Relationships" + $vt.graph.entity.file.sha256 = $file_hash + + // Uses VirusTotal integration via entity graph, this section maps the hash to the ip address it contacts + $vt.graph.relations.entity_type = "IP_ADDRESS" + $vt.graph.relations.relationship = "CONTACTS" + $vt.graph.relations.entity.ip = $ip + + // Tor IP listing provided by GCTI Feed + $gcti.graph.entity.artifact.ip = $ip + $gcti.graph.metadata.entity_type = "IP_ADDRESS" + $gcti.graph.metadata.source_type = "GLOBAL_CONTEXT" + $gcti.graph.metadata.threat.threat_feed_name = "Tor Exit Nodes" + $gcti.graph.metadata.vendor_name = "Google Cloud Threat Intelligence" + $gcti.graph.metadata.product_name = "GCTI Feed" + + match: + $hostname over 5m + + outcome: + $risk_score = max( + if($gcti.graph.metadata.threat.confidence = "HIGH_CONFIDENCE", 70) + + // Unauthorized target geographies + if($network.target.ip_geo_artifact.location.country_or_region = "Cuba", 20) + + if($network.target.ip_geo_artifact.location.country_or_region = "Iran", 20) + + if($network.target.ip_geo_artifact.location.country_or_region = "North Korea", 20) + + if($network.target.ip_geo_artifact.location.country_or_region = "Russia", 20) + + if($network.target.ip_geo_artifact.location.country_or_region = "Syria", 20) + ) + $mitre_attack_tactic = array_distinct("Command and Control") + $mitre_attack_technique = array_distinct("Proxy: Multi-hop Proxy") + $mitre_attack_technique_id = array_distinct("T1090.003") + $event_count = count_distinct($network.metadata.id) + $count_file_hash = count_distinct($file_hash) + $count_tor_ips = count_distinct($ip) + $tor_geoip_country = array_distinct($network.target.ip_geo_artifact.location.country_or_region) + $tor_geoip_state = array_distinct($network.target.ip_geo_artifact.location.state) + // added to populate alert graph with additional context + $principal_ip = array_distinct($network.principal.ip) + $target_ip = array_distinct($network.target.ip) + $principal_process_pid = array_distinct($network.principal.process.pid) + $principal_process_command_line = array_distinct($network.principal.process.command_line) + $principal_process_file_sha256 = array_distinct($network.principal.process.file.sha256) + $principal_process_file_full_path = array_distinct($network.principal.process.file.full_path) + $principal_process_product_specific_process_id = array_distinct($network.principal.process.product_specific_process_id) + $principal_process_parent_process_product_specific_process_id = array_distinct($network.principal.process.parent_process.product_specific_process_id) + //$target_process_pid = array_distinct($network.target.process.pid) + //$target_process_command_line = array_distinct($network.target.process.command_line) + //$target_process_file_sha256 = array_distinct($network.target.process.file.sha256) + $target_process_file_full_path = array_distinct($network.target.process.file.full_path) + //$target_process_product_specific_process_id = array_distinct($network.target.process.product_specific_process_id) + //$target_process_parent_process_product_specific_process_id = array_distinct($network.target.process.parent_process.product_specific_process_id) + $principal_user_userid = array_distinct($network.principal.user.userid) + //$target_user_userid = array_distinct($network.target.user.userid) + $target_url = array_distinct($network.target.url) + + condition: + $network and $vt and $gcti +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule whois_expired_domain_accessed { + + meta: + author = "Google Cloud Security" + description = "Example usage of WHOIS data, detecting an executable file download from a domain that's recently expired" + rule_id = "mr_7b487c4f-cbf9-4b11-8b25-632ada3f90a3" + rule_name = "WHOIS Expired Domain Accessed" + type = "alert" + tags = "whois" + data_source = "zscalar" + severity = "Low" + priority = "Low" + + events: + $access.metadata.event_type = "NETWORK_HTTP" + $access.target.hostname = $hostname + + // join access event to entity graph to use WHOIS data + $whois.graph.entity.domain.name = $hostname + + // Whois domains provided by GCTI Feed + $whois.graph.metadata.entity_type = "DOMAIN_NAME" + $whois.graph.metadata.vendor_name = "WHOIS" + $whois.graph.metadata.product_name = "WHOISXMLAPI Simple Whois" + $whois.graph.metadata.source_type = "GLOBAL_CONTEXT" + // Filter out domains without expiration time + $whois.graph.entity.domain.expiration_time.seconds > 0 + // Domain expired before the event + $whois.graph.entity.domain.expiration_time.seconds < $access.metadata.event_timestamp.seconds + + match: + $hostname over 1h + + outcome: + $risk_score = max(20) + $event_count = count_distinct($access.metadata.id) + //added to populate alert graph with additional context + $principal_hostname = array_distinct($access.principal.hostname) + // Commented out principal.hostname because it is already represented in graph as match variable. If match changes, can uncomment to add to results + //$target_hostname = array_distinct($access.target.hostname) + $principal_process_pid = array_distinct($access.principal.process.pid) + $principal_process_command_line = array_distinct($access.principal.process.command_line) + $principal_process_file_sha256 = array_distinct($access.principal.process.file.sha256) + $principal_process_file_full_path = array_distinct($access.principal.process.file.full_path) + $principal_process_product_specific_process_id = array_distinct($access.principal.process.product_specific_process_id) + $principal_process_parent_process_product_specific_process_id = array_distinct($access.principal.process.parent_process.product_specific_process_id) + $target_process_pid = array_distinct($access.target.process.pid) + $target_process_command_line = array_distinct($access.target.process.command_line) + $target_process_file_sha256 = array_distinct($access.target.process.file.sha256) + $target_process_file_full_path = array_distinct($access.target.process.file.full_path) + $target_process_product_specific_process_id = array_distinct($access.target.process.product_specific_process_id) + $target_process_parent_process_product_specific_process_id = array_distinct($access.target.process.parent_process.product_specific_process_id) + $principal_user_userid = array_distinct($access.principal.user.userid) + $target_user_userid = array_distinct($access.target.user.userid) + $target_url = array_distinct($access.target.url) + + condition: + $access and $whois +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule ioc_ip_target { + + meta: + author = "Google Cloud Security" + description = "Detect network events that indicate communication to a watchlisted IP address" + rule_id = "mr_cb71b798-5931-47a9-8572-8166db41fc5c" + rule_name = "IOC IP Target" + type = "alert" + tags = "threat indicators" + assumption = "Assumes MISP data has been ingested into entity graph; this rule can be modified to utilize other TI indicators" + data_source = "microsoft windows events" + severity = "Medium" + priority = "Medium" + + events: + $network.metadata.event_type = "NETWORK_CONNECTION" + $network.target.ip = $ip + //Target IP is not part of RFC1918 space, can modify as needed + not net.ip_in_range_cidr($network.target.ip, "10.0.0.0/24") + not net.ip_in_range_cidr($network.target.ip, "172.16.0.0/12") + not net.ip_in_range_cidr($network.target.ip, "192.168.0.0/16") + + // Correlates with MISP data; can be modified based on your MISP parser or other TI + $ioc.graph.metadata.product_name = "MISP" + $ioc.graph.metadata.entity_type = "IP_ADDRESS" + $ioc.graph.metadata.source_type = "ENTITY_CONTEXT" + $ioc.graph.entity.ip = $ip + + match: + $ip over 5m + + outcome: + $risk_score = max(65) + $event_count = count_distinct($network.metadata.id) + // added to populate alert graph with additional context + $principal_ip = array_distinct($network.principal.ip) + // Commented out target.ip because it is already represented in graph as match variable. If match changes, can uncomment to add to results + //$target_ip = array_distinct($network.target.ip) + $principal_process_pid = array_distinct($network.principal.process.pid) + $principal_process_command_line = array_distinct($network.principal.process.command_line) + $principal_process_file_sha256 = array_distinct($network.principal.process.file.sha256) + $principal_process_file_full_path = array_distinct($network.principal.process.file.full_path) + $principal_process_product_specific_process_id = array_distinct($network.principal.process.product_specific_process_id) + $principal_process_parent_process_product_specific_process_id = array_distinct($network.principal.process.parent_process.product_specific_process_id) + $target_process_pid = array_distinct($network.target.process.pid) + $target_process_command_line = array_distinct($network.target.process.command_line) + $target_process_file_sha256 = array_distinct($network.target.process.file.sha256) + $target_process_file_full_path = array_distinct($network.target.process.file.full_path) + $target_process_product_specific_process_id = array_distinct($network.target.process.product_specific_process_id) + $target_process_parent_process_product_specific_process_id = array_distinct($network.target.process.parent_process.product_specific_process_id) + $principal_user_userid = array_distinct($network.principal.user.userid) + $target_user_userid = array_distinct($network.target.user.userid) + + condition: + $network and $ioc +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule network_http_low_prevalence_domain_access { + + meta: + author = "Google Cloud Security" + description = "Detects network web access to a low prevalence domain" + rule_id = "mr_c376478e-1c93-4d27-8bea-a56c3c0052f5" + rule_name = "Network HTTP Low Prevalence Domain Access" + type = "alert" + tags = "prevalence" + data_source = "zscalar" + severity = "Critical" + priority = "Critical" + + events: + $http.metadata.event_type = "NETWORK_HTTP" + $http.principal.ip = $ip + // filter out URLs with RFC 1918 IP addresses, i.e., internal assets + not re.regex($http.target.hostname, `(127(?:\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$)|(10(?:\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$)|(192\.168(?:\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){2}$)|(172\.(?:1[6-9]|2\d|3[0-1])(?:\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){2})`) + // only match valid FQDN, filter out background non-routable noise + re.regex($http.target.hostname, `(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9][a-z0-9-]{0,61}[a-z0-9]`) + $http.target.hostname = $domain_name + + $prevalence.graph.entity.domain.name = $domain_name + // derived from events ingested by Chronicle + $prevalence.graph.metadata.entity_type = "DOMAIN_NAME" + $prevalence.graph.metadata.source_type = "DERIVED_CONTEXT" + $prevalence.graph.entity.domain.prevalence.day_count = 10 + // tune prevalence as fits your results + $prevalence.graph.entity.domain.prevalence.rolling_max > 0 + $prevalence.graph.entity.domain.prevalence.rolling_max <= 3 + + match: + $ip over 1h + + outcome: + $risk_score = max( + // increment risk score based upon rolling_max prevalence + if ( $prevalence.graph.entity.domain.prevalence.rolling_max >= 10, 10) + + if ( $prevalence.graph.entity.domain.prevalence.rolling_max >= 2 and $prevalence.graph.entity.domain.prevalence.rolling_max <= 9 , 20) + + if ( $prevalence.graph.entity.domain.prevalence.rolling_max = 1, 30) + ) + $event_count = count_distinct($http.metadata.id) + $domain_list = array_distinct($domain_name) + $domain_count = count_distinct($domain_name) + // added to populate alert graph with additional context + $principal_hostname = array_distinct($http.principal.hostname) + $target_hostname = array_distinct($http.target.hostname) + $principal_user_userid = array_distinct($http.principal.user.userid) + $target_url = array_distinct($http.target.url) + + + condition: + $http and $prevalence +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule vt_relationships_file_downloaded_from_ip { + + meta: + author = "Google Cloud Security" + description = "Alert on downloading a known file hash from a known IP with VT Relationships." + rule_id = "mr_1a62ba21-6f3d-40c7-9278-b1e2d639a10b" + rule_name = "VT Relationships File Downloaded From IP" + type = "alert" + tags = "vt" + data_source = "zscalar, crowdstrike" + severity = "High" + priority = "High" + + events: + // NETWORK_HTTP + $network.metadata.event_type = "NETWORK_HTTP" + $network.principal.user.userid = $userid + $network.target.ip = $ip + + // FILE_CREATION + $file.metadata.event_type = "FILE_CREATION" + $file.target.user.userid = $userid + $file.target.file.sha256 = $file_hash + + // Network HTTP event must occur before the file creation event + $network.metadata.event_timestamp.seconds < $file.metadata.event_timestamp.seconds + + //Uses VirusTotal integration via entity graph, this section maps to target file hash + $vt.graph.metadata.entity_type = "FILE" + $vt.graph.metadata.source_type = "GLOBAL_CONTEXT" + $vt.graph.metadata.vendor_name = "VirusTotal" + $vt.graph.metadata.product_name = "VirusTotal Relationships" + $vt.graph.entity.file.sha256 = $file_hash + + //Uses VirusTotal integration via entity graph, this section maps the hash to the ip address it is downloaded from + $vt.graph.relations.entity_type = "IP_ADDRESS" + $vt.graph.relations.relationship = "DOWNLOADED_FROM" + $vt.graph.relations.entity.ip = $ip + + match: + $userid over 5m + + outcome: + $risk_score = max(85) + // added to populate alert graph with additional context + $principal_hostname = array_distinct($network.principal.hostname) + $target_hostname = array_distinct($network.target.hostname) + $principal_process_pid = array_distinct($file.principal.process.pid) + $principal_process_command_line = array_distinct($file.principal.process.command_line) + $principal_process_file_sha256 = array_distinct($file.principal.process.file.sha256) + $principal_process_file_full_path = array_distinct($file.principal.process.file.full_path) + $principal_process_product_specific_process_id = array_distinct($file.principal.process.product_specific_process_id) + $principal_process_parent_process_product_specific_process_id = array_distinct($file.principal.process.parent_process.product_specific_process_id) + $target_process_pid = array_distinct($file.target.process.pid) + $target_process_command_line = array_distinct($file.target.process.command_line) + $target_process_file_sha256 = array_distinct($file.target.process.file.sha256) + $target_process_file_full_path = array_distinct($file.target.process.file.full_path) + $target_process_product_specific_process_id = array_distinct($file.target.process.product_specific_process_id) + $target_process_parent_process_product_specific_process_id = array_distinct($file.target.process.parent_process.product_specific_process_id) + // Commented out principal.user.userid because it is already represented in graph as match variable. If match changes, can uncomment to add to results + //$principal_user_userid = array_distinct($file.principal.user.userid) + $target_user_userid = array_distinct($file.target.user.userid) + $target_url = array_distinct($network.target.url) + + condition: + $network and $file and $vt +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule domain_prevalence { + + meta: + author = "Google Cloud Security" + description = "Detects DNS events querying domains that have a low rolling max prevalence." + rule_id = "mr_cf5dd851-d7e9-42b8-baf9-f4527ab61bf3" + rule_name = "Domain Prevalence" + type = "alert" + tags = "prevalence" + data_source = "extrahop, tanium, microsoft sysmon, gcp dns, crowdstrike" + severity = "Low" + priority = "Low" + + events: + $dns.metadata.event_type = "NETWORK_DNS" + $dns.network.dns.questions.name = $domain + + // derived from events ingested by Chronicle + $prevalence.graph.metadata.entity_type = "DOMAIN_NAME" + $prevalence.graph.metadata.source_type = "DERIVED_CONTEXT" + $prevalence.graph.entity.hostname = $domain + $prevalence.graph.entity.domain.prevalence.day_count = 10 + $prevalence.graph.entity.domain.prevalence.rolling_max <= 3 + $prevalence.graph.entity.domain.prevalence.rolling_max > 0 + + match: + $domain over 5m + + outcome: + $risk_score = max(35) + $event_count = count_distinct($dns.metadata.id) + $network_dns_questions_name = array_distinct($dns.network.dns.questions.name) + $network_dns_answers_data = array_distinct($dns.network.dns.answers.data) + // added to populate alert graph with additional context + $principal_ip = array_distinct($dns.principal.ip) + $target_ip = array_distinct($dns.target.ip) + $principal_process_pid = array_distinct($dns.principal.process.pid) + $principal_process_file_full_path = array_distinct($dns.principal.process.file.full_path) + $principal_process_product_specific_process_id = array_distinct($dns.principal.process.product_specific_process_id) + $principal_process_command_line = array_distinct($dns.principal.process.command_line) + $principal_process_file_sha256 = array_distinct($dns.principal.process.file.sha256) + $principal_process_parent_process_product_specific_process_id = array_distinct($dns.principal.process.parent_process.product_specific_process_id) + $principal_user_userid = array_distinct($dns.principal.user.userid) + + + condition: + $dns and $prevalence +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule ioc_domain_internal_policy { + + meta: + author = "Google Cloud Security" + description = "Detect DNS events that communicate with gaming sites in MISP. These violate policy." + rule_id = "mr_853bfafe-3049-43b5-a077-6a5f4a24ea3c" + rule_name = "IOC Domain Internal Policy" + type = "alert" + tags = "threat indicators" + assumption = "Assumes MISP data has been ingested into entity graph; this rule can be modified to utilize other TI indicators" + data_source = "microsoft sysmon" + severity = "Low" + priority = "Low" + + events: + $dns.metadata.event_type = "NETWORK_DNS" + $dns.network.dns.questions.name = $dns_query + + // Correlates with MISP data; can be modified based on your MISP parser or other TI + $ioc.graph.metadata.product_name = "MISP" + $ioc.graph.metadata.entity_type = "DOMAIN_NAME" + $ioc.graph.metadata.source_type = "ENTITY_CONTEXT" + // Summary is used to focus on a specific subset of MISP indicators, can modify as needed + $ioc.graph.metadata.threat.summary = "Gaming Sites" + // Threat Feed Name is used to focus on a specific subset of MISP indicators, can modify as needed + $ioc.graph.metadata.threat.threat_feed_name = "Internal" + $ioc.graph.entity.hostname = $dns_query + // Regex used to extract subset of data from field description, optional + re.capture($ioc.graph.metadata.threat.description, "additional info: (.*)") = $info + + match: + $dns_query over 5m + + outcome: + $risk_score = max(35) + $event_count = count_distinct($dns.metadata.id) + // If not doing any additional extractions to $info placeholder variable, the following outcome variable can be removed + $threat_info = array_distinct($info) + $network_dns_questions_name = array_distinct($dns.network.dns.questions.name) + $network_dns_answers_data = array_distinct($dns.network.dns.answers.data) + // added to populate alert graph with additional context + $principal_ip = array_distinct($dns.principal.ip) + $target_ip = array_distinct($dns.target.ip) + $principal_process_pid = array_distinct($dns.principal.process.pid) + $principal_process_file_full_path = array_distinct($dns.principal.process.file.full_path) + $principal_process_product_specific_process_id = array_distinct($dns.principal.process.product_specific_process_id) + $principal_user_userid = array_distinct($dns.principal.user.userid) + $principal_process_command_line = array_distinct($dns.principal.process.command_line) + $principal_process_file_sha256 = array_distinct($dns.principal.process.file.sha256) + $principal_process_parent_process_product_specific_process_id = array_distinct($dns.principal.process.parent_process.product_specific_process_id) + + condition: + $dns and $ioc +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule gcti_remote_access_tools { + + meta: + author = "Google Cloud Security" + description = "Alert process and file create events that are associated with hashes from the GCTI Remote Access Tool list" + rule_id = "mr_d838d64d-4a6f-4999-a895-0b5771d02aa6" + rule_name = "GCTI Remote Access Tools" + mitre_attack_tactic = "Command and Control" + mitre_attack_technique = "Remote Access Software" + mitre_attack_url = "https://attack.mitre.org/techniques/T1219/" + mitre_attack_version = "v13.1" + type = "alert" + tags = "rat" + data_source = "crowdstrike, microsoft sysmon, microsoft defender atp" + severity = "High" + priority = "High" + + events: + // find a process launch event + ($process.metadata.event_type = "PROCESS_LAUNCH" or $process.metadata.event_type = "PROCESS_MODULE_LOAD" or $process.metadata.event_type = "PROCESS_UNCATEGORIZED" or $process.metadata.event_type = "FILE_CREATION") + $process.target.process.file.sha256 != "" + $process.target.process.file.sha256 = $rat_hash + $process.principal.hostname = $hostname + + // join graph and event hashes + $gcti.graph.entity.file.sha256 = $rat_hash + + // look for files identified as likely remote access tools + $gcti.graph.metadata.entity_type = "FILE" + $gcti.graph.metadata.vendor_name = "Google Cloud Threat Intelligence" + $gcti.graph.metadata.product_name = "GCTI Feed" + $gcti.graph.metadata.source_type = "GLOBAL_CONTEXT" + $gcti.graph.metadata.threat.threat_feed_name = "Remote Access Tools" + + match: + $hostname over 5m + + outcome: + $risk_score = max(65) + $mitre_attack_tactic = "Command and Control" + $mitre_attack_technique = "Remote Access Software" + $mitre_attack_technique_id = "T1219" + $event_count = count_distinct($process.metadata.id) + // added to populate alert graph with additional context + // Commented out principal.hostname because it is already represented in graph as match variable. If match changes, can uncomment to add to results + //$principal_hostname = array_distinct($process.principal.hostname) + $principal_process_pid = array_distinct($process.principal.process.pid) + $principal_process_command_line = array_distinct($process.principal.process.command_line) + $principal_process_file_sha256 = array_distinct($process.principal.process.file.sha256) + $principal_process_file_full_path = array_distinct($process.principal.process.file.full_path) + $principal_process_product_specific_process_id = array_distinct($process.principal.process.product_specific_process_id) + $principal_process_parent_process_product_specific_process_id = array_distinct($process.principal.process.parent_process.product_specific_process_id) + $target_process_pid = array_distinct($process.target.process.pid) + $target_process_command_line = array_distinct($process.target.process.command_line) + $target_process_file_sha256 = array_distinct($process.target.process.file.sha256) + $target_process_file_full_path = array_distinct($process.target.process.file.full_path) + $target_process_product_specific_process_id = array_distinct($process.target.process.product_specific_process_id) + $target_process_parent_process_product_specific_process_id = array_distinct($process.target.process.parent_process.product_specific_process_id) + $target_file_full_path = array_distinct($process.target.file.full_path) + $principal_user_userid = array_distinct($process.principal.user.userid) + $target_resource_name = array_distinct($process.target.resource.name) + + condition: + $process and $gcti +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule gcti_benign_binaries_contacts_tor_exit_node { + + meta: + author = "Google Cloud Security" + description = "Alert on Benign Binary contacting a TOR IP" + rule_id = "mr_8bb13cf7-d66b-41f2-9bbc-0a1884a77f70" + rule_name = "GCTI Benign Binaries Contacts Tor Exit Node" + mitre_attack_tactic = "Command and Control" + mitre_attack_technique = "Proxy: Multi-hop Proxy" + mitre_attack_url = "https://attack.mitre.org/techniques/T1090/003/" + mitre_attack_version = "v13.1" + type = "alert" + tags = "tor, benign binaries" + data_source = "crowdstrike" + severity = "High" + priority = "High" + + events: + $network.metadata.event_type = "NETWORK_CONNECTION" + $network.principal.process.file.sha256 = $benign_hash + $network.target.ip = $ip + + // Benign Files provided by GCTI Feed + $gcti_feed.graph.entity.file.sha256 = $benign_hash + $gcti_feed.graph.metadata.vendor_name = "Google Cloud Threat Intelligence" + $gcti_feed.graph.metadata.product_name = "GCTI Feed" + $gcti_feed.graph.metadata.entity_type = "FILE" + $gcti_feed.graph.metadata.threat.threat_feed_name = "Benign Binaries" + $gcti_feed.graph.metadata.source_type = "GLOBAL_CONTEXT" + + // Tor IP listing provided by GCTI Feed + $tor.graph.entity.artifact.ip = $ip + $tor.graph.metadata.entity_type = "IP_ADDRESS" + $tor.graph.metadata.threat.threat_feed_name = "Tor Exit Nodes" + $tor.graph.metadata.vendor_name = "Google Cloud Threat Intelligence" + $tor.graph.metadata.product_name = "GCTI Feed" + $tor.graph.metadata.source_type = "GLOBAL_CONTEXT" + + match: + $ip over 5m + + outcome: + $risk_score = max( + if($tor.graph.metadata.threat.confidence = "HIGH_CONFIDENCE", 70) + + // Unauthorized target geographies + if($network.target.ip_geo_artifact.location.country_or_region = "Cuba", 20) + + if($network.target.ip_geo_artifact.location.country_or_region = "Iran", 20) + + if($network.target.ip_geo_artifact.location.country_or_region = "North Korea", 20) + + if($network.target.ip_geo_artifact.location.country_or_region = "Russia", 20) + + if($network.target.ip_geo_artifact.location.country_or_region = "Syria", 20) + ) + $mitre_attack_tactic = array_distinct("Command and Control") + $mitre_attack_technique = array_distinct("Proxy: Multi-hop Proxy") + $mitre_attack_technique_id = array_distinct("T1090.003") + $event_count = count_distinct($network.metadata.id) + $tor_ip_country = array_distinct($network.target.ip_geo_artifact.location.country_or_region) + // added to populate alert graph with additional context + $principal_ip = array_distinct($network.principal.ip) + // Commented out target.ip because it is already represented in graph as match variable. If match changes, can uncomment to add to results + //$target_ip = array_distinct($network.target.ip) + $principal_process_pid = array_distinct($network.principal.process.pid) + $principal_process_command_line = array_distinct($network.principal.process.command_line) + $principal_process_file_sha256 = array_distinct($network.principal.process.file.sha256) + $principal_process_file_full_path = array_distinct($network.principal.process.file.full_path) + $principal_process_product_specific_process_id = array_distinct($network.principal.process.product_specific_process_id) + $principal_process_parent_process_product_specific_process_id = array_distinct($network.principal.process.parent_process.product_specific_process_id) + $target_process_pid = array_distinct($network.target.process.pid) + $target_process_command_line = array_distinct($network.target.process.command_line) + $target_process_file_sha256 = array_distinct($network.target.process.file.sha256) + $target_process_file_full_path = array_distinct($network.target.process.file.full_path) + $target_process_product_specific_process_id = array_distinct($network.target.process.product_specific_process_id) + //$target_process_parent_process_product_specific_process_id = array_distinct($network.target.process.parent_process.product_specific_process_id) + $principal_user_userid = array_distinct($network.principal.user.userid) + $target_user_userid = array_distinct($network.target.user.userid) + + condition: + $network and $gcti_feed and $tor +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule safebrowsing_process_creation_hashes_seen_more_than_7_days { + + meta: + author = "Google Cloud Security" + description = "Identify process and file creation using safe browsing hashes where the first and last seen are more than 7 days apart" + rule_id = "mr_9970945d-45cf-44ed-887a-ff876d5a072b" + rule_name = "Safebrowsing Process Creation Hashes Seen More Than 7 Days" + type = "alert" + tags = "safe browsing, first last seen" + data_source = "microsoft sysmon, crowdstrike" + severity = "Medium" + priority = "Medium" + + events: + ($execution.metadata.event_type = "PROCESS_LAUNCH" or $execution.metadata.event_type = "FILE_CREATION") + $execution.principal.hostname = $hostname + $execution.target.process.file.sha256 = $sha256 + + // Safe Browsing file hashes provided by GCTI Feed + $safebrowse.graph.entity.file.sha256 = $sha256 + $safebrowse.graph.metadata.entity_type = "FILE" + $safebrowse.graph.metadata.product_name = "Google Safe Browsing" + $safebrowse.graph.metadata.source_type = "GLOBAL_CONTEXT" + + // derived from events ingested by Chronicle + $seen.graph.entity.file.sha256 = $sha256 + $seen.graph.metadata.entity_type = "FILE" + $seen.graph.metadata.source_type = "DERIVED_CONTEXT" + $seen.graph.entity.file.last_seen_time.seconds > 0 + 604800 <= $seen.graph.entity.file.last_seen_time.seconds - $seen.graph.entity.file.first_seen_time.seconds + + match: + $sha256 over 1h + + outcome: + $risk_score = max( if($seen.graph.entity.file.last_seen_time.seconds - $seen.graph.entity.file.first_seen_time.seconds > 604800 and + $seen.graph.entity.file.last_seen_time.seconds - $seen.graph.entity.file.first_seen_time.seconds < 1209600, 25, 0) + + if($seen.graph.entity.file.last_seen_time.seconds - $seen.graph.entity.file.first_seen_time.seconds >= 1209600 and + $seen.graph.entity.file.last_seen_time.seconds - $seen.graph.entity.file.first_seen_time.seconds < 1814400, 50, 0) + + if($seen.graph.entity.file.last_seen_time.seconds - $seen.graph.entity.file.first_seen_time.seconds >= 1814400 and + $seen.graph.entity.file.last_seen_time.seconds - $seen.graph.entity.file.first_seen_time.seconds < 2592000, 75, 0) + + if($seen.graph.entity.file.last_seen_time.seconds - $seen.graph.entity.file.first_seen_time.seconds >= 2592000, 100, 0)) + $event_count = count_distinct($execution.metadata.id) + // added to populate alert graph with additional context + $principal_hostname = array_distinct($execution.principal.hostname) + $principal_process_pid = array_distinct($execution.principal.process.pid) + $principal_process_command_line = array_distinct($execution.principal.process.command_line) + $principal_process_file_sha256 = array_distinct($execution.principal.process.file.sha256) + $principal_process_file_full_path = array_distinct($execution.principal.process.file.full_path) + $principal_process_product_specific_process_id = array_distinct($execution.principal.process.product_specific_process_id) + $principal_process_parent_process_product_specific_process_id = array_distinct($execution.principal.process.parent_process.product_specific_process_id) + $target_process_pid = array_distinct($execution.target.process.pid) + $target_process_command_line = array_distinct($execution.target.process.command_line) + // Commented out principal.hostname because it is already represented in graph as match variable. If match changes, can uncomment to add to results + //$target_process_file_sha256 = array_distinct($execution.target.process.file.sha256) + $target_process_file_full_path = array_distinct($execution.target.process.file.full_path) + $target_process_product_specific_process_id = array_distinct($execution.target.process.product_specific_process_id) + $principal_user_userid = array_distinct($execution.principal.user.userid) + $target_file_sha256 = array_distinct($execution.target.file.sha256) + $target_file_full_path = array_distinct($execution.target.file.full_path) + + condition: + $execution and $safebrowse and $seen +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule google_safebrowsing_file_contacts_tor_exit_node { + + meta: + author = "Google Cloud Security" + description = "A malicious file contacting a known Tor Exit Node." + rule_id = "mr_f6733319-50b3-477e-bad6-96bb4c14c632" + rule_name = "Google Safebrowsing File Contacts Tor Exit Node" + mitre_attack_tactic = "Command and Control" + mitre_attack_technique = "Proxy: Multi-hop Proxy" + mitre_attack_url = "https://attack.mitre.org/techniques/T1090/003/" + mitre_attack_version = "v13.1" + type = "alert" + data_source = "microsoft defender atp, crowdstrike, microsoft sysmon" + severity = "Critical" + priority = "High" + + events: + $network.metadata.event_type = "NETWORK_CONNECTION" + $network.principal.process.file.sha256 != "" + $network.principal.process.file.sha256 = $file_hash + $network.principal.hostname = $hostname + $network.target.ip = $ip + + // Safe Browsing file hashes provided by GCTI Feed + $safebrowse.graph.metadata.product_name = "Google Safe Browsing" + $safebrowse.graph.metadata.entity_type = "FILE" + $safebrowse.graph.metadata.source_type = "GLOBAL_CONTEXT" + $safebrowse.graph.metadata.threat.category = "SOFTWARE_MALICIOUS" + $safebrowse.graph.entity.file.sha256 = $file_hash + + // Tor IP listing provided by GCTI Feed + $gcti.graph.entity.artifact.ip = $ip + $gcti.graph.metadata.entity_type = "IP_ADDRESS" + $gcti.graph.metadata.source_type = "GLOBAL_CONTEXT" + $gcti.graph.metadata.threat.threat_feed_name = "Tor Exit Nodes" + $gcti.graph.metadata.vendor_name = "Google Cloud Threat Intelligence" + $gcti.graph.metadata.product_name = "GCTI Feed" + + match: + $hostname over 1h + + outcome: + $risk_score = max(95) + $mitre_attack_tactic = array_distinct("Command and Control") + $mitre_attack_technique = array_distinct("Proxy: Multi-hop Proxy") + $mitre_attack_technique_id = array_distinct("T1090.003") + $event_count = count_distinct($network.metadata.id) + //added to populate alert graph with additional context + $principal_ip = array_distinct($network.principal.ip) + $target_ip = array_distinct($network.target.ip) + $principal_process_pid = array_distinct($network.principal.process.pid) + $principal_process_command_line = array_distinct($network.principal.process.command_line) + $principal_process_file_sha256 = array_distinct($network.principal.process.file.sha256) + $principal_process_file_full_path = array_distinct($network.principal.process.file.full_path) + $principal_process_product_specific_process_id = array_distinct($network.principal.process.product_specific_process_id) + $principal_process_parent_process_product_specific_process_id = array_distinct($network.principal.process.parent_process.product_specific_process_id) + //$target_process_pid = array_distinct($network.target.process.pid) + $target_process_command_line = array_distinct($network.target.process.command_line) + $target_process_file_sha256 = array_distinct($network.target.process.file.sha256) + $target_process_file_full_path = array_distinct($network.target.process.file.full_path) + $target_process_product_specific_process_id = array_distinct($network.target.process.product_specific_process_id) + $target_process_parent_process_product_specific_process_id = array_distinct($network.target.process.parent_process.product_specific_process_id) + $principal_user_userid = array_distinct($network.principal.user.userid) + $target_user_userid = array_distinct($network.target.user.userid) + + condition: + $network and $gcti and $safebrowse +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule ioc_sha256_hash_vt { + + meta: + author = "Google Cloud Security" + description = "Detect file/process events with watchlisted hashes from MISP that VT flagged as MS Office docx file types" + rule_id = "mr_d36dec67-3af0-4d52-be78-1fe14c865006" + rule_name = "IOC SHA256 Hash VT" + type = "alert" + tags = "threat indicators, vt enrichment" + assumption = "Assumes MISP data has been ingested into entity graph; this rule can be modified to utilize other TI indicators" + data_source = "microsoft sysmon" + severity = "Medium" + priority = "Medium" + + events: + $process.metadata.event_type = "PROCESS_LAUNCH" or $process.metadata.event_type ="FILE_CREATION" + $process.principal.hostname = $hostname + $process.target.file.sha256 != "" + $process.target.file.sha256 = $sha256 + // Enriched field from VirusTotal integration, can be commented out or modified if not using + $process.target.file.file_type = "FILE_TYPE_DOCX" + + // Correlates with MISP data; can be modified based on your MISP parser or other TI + $ioc.graph.metadata.product_name = "MISP" + $ioc.graph.metadata.entity_type = "FILE" + $ioc.graph.metadata.source_type = "ENTITY_CONTEXT" + $ioc.graph.entity.file.sha256 = $sha256 + + match: + $hostname over 15m + + outcome: + $risk_score = max(65) + $event_count = count_distinct($process.metadata.id) + // added to populate alert graph with additional context + // Commented out principal.hostname because it is already represented in graph as match variable. If match changes, can uncomment to add to results + //$principal_hostname = array_distinct($process.principal.hostname) + $principal_process_pid = array_distinct($process.principal.process.pid) + $principal_process_command_line = array_distinct($process.principal.process.command_line) + $principal_process_file_sha256 = array_distinct($process.principal.process.file.sha256) + $principal_process_file_full_path = array_distinct($process.principal.process.file.full_path) + $principal_process_product_specific_process_id = array_distinct($process.principal.process.product_specific_process_id) + $principal_process_parent_process_product_specific_process_id = array_distinct($process.principal.process.parent_process.product_specific_process_id) + $target_process_pid = array_distinct($process.target.process.pid) + $target_process_command_line = array_distinct($process.target.process.command_line) + $target_process_file_sha256 = array_distinct($process.target.process.file.sha256) + $target_process_file_full_path = array_distinct($process.target.process.file.full_path) + $target_process_product_specific_process_id = array_distinct($process.target.process.product_specific_process_id) + $principal_user_userid = array_distinct($process.principal.user.userid) + $target_file_sha256 = array_distinct($process.target.file.sha256) + $target_file_full_path = array_distinct($process.target.file.full_path) + + condition: + $process and $ioc +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule low_prevalence_hash_on_process_launch_low_prevalence_domain_accessed { + + meta: + author = "Google Cloud Security" + description = "Detects when a low prevalence hash is seen during a process launch event, and a low prevalence domain is accessed within 10m." + rule_id = "mr_0624f9fb-8c73-4b8c-8651-b88ed736c862" + rule_name = "Low Prevalence Hash On Process Launch Low Prevalence Domain Accessed" + type = "alert" + tags = "prevalence" + data_source = "zscalar, microsoft sysmon" + severity = "Low" + priority = "Low" + + events: + // Process Launch + $process.metadata.event_type = "PROCESS_LAUNCH" + $process.principal.ip = $ip + $process.target.file.sha256 != "" + $process.target.file.sha256 = $sha256 + + // File Prevalence Criteria + $fileprev.graph.metadata.entity_type = "FILE" + $fileprev.graph.metadata.source_type = "DERIVED_CONTEXT" + $fileprev.graph.entity.file.prevalence.day_count = 10 + $fileprev.graph.entity.file.prevalence.rolling_max > 0 + //Adjust rolling_max for a different threshold as needed + $fileprev.graph.entity.file.prevalence.rolling_max <= 2 + //Join process event to file prevalence entity + $fileprev.graph.entity.file.sha256 = $sha256 + + // Network HTTP + $http.metadata.event_type = "NETWORK_HTTP" + $http.principal.ip = $ip + $http.target.hostname = $hostname + // Filter out URLs with RFC 1918 IP addresses + not net.ip_in_range_cidr($http.target.ip, "127.0.0.1/32") + not net.ip_in_range_cidr($http.target.ip, "10.0.0.0/8") + not net.ip_in_range_cidr($http.target.ip, "172.16.0.0/12") + not net.ip_in_range_cidr($http.target.ip, "192.168.0.0/16") + // Only match valid FQDN, filter out background non-routable noise + re.regex($http.target.hostname, `(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9][a-z0-9-]{0,61}[a-z0-9]`) + + // Domain Prevalence Criteria + $domainprev.graph.metadata.entity_type = "DOMAIN_NAME" + $domainprev.graph.metadata.source_type = "DERIVED_CONTEXT" + $domainprev.graph.entity.domain.prevalence.day_count = 10 + $domainprev.graph.entity.domain.prevalence.rolling_max > 0 + // Adjust rolling_max for a different threshold as needed + $domainprev.graph.entity.domain.prevalence.rolling_max < 2 + // Join network event to domain entity + $domainprev.graph.entity.domain.name = $hostname + + // Apply timing element to force the process to occur before the http + $process.metadata.event_timestamp.seconds <= $http.metadata.event_timestamp.seconds + + match: + $ip over 10m + + outcome: + $risk_score = max( + // increment risk score based upon rolling_max prevalence + if ( $domainprev.graph.entity.domain.prevalence.rolling_max >= 10, 10) + + if ( $domainprev.graph.entity.domain.prevalence.rolling_max >= 2 and $domainprev.graph.entity.domain.prevalence.rolling_max <= 9 , 20) + + if ( $domainprev.graph.entity.domain.prevalence.rolling_max = 1, 30) + ) + // added to populate alert graph with additional context + // Commented out principal.ip because it is already represented in graph as match variable. If match changes, can uncomment to add to results + //$principal_ip = array_distinct($http.principal.ip) + $target_ip = array_distinct($http.target.ip) + $principal_process_pid = array_distinct($process.principal.process.pid) + $principal_process_command_line = array_distinct($process.principal.process.command_line) + $principal_process_file_sha256 = array_distinct($process.principal.process.file.sha256) + $principal_process_file_full_path = array_distinct($process.principal.process.file.full_path) + $principal_process_product_specific_process_id = array_distinct($process.principal.process.product_specific_process_id) + $principal_process_parent_process_product_specific_process_id = array_distinct($process.principal.process.parent_process.product_specific_process_id) + $target_process_pid = array_distinct($process.target.process.pid) + $target_process_command_line = array_distinct($process.target.process.command_line) + $target_process_file_sha256 = array_distinct($process.target.process.file.sha256) + $target_process_file_full_path = array_distinct($process.target.process.file.full_path) + $target_process_product_specific_process_id = array_distinct($process.target.process.product_specific_process_id) + $principal_user_userid = array_distinct($process.principal.user.userid) + $target_url = array_distinct($http.target.url) + + condition: + $process and $fileprev and $http and $domainprev +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule network_connection_first_seen_in_past_day { + + meta: + author = "Google Cloud Security" + description = "Detect network connection to an ip address that was only seen for the first time in the past 24 hours" + rule_id = "mr_c3c9e4d3-eaa5-4f5b-9c64-70ce93247c51" + rule_name = "Network Connection First Seen In Past Day" + type = "alert" + tags = "first last seen" + data_source = "microsoft windows , gcp firewall, microsoft sysmon, crowdstrike, gcp scc, zeek" + severity = "Low" + priority = "Low" + + events: + $network.metadata.event_type = "NETWORK_CONNECTION" + $network.target.ip = $ip + //Target IP is not part of RFC1918 space, can modify as needed + not net.ip_in_range_cidr ($network.target.ip, "10.0.0.0/24") + not net.ip_in_range_cidr ($network.target.ip, "172.16.0.0/20") + not net.ip_in_range_cidr ($network.target.ip, "192.168.0.0/16") + + //derived from events ingested by Chronicle + $entity.graph.entity.artifact.ip = $ip + $entity.graph.metadata.entity_type = "IP_ADDRESS" + $entity.graph.metadata.source_type = "DERIVED_CONTEXT" + $entity.graph.entity.artifact.first_seen_time.seconds > 0 + + //calculate the different between current time and the first time the ip was listed as seen in the entity graph + 86400 > timestamp.current_seconds() - $entity.graph.entity.artifact.first_seen_time.seconds + + match: + $ip over 24h + + outcome: + $risk_score = max(35) + $event_count = count_distinct($network.metadata.id) + //added to populate alert graph with additional context + $principal_ip = array_distinct($network.principal.ip) + // Commented out target.ip because it is already represented in graph as match variable. If match changes, can uncomment to add to results + //$target_ip = array_distinct($network.target.ip) + $principal_process_pid = array_distinct($network.principal.process.pid) + $principal_process_command_line = array_distinct($network.principal.process.command_line) + $principal_process_file_sha256 = array_distinct($network.principal.process.file.sha256) + $principal_process_file_full_path = array_distinct($network.principal.process.file.full_path) + $principal_process_product_specific_process_id = array_distinct($network.principal.process.product_specific_process_id) + $principal_process_parent_process_product_specific_process_id = array_distinct($network.principal.process.parent_process.product_specific_process_id) + $target_process_pid = array_distinct($network.target.process.pid) + $target_process_command_line = array_distinct($network.target.process.command_line) + $target_process_file_sha256 = array_distinct($network.target.process.file.sha256) + $target_process_file_full_path = array_distinct($network.target.process.file.full_path) + $target_process_product_specific_process_id = array_distinct($network.target.process.product_specific_process_id) + $target_process_parent_process_product_specific_process_id = array_distinct($network.target.process.parent_process.product_specific_process_id) + $principal_user_userid = array_distinct($network.principal.user.userid) + $target_user_userid = array_distinct($network.target.user.userid) + + condition: + $network and $entity +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule process_launch_vt_enrichment { + + meta: + author = "Google Cloud Security" + description = "Identify process creations that are tagged exploit in VT" + rule_id = "mr_cf022210-8063-4aa0-9ad3-b2a2f7a7f725" + rule_name = "Process Launch VT Enrichment" + type = "alert" + tags = "vt enrichment" + data_source = "crowdstrike" + severity = "High" + priority = "High" + + events: + ($process.metadata.event_type = "PROCESS_LAUNCH" or $process.metadata.event_type = "FILE_CREATION") + $process.principal.hostname = $hostname + // Enriched field from VirusTotal integration, can be commented out or modified if not using + any $process.target.file.tags = "exploit" nocase + + match: + $hostname over 5m + + outcome: + $risk_score = max(85) + $event_count = count_distinct($process.metadata.id) + // added to populate alert graph with additional context + // Commented out principal.hostname because it is already represented in graph as match variable. If match changes, can uncomment to add to results + //$principal_hostname = array_distinct($process.principal.hostname) + $principal_process_pid = array_distinct($process.principal.process.pid) + $principal_process_command_line = array_distinct($process.principal.process.command_line) + $principal_process_file_sha256 = array_distinct($process.principal.process.file.sha256) + $principal_process_file_full_path = array_distinct($process.principal.process.file.full_path) + $principal_process_product_specific_process_id = array_distinct($process.principal.process.product_specific_process_id) + $principal_process_parent_process_product_specific_process_id = array_distinct($process.principal.process.parent_process.product_specific_process_id) + $target_process_pid = array_distinct($process.target.process.pid) + $target_process_command_line = array_distinct($process.target.process.command_line) + $target_process_file_sha256 = array_distinct($process.target.process.file.sha256) + $target_process_file_full_path = array_distinct($process.target.process.file.full_path) + $target_process_product_specific_process_id = array_distinct($process.target.process.product_specific_process_id) + $principal_user_userid = array_distinct($process.principal.user.userid) + $target_file_sha256 = array_distinct($process.target.file.sha256) + $target_file_full_path = array_distinct($process.target.file.full_path) + + condition: + $process +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule whois_recently_created_domain_access { + + meta: + author = "Google Cloud Security" + description = "Detects access attempts to a newly created domain via WHOIS enrichment." + rule_id = "mr_209a5ab1-a0ea-473c-bfae-7beb67673e99" + rule_name = "WHOIS Recently Created Domain Access" + type = "alert" + tags = "whois" + data_source = "zscalar" + severity = "Info" + priority = "Info" + + events: + ($access.metadata.event_type = "NETWORK_HTTP" or $access.metadata.event_type = "NETWORK_CONNECTION") + + // join access event to entity graph to use WHOIS data + $access.target.hostname = $domain + + // Whois domains provided by GCTI Feed + $whois.graph.entity.domain.name = $domain + $whois.graph.metadata.entity_type = "DOMAIN_NAME" + $whois.graph.metadata.vendor_name = "WHOIS" + $whois.graph.metadata.product_name = "WHOISXMLAPI Simple Whois" + $whois.graph.metadata.source_type = "GLOBAL_CONTEXT" + $whois.graph.entity.domain.creation_time.seconds > 0 + + // domain was created in the last 30 days + 2592000 > timestamp.current_seconds() - $whois.graph.entity.domain.creation_time.seconds + + match: + $domain over 1h + + outcome: + $risk_score = max(20) + $event_count = count_distinct($access.metadata.id) + //added to populate alert graph with additional context + $principal_hostname = array_distinct($access.principal.hostname) + // Commented out target.hostname because it is already represented in graph as match variable. If match changes, can uncomment to add to results + //$target_hostname = array_distinct($access.target.hostname) + $principal_process_pid = array_distinct($access.principal.process.pid) + $principal_process_command_line = array_distinct($access.principal.process.command_line) + $principal_process_file_sha256 = array_distinct($access.principal.process.file.sha256) + $principal_process_file_full_path = array_distinct($access.principal.process.file.full_path) + $principal_process_product_specific_process_id = array_distinct($access.principal.process.product_specific_process_id) + $principal_process_parent_process_product_specific_process_id = array_distinct($access.principal.process.parent_process.product_specific_process_id) + $target_process_pid = array_distinct($access.target.process.pid) + $target_process_command_line = array_distinct($access.target.process.command_line) + $target_process_file_sha256 = array_distinct($access.target.process.file.sha256) + $target_process_file_full_path = array_distinct($access.target.process.file.full_path) + $target_process_product_specific_process_id = array_distinct($access.target.process.product_specific_process_id) + $target_process_parent_process_product_specific_process_id = array_distinct($access.target.process.parent_process.product_specific_process_id) + $principal_user_userid = array_distinct($access.principal.user.userid) + $target_user_userid = array_distinct($access.target.user.userid) + $target_url = array_distinct($access.target.url) + + condition: + $access and $whois +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule ip_target_prevalence { + + meta: + author = "Google Cloud Security" + description = "Detect events that are communicating to IP addresses that have a low rolling max prevalence." + rule_id = "mr_0de02f28-2a7d-4128-aa31-02308491e744" + rule_name = "IP Target Prevalence" + type = "alert" + tags = "prevalence" + data_source = "crowdstrike, gcp firewall, microsoft sysmon, gcp scc, microsoft defender atp, corelight zeek, microsoft windows events" + severity = "Low" + priority = "Low" + + events: + $network.metadata.event_type = "NETWORK_CONNECTION" + $network.target.ip = $ip + + // derived from events ingested by Chronicle + $prevalence.graph.metadata.entity_type = "IP_ADDRESS" + $prevalence.graph.metadata.source_type = "DERIVED_CONTEXT" + $prevalence.graph.entity.artifact.prevalence.day_count = 10 + $prevalence.graph.entity.artifact.prevalence.rolling_max <= 3 + $prevalence.graph.entity.artifact.prevalence.rolling_max > 0 + $prevalence.graph.entity.artifact.ip = $ip + + match: + $ip over 5m + + outcome: + $risk_score = max(35) + $event_count = count_distinct($network.metadata.id) + // added to populate alert graph with additional context + $principal_ip = array_distinct($network.principal.ip) + // Commented out target.ip because it is already represented in graph as match variable. If match changes, can uncomment to add to results + //$target_ip = array_distinct($network.target.ip) + $principal_process_pid = array_distinct($network.principal.process.pid) + $principal_process_command_line = array_distinct($network.principal.process.command_line) + $principal_process_file_sha256 = array_distinct($network.principal.process.file.sha256) + $principal_process_file_full_path = array_distinct($network.principal.process.file.full_path) + $principal_process_product_specific_process_id = array_distinct($network.principal.process.product_specific_process_id) + $principal_process_parent_process_product_specific_process_id = array_distinct($network.principal.process.parent_process.product_specific_process_id) + $target_process_pid = array_distinct($network.target.process.pid) + $target_process_command_line = array_distinct($network.target.process.command_line) + $target_process_file_sha256 = array_distinct($network.target.process.file.sha256) + $target_process_file_full_path = array_distinct($network.target.process.file.full_path) + $target_process_product_specific_process_id = array_distinct($network.target.process.product_specific_process_id) + $target_process_parent_process_product_specific_process_id = array_distinct($network.target.process.parent_process.product_specific_process_id) + $principal_user_userid = array_distinct($network.principal.user.userid) + $target_user_userid = array_distinct($network.target.user.userid) + + condition: + $network and $prevalence +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule dns_query_to_recently_created_domain { + + meta: + author = "Google Cloud Security" + description = "DNS query to a recently created domain" + rule_id = "mr_a5cff3f1-8092-48a0-b4a3-f3f856299474" + rule_name = "DNS Query To Recently Created Domain" + type = "alert" + tags = "whois" + data_source = "microsoft sysmon" + severity = "Low" + priority = "Low" + + events: + $dns.metadata.event_type = "NETWORK_DNS" + $dns.network.dns.questions.name = $dns_query + $dns.principal.user.userid = $user + + // whois data provided by GCTI + $whois.graph.entity.hostname = $dns_query + $whois.graph.metadata.entity_type = "DOMAIN_NAME" + $whois.graph.metadata.vendor_name = "WHOIS" + $whois.graph.entity.domain.creation_time.seconds > 0 + // domain was created in the last 30 days + 2592000 > timestamp.current_seconds() - $whois.graph.entity.domain.creation_time.seconds + + match: + $user over 1h + + outcome: + $risk_score = max(35) + $event_count = count_distinct($dns.metadata.id) + $network_dns_questions_name = array_distinct($dns.network.dns.questions.name) + $network_dns_answers_data = array_distinct($dns.network.dns.answers.data) + // added to populate alert graph with additional context + $principal_ip = array_distinct($dns.principal.ip) + $target_ip = array_distinct($dns.target.ip) + $principal_process_pid = array_distinct($dns.principal.process.pid) + $principal_process_file_full_path = array_distinct($dns.principal.process.file.full_path) + $principal_process_product_specific_process_id = array_distinct($dns.principal.process.product_specific_process_id) + $principal_process_command_line = array_distinct($dns.principal.process.command_line) + $principal_process_file_sha256 = array_distinct($dns.principal.process.file.sha256) + $principal_process_parent_process_product_specific_process_id = array_distinct($dns.principal.process.parent_process.product_specific_process_id) + // Commented out principal.user.userid because it is already represented in graph as match variable. If match changes, can uncomment to add to results + //$principal_user_userid = array_distinct($dns.principal.user.userid) + + condition: + $dns and $whois +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + rule google_safebrowsing_with_prevalence { + + meta: + author = "Google Cloud Security" + description = "Detect process launch events that correlate to Safe Browsing hash data and have low prevalence" + rule_id = "mr_4b77947d-b7a5-4308-b54c-a87b2b1cb80f" + rule_name = "Google Safebrowsing With Prevalence" + type = "alert" + tags = "safe browsing, prevalence" + data_source = "microsoft sysmon" + severity = "Critical" + priority = "High" + + events: + $execution.metadata.event_type = "PROCESS_LAUNCH" + $execution.principal.hostname = $hostname + $execution.target.process.file.sha256 = $hash + + // Safe Browsing file hashes provided by GCTI Feed + $safebrowsing.graph.metadata.entity_type = "FILE" + $safebrowsing.graph.metadata.threat.severity = "CRITICAL" + $safebrowsing.graph.metadata.product_name = "Google Safe Browsing" + $safebrowsing.graph.metadata.source_type = "GLOBAL_CONTEXT" + $safebrowsing.graph.entity.file.sha256 = $hash + + //derived from events ingested by Chronicle + $prevalence.graph.metadata.entity_type = "FILE" + $prevalence.graph.metadata.source_type = "DERIVED_CONTEXT" + $prevalence.graph.entity.file.prevalence.day_count = 10 + $prevalence.graph.entity.file.prevalence.rolling_max <= 3 + $prevalence.graph.entity.file.prevalence.rolling_max > 0 + $prevalence.graph.entity.file.sha256 = $hash + + match: + $hostname, $hash over 5m + + outcome: + $risk_score = max(95) + $event_count = count_distinct($execution.metadata.id) + // added to populate alert graph with additional context + // Commented out principal.hostname because it is already represented in graph as match variable. If match changes, can uncomment to add to results + //$principal_hostname = array_distinct($execution.principal.hostname) + $principal_process_pid = array_distinct($execution.principal.process.pid) + $principal_process_command_line = array_distinct($execution.principal.process.command_line) + $principal_process_file_sha256 = array_distinct($execution.principal.process.file.sha256) + $principal_process_file_full_path = array_distinct($execution.principal.process.file.full_path) + $principal_process_product_specific_process_id = array_distinct($execution.principal.process.product_specific_process_id) + $principal_process_parent_process_product_specific_process_id = array_distinct($execution.principal.process.parent_process.product_specific_process_id) + $target_process_pid = array_distinct($execution.target.process.pid) + $target_process_command_line = array_distinct($execution.target.process.command_line) + $target_process_file_sha256 = array_distinct($execution.target.process.file.sha256) + $target_process_file_full_path = array_distinct($execution.target.process.file.full_path) + $target_process_product_specific_process_id = array_distinct($execution.target.process.product_specific_process_id) + $principal_user_userid = array_distinct($execution.principal.user.userid) + + condition: + $execution and $safebrowsing and $prevalence +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule ioc_hash_prevalence { + + meta: + author = "Google Cloud Security" + description = "Detect process/file events that match hashes found in our MISP instance and have low rolling max prevalence" + rule_id = "mr_58c661e3-e609-4df8-ae36-e85480e62a50" + rule_name = "IOC Hash Prevalence" + type = "alert" + tags = "prevalence, threat indicators" + assumption = "Assumes MISP data has been ingested into entity graph; this rule can be modified to utilize other TI indicators" + data_source = "microsoft sysmon" + severity = "High" + priority = "High" + + events: + $process.metadata.event_type = "FILE_CREATION" or $process.metadata.event_type = "PROCESS_LAUNCH" + $process.target.process.file.sha256 = $sha256 + + // derived from events ingested by Chronicle + $prevalence.graph.metadata.entity_type = "FILE" + $prevalence.graph.metadata.source_type = "DERIVED_CONTEXT" + $prevalence.graph.entity.file.prevalence.day_count = 10 + $prevalence.graph.entity.file.prevalence.rolling_max <= 3 + $prevalence.graph.entity.file.prevalence.rolling_max > 0 + $prevalence.graph.entity.file.sha256 = $sha256 + + // Correlates with MISP data; can be modified based on your MISP parser or other TI + $ioc.graph.metadata.entity_type = "FILE" + $ioc.graph.metadata.source_type = "ENTITY_CONTEXT" + $ioc.graph.metadata.product_name = "MISP" + $ioc.graph.entity.file.sha256 = $sha256 + + match: + $sha256 over 5m + + outcome: + $risk_score = max(85) + $event_count = count_distinct($process.metadata.id) + // added to populate alert graph with additional context + $principal_hostname = array_distinct($process.principal.hostname) + $principal_process_pid = array_distinct($process.principal.process.pid) + $principal_process_command_line = array_distinct($process.principal.process.command_line) + $principal_process_file_sha256 = array_distinct($process.principal.process.file.sha256) + $principal_process_file_full_path = array_distinct($process.principal.process.file.full_path) + $principal_process_product_specific_process_id = array_distinct($process.principal.process.product_specific_process_id) + $principal_process_parent_process_product_specific_process_id = array_distinct($process.principal.process.parent_process.product_specific_process_id) + $target_process_pid = array_distinct($process.target.process.pid) + $target_process_command_line = array_distinct($process.target.process.command_line) + // Commented out target.process.file.sha256 because it is already represented in graph as match variable. If match changes, can uncomment to add to results + $target_process_file_sha256 = array_distinct($process.target.process.file.sha256) + $target_process_file_full_path = array_distinct($process.target.process.file.full_path) + $target_process_product_specific_process_id = array_distinct($process.target.process.product_specific_process_id) + $principal_user_userid = array_distinct($process.principal.user.userid) + $target_file_sha256 = array_distinct($process.target.file.sha256) + $target_file_full_path = array_distinct($process.target.file.full_path) + + condition: + $process and $ioc and $prevalence +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule ioc_sha256_hash { + + meta: + author = "Google Cloud Security" + description = "Detect file/process events that match watchlisted hashes in MISP" + rule_id = "mr_82df7e96-1bc3-489d-9e17-ff86e8f6e89b" + rule_name = "IOC SHA256 Hash" + type = "alert" + tags = "threat indicators" + assumption = "Assumes MISP data has been ingested into entity graph; this rule can be modified to utilize other TI indicators" + data_source = "microsoft sysmon" + severity = "Medium" + priority = "Medium" + + events: + $process.metadata.event_type = "PROCESS_LAUNCH" or $process.metadata.event_type ="FILE_CREATION" + $process.target.process.file.sha256 = $sha256 + + // Correlates with MISP data; can be modified based on your MISP parser or other TI + $ioc.graph.metadata.product_name = "MISP" + $ioc.graph.metadata.entity_type = "FILE" + $ioc.graph.metadata.source_type = "ENTITY_CONTEXT" + $ioc.graph.entity.file.sha256 = $sha256 + + match: + $sha256 over 5m + + outcome: + $risk_score = max(65) + $event_count = count_distinct($process.metadata.id) + // added to populate alert graph with additional context + $principal_hostname = array_distinct($process.principal.hostname) + $principal_process_pid = array_distinct($process.principal.process.pid) + $principal_process_command_line = array_distinct($process.principal.process.command_line) + $principal_process_file_sha256 = array_distinct($process.principal.process.file.sha256) + $principal_process_file_full_path = array_distinct($process.principal.process.file.full_path) + $principal_process_product_specific_process_id = array_distinct($process.principal.process.product_specific_process_id) + $principal_process_parent_process_product_specific_process_id = array_distinct($process.principal.process.parent_process.product_specific_process_id) + $target_process_pid = array_distinct($process.target.process.pid) + $target_process_command_line = array_distinct($process.target.process.command_line) + // Commented out target.process.file.sha256 because it is already represented in graph as match variable. If match changes, can uncomment to add to results + //$target_process_file_sha256 = array_distinct($process.target.process.file.sha256) + $target_process_file_full_path = array_distinct($process.target.process.file.full_path) + $target_process_product_specific_process_id = array_distinct($process.target.process.product_specific_process_id) + $principal_user_userid = array_distinct($process.principal.user.userid) + $target_file_sha256 = array_distinct($process.target.file.sha256) + $target_file_full_path = array_distinct($process.target.file.full_path) + + condition: + $process and $ioc +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule google_safebrowsing_file_process_creation { + + meta: + author = "Google Cloud Security" + description = "Detection of process/file events that match Safe Browsing hashes, which are files deemed to be malicious" + rule_id = "mr_6aa149a9-cae3-4414-b50f-75cf53ac5e11" + rule_name = "Google Safebrowsing File Process Creation" + type = "alert" + tags = "safe browsing" + data_source = "microsoft sysmon" + severity = "Critical" + priority = "High" + + events: + ($execution.metadata.event_type = "PROCESS_LAUNCH" or $execution.metadata.event_type = "FILE_CREATION") + $execution.principal.hostname = $hostname + $execution.target.process.file.sha256 != "" + $execution.target.process.file.sha256 = $sha256 + + // join execution event with Safe Browsing graph + $safebrowse.graph.entity.file.sha256 = $sha256 + + // Safe Browsing file hashes provided by GCTI Feed + $safebrowse.graph.metadata.product_name = "Google Safe Browsing" + $safebrowse.graph.metadata.entity_type = "FILE" + $safebrowse.graph.metadata.source_type = "GLOBAL_CONTEXT" + + // Can comment the following two lines to adjust the safe browsing hashes available for correlation + $safebrowse.graph.metadata.threat.category = "SOFTWARE_MALICIOUS" + $safebrowse.graph.metadata.threat.severity = "CRITICAL" + + match: + $hostname over 1h + + outcome: + $risk_score = max(95) + $event_count = count_distinct($execution.metadata.id) + // added to populate alert graph with additional context + // Commented out principal.hostname because it is already represented in graph as match variable. If match changes, can uncomment to add to results + $principal_hostname = array_distinct($execution.principal.hostname) + $principal_process_pid = array_distinct($execution.principal.process.pid) + $principal_process_command_line = array_distinct($execution.principal.process.command_line) + $principal_process_file_sha256 = array_distinct($execution.principal.process.file.sha256) + $principal_process_file_full_path = array_distinct($execution.principal.process.file.full_path) + $principal_process_product_specific_process_id = array_distinct($execution.principal.process.product_specific_process_id) + $principal_process_parent_process_product_specific_process_id = array_distinct($execution.principal.process.parent_process.product_specific_process_id) + $target_process_pid = array_distinct($execution.target.process.pid) + $target_process_command_line = array_distinct($execution.target.process.command_line) + $target_process_file_sha256 = array_distinct($execution.target.process.file.sha256) + $target_process_file_full_path = array_distinct($execution.target.process.file.full_path) + $target_process_product_specific_process_id = array_distinct($execution.target.process.product_specific_process_id) + $principal_user_userid = array_distinct($execution.principal.user.userid) + $target_file_sha256 = array_distinct($execution.target.file.sha256) + $target_file_full_path = array_distinct($execution.target.file.full_path) + + condition: + $execution and $safebrowse +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule whois_dns_query_to_typosquatting_domain { + + meta: + author = "Google Cloud Security" + description = "Provides example usage of WHOIS data, detecting a DNS query for a domain that contains a specific string and is not registered with the defined domain registrar." + rule_id = "mr_32cd8835-d328-4a89-8265-f19cffe89346" + rule_name = "WHOIS DNS Query To Typesquatting Domain" + // This rule must be customized to alert on DNS queries for possible typosquatting domains that contain your organization's domain name(s) that are not registered with your approved domain registrar. + type = "hunt" + tags = "whois" + data_source = "microsoft sysmon" + severity = "low" + priority = "low" + + events: + // Match on DNS queries for domains that contain a specific string or company name(s). + $dns.metadata.event_type = "NETWORK_DNS" + // Customize the value for $dns.network.dns.questions.name to fit your environment. + $dns.network.dns.questions.name = /threatpunter/ nocase + $dns.network.dns.questions.name = $dns_query_name + + // Join DNS query events with WHOIS data. + $whois.graph.entity.hostname = $dns_query_name + $whois.graph.metadata.entity_type = "DOMAIN_NAME" + $whois.graph.metadata.vendor_name = "WHOIS" + $whois.graph.metadata.product_name = "WHOISXMLAPI Simple Whois" + $whois.graph.metadata.source_type = "GLOBAL_CONTEXT" + + // Check if the domain is registered with a registrar other than Mark Monitor. + // Customize the values for $whois.graph.entity.domain.registrar based on the approved/expected registrar(s) used by your organization. + $whois.graph.entity.domain.registrar != "MarkMonitor Inc." + + // Check if the domain was first seen in our environment within the last 30 days (2592000 seconds). + $seen.graph.entity.domain.name = $dns_query_name + $seen.graph.entity.domain.first_seen_time.seconds > 0 + 2592000 > timestamp.current_seconds() - $seen.graph.entity.domain.first_seen_time.seconds + + match: + // Return the DNS query name when the rule finds a match within a 1 hour time window. + $dns_query_name over 1h + + outcome: + $event_count = count_distinct($dns.metadata.id) + $principal_hostname = array_distinct($dns.principal.hostname) + $network_dns_questions_name = array_distinct($dns.network.dns.questions.name) + $network_dns_answers_data = array_distinct($dns.network.dns.answers.data) + $principal_ip = array_distinct($dns.principal.ip) + $target_ip = array_distinct($dns.target.ip) + $principal_process_pid = array_distinct($dns.principal.process.pid) + $principal_process_file_full_path = array_distinct($dns.principal.process.file.full_path) + $principal_process_product_specific_process_id = array_distinct($dns.principal.process.product_specific_process_id) + $principal_process_command_line = array_distinct($dns.principal.process.command_line) + $principal_process_file_sha256 = array_distinct($dns.principal.process.file.sha256) + $principal_process_parent_process_product_specific_process_id = array_distinct($dns.principal.process.parent_process.product_specific_process_id) + $principal_user_userid = array_distinct($dns.principal.user.userid) + + condition: + // Trigger rule if a match is found for the following events. + $dns and $whois and $seen +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule vt_relationships_file_contacts_domain { + + meta: + author = "Google Cloud Security" + description = "Alert on known Hash querying a known hostname with VT Relationships" + rule_id = "mr_42ee37ba-cb36-49f2-b784-05ca0bd55b9f" + rule_name = "VT Relationships File Contacts Domain" + type = "alert" + tags = "vt" + data_source = "microsoft sysmon, crowdstrike" + severity = "High" + priority = "High" + + events: + $dns.metadata.event_type = "NETWORK_DNS" + $dns.principal.process.file.sha256 = $file_hash + $dns.network.dns.questions.name = $domain + strings.coalesce($dns.principal.hostname, $dns.target.user.userid) = $hostname_or_userid + + // Uses VirusTotal integration via entity graph, this section maps to principal process file hash + $vt.graph.metadata.entity_type = "FILE" + $vt.graph.metadata.source_type = "GLOBAL_CONTEXT" + $vt.graph.metadata.vendor_name = "VirusTotal" + $vt.graph.metadata.product_name = "VirusTotal Relationships" + $vt.graph.entity.file.sha256 = $file_hash + + // Uses VirusTotal integration via entity graph, this section maps the hash to the domain it contacts + $vt.graph.relations.entity_type = "DOMAIN_NAME" + $vt.graph.relations.relationship = "CONTACTS" + $vt.graph.relations.entity.domain.name = $domain + + match: + $hostname_or_userid over 5m + + outcome: + $risk_score = max(85) + $event_count = count_distinct($dns.metadata.id) + $network_dns_questions_name = array_distinct($dns.network.dns.questions.name) + $network_dns_answers_data = array_distinct($dns.network.dns.answers.data) + // added to populate alert graph with additional context + $principal_ip = array_distinct($dns.principal.ip) + $target_ip = array_distinct($dns.target.ip) + $principal_process_pid = array_distinct($dns.principal.process.pid) + $principal_process_file_full_path = array_distinct($dns.principal.process.file.full_path) + $principal_process_product_specific_process_id = array_distinct($dns.principal.process.product_specific_process_id) + $principal_user_userid = array_distinct($dns.principal.user.userid) + $principal_process_command_line = array_distinct($dns.principal.process.command_line) + $principal_process_file_sha256 = array_distinct($dns.principal.process.file.sha256) + $principal_process_parent_process_product_specific_process_id = array_distinct($dns.principal.process.parent_process.product_specific_process_id) + + condition: + $dns and $vt +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule vt_relationships_file_executes_file { + + meta: + author = "Google Cloud Security" + description = "Alert on known File Hash executing known File Hash with VT Relationships." + rule_id = "mr_9250a0b5-b671-4c63-bb78-d7fda0ac2cf4" + rule_name = "VT Relationships File Executes File" + type = "alert" + tags = "vt" + data_source = "microsoft sysmon" + severity = "High" + priority = "High" + + events: + $process.metadata.event_type = "PROCESS_LAUNCH" + $process.principal.process.file.sha256 = $p_file_hash + $process.target.process.file.sha256 = $t_file_hash + $process.principal.hostname = $hostname + + // Uses VirusTotal integration via entity graph, this section maps to principal process file hash + $vt.graph.metadata.entity_type = "FILE" + $vt.graph.metadata.source_type = "GLOBAL_CONTEXT" + $vt.graph.metadata.vendor_name = "VirusTotal" + $vt.graph.metadata.product_name = "VirusTotal Relationships" + $vt.graph.entity.file.sha256 = $p_file_hash + + // Uses VirusTotal integration via entity graph, this section maps the hash to a hash it executes + $vt.graph.relations.entity_type = "FILE" + $vt.graph.relations.relationship = "EXECUTES" + $vt.graph.relations.entity.file.sha256 = $t_file_hash + + match: + $hostname over 5m + + outcome: + $risk_score = max(85) + $event_count = count_distinct($process.metadata.id) + //added to populate alert graph with additional context + // Commented out principal.hostname because it is already represented in graph as match variable. If match changes, can uncomment to add to results + //$principal_hostname = array_distinct($process.principal.hostname) + $principal_process_pid = array_distinct($process.principal.process.pid) + $principal_process_command_line = array_distinct($process.principal.process.command_line) + $principal_process_file_sha256 = array_distinct($process.principal.process.file.sha256) + $principal_process_file_full_path = array_distinct($process.principal.process.file.full_path) + $principal_process_product_specific_process_id = array_distinct($process.principal.process.product_specific_process_id) + $principal_process_parent_process_product_specific_process_id = array_distinct($process.principal.process.parent_process.product_specific_process_id) + $target_process_pid = array_distinct($process.target.process.pid) + $target_process_command_line = array_distinct($process.target.process.command_line) + $target_process_file_sha256 = array_distinct($process.target.process.file.sha256) + $target_process_file_full_path = array_distinct($process.target.process.file.full_path) + $target_process_product_specific_process_id = array_distinct($process.target.process.product_specific_process_id) + $principal_user_userid = array_distinct($process.principal.user.userid) + + condition: + $process and $vt +} + +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule gcti_tor_exit_nodes { + + meta: + author = "Google Cloud Security" + description = "Alert traffic destined for known Tor exit nodes" + rule_id = "mr_1d31f0e4-8cd9-4fc2-ae87-e91a435fe34f" + rule_name = "GCTI Tor Exit Nodes" + mitre_attack_tactic = "Command and Control" + mitre_attack_technique = "Proxy: Multi-hop Proxy" + mitre_attack_url = "https://attack.mitre.org/techniques/T1090/003/" + mitre_attack_version = "v13.1" + type = "alert" + tags = "tor" + data_source = "crowdstrike, microsoft sysmon, microsoft defender atp" + severity = "High" + priority = "High" + + events: + $network.metadata.event_type = "NETWORK_CONNECTION" + $network.security_result.action = "ALLOW" + $network.target.ip = $ip + + // Tor IP listing provided by GCTI Feed + $gcti_feed.graph.entity.artifact.ip = $ip + $gcti_feed.graph.metadata.entity_type = "IP_ADDRESS" + $gcti_feed.graph.metadata.threat.threat_feed_name = "Tor Exit Nodes" + $gcti_feed.graph.metadata.product_name = "GCTI Feed" + $gcti_feed.graph.metadata.source_type = "GLOBAL_CONTEXT" + + match: + $ip over 1h + + outcome: + $risk_score = max(85) + $mitre_attack_tactic = array_distinct("Command and Control") + $mitre_attack_technique = array_distinct("Proxy: Multi-hop Proxy") + $mitre_attack_technique_id = array_distinct("T1090.003") + $event_count = count_distinct($network.metadata.id) + $tor_geoip_country = array_distinct($network.target.ip_geo_artifact.location.country_or_region) + $tor_geoip_state = array_distinct($network.target.ip_geo_artifact.location.state) + // added to populate alert graph with additional context + $principal_ip = array_distinct($network.principal.ip) + // Commented out target.ip because it is already represented in graph as match variable. If match changes, can uncomment to add to results + //$target_ip = array_distinct($network.target.ip) + $principal_process_pid = array_distinct($network.principal.process.pid) + $principal_process_command_line = array_distinct($network.principal.process.command_line) + $principal_process_file_sha256 = array_distinct($network.principal.process.file.sha256) + $principal_process_file_full_path = array_distinct($network.principal.process.file.full_path) + $principal_process_product_specific_process_id = array_distinct($network.principal.process.product_specific_process_id) + $principal_process_parent_process_product_specific_process_id = array_distinct($network.principal.process.parent_process.product_specific_process_id) + $target_process_pid = array_distinct($network.target.process.pid) + $target_process_command_line = array_distinct($network.target.process.command_line) + $target_process_file_sha256 = array_distinct($network.target.process.file.sha256) + $target_process_file_full_path = array_distinct($network.target.process.file.full_path) + //$target_process_product_specific_process_id = array_distinct($network.target.process.product_specific_process_id) + //$target_process_parent_process_product_specific_process_id = array_distinct($network.target.process.parent_process.product_specific_process_id) + $principal_user_userid = array_distinct($network.principal.user.userid) + $target_user_userid = array_distinct($network.target.user.userid) + + condition: + $network and $gcti_feed +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule hash_prevalence { + + meta: + author = "Google Cloud Security" + description = "Correlate process events with hashes that have a low rolling max over the past 10 days" + rule_id = "mr_abaa155b-f4ce-4fb2-b525-3eed59bca6d1" + rule_name = "Hash Prevalence" + type = "alert" + tags = "prevalence" + data_source = "crowdstrike, sentinelone, microsoft sysmon, microsoft defender atp" + severity = "Low" + priority = "Low" + + events: + $process.metadata.event_type = "PROCESS_LAUNCH" + $process.target.process.file.sha256 = $sha256 + + $prevalence.graph.metadata.entity_type = "FILE" + $prevalence.graph.metadata.source_type = "DERIVED_CONTEXT" + $prevalence.graph.entity.file.prevalence.day_count = 10 + $prevalence.graph.entity.file.prevalence.rolling_max <= 3 + $prevalence.graph.entity.file.prevalence.rolling_max > 0 + $prevalence.graph.entity.file.sha256 = $sha256 + match: + $sha256 over 5m + + outcome: + $risk_score = max(35) + $event_count = count_distinct($process.metadata.id) + // added to populate alert graph with additional context + $principal_hostname = array_distinct($process.principal.hostname) + $principal_process_pid = array_distinct($process.principal.process.pid) + $principal_process_command_line = array_distinct($process.principal.process.command_line) + $principal_process_file_sha256 = array_distinct($process.principal.process.file.sha256) + $principal_process_file_full_path = array_distinct($process.principal.process.file.full_path) + $principal_process_product_specific_process_id = array_distinct($process.principal.process.product_specific_process_id) + $principal_process_parent_process_product_specific_process_id = array_distinct($process.principal.process.parent_process.product_specific_process_id) + $target_process_pid = array_distinct($process.target.process.pid) + $target_process_command_line = array_distinct($process.target.process.command_line) + // Commented out process.target.process.file.sha256 because it is already represented in graph as match variable. If match changes, can uncomment to add to results + //$target_process_file_sha256 = array_distinct($process.target.process.file.sha256) + $target_process_file_full_path = array_distinct($process.target.process.file.full_path) + $target_process_product_specific_process_id = array_distinct($process.target.process.product_specific_process_id) + $principal_user_userid = array_distinct($process.principal.user.userid) + + condition: + $process and $prevalence +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule vt_relationships_file_downloaded_from_url { + + meta: + author = "Google Cloud Security" + description = "Alert on downloading a known file hash from a known IP with VT Relationships." + rule_id = "mr_2890216d-6106-4841-b714-177f55ecc837" + rule_name = "VT Relationships File Downloaded From URL" + type = "alert" + tags = "vt" + data_source = "microsoft login events" + severity = "Critical" + priority = "Critical" + + events: + // NETWORK_HTTP + $http.metadata.event_type = "NETWORK_HTTP" + $http.principal.user.userid = $userid + $http.target.url = $url + + // FILE_CREATION + $file.metadata.event_type = "FILE_CREATION" + $file.target.user.userid = $userid + $file.target.file.sha256 = $file_hash + //$vtUrl = strings.concat("https://www.virustotal.com/gui/file/", $file.target.file.sha256) + + // Network HTTP event must occur before the file creation event + $http.metadata.event_timestamp.seconds < $file.metadata.event_timestamp.seconds + + // Uses VirusTotal integration via entity graph, this section maps to target file hash + $vt.graph.metadata.entity_type = "FILE" + $vt.graph.metadata.source_type = "GLOBAL_CONTEXT" + $vt.graph.metadata.vendor_name = "VirusTotal" + $vt.graph.metadata.product_name = "VirusTotal Relationships" + $vt.graph.entity.file.sha256 = $file_hash + + // Uses VirusTotal integration via entity graph, this section maps the hash to the url it is downloaded from + $vt.graph.relations.entity_type = "URL" + $vt.graph.relations.relationship = "DOWNLOADED_FROM" + $vt.graph.relations.entity.url = $url + + match: + $userid over 1m + + outcome: + $risk_score = max(95) + //added to populate alert graph with additional context + $principal_hostname = array_distinct($http.principal.hostname) + $target_hostname = array_distinct($file.target.hostname) + $principal_process_pid = array_distinct($file.principal.process.pid) + $principal_process_command_line = array_distinct($file.principal.process.command_line) + $principal_process_file_sha256 = array_distinct($file.principal.process.file.sha256) + $principal_process_file_full_path = array_distinct($file.principal.process.file.full_path) + $principal_process_product_specific_process_id = array_distinct($file.principal.process.product_specific_process_id) + $principal_process_parent_process_product_specific_process_id = array_distinct($file.principal.process.parent_process.product_specific_process_id) + $target_process_pid = array_distinct($file.target.process.pid) + $target_process_command_line = array_distinct($file.target.process.command_line) + $target_process_file_sha256 = array_distinct($file.target.process.file.sha256) + $target_process_file_full_path = array_distinct($file.target.process.file.full_path) + $target_process_product_specific_process_id = array_distinct($file.target.process.product_specific_process_id) + $target_process_parent_process_product_specific_process_id = array_distinct($file.target.process.parent_process.product_specific_process_id) + $principal_user_userid = array_distinct($file.principal.user.userid) + // Commented out target.user.userid because it is already represented in graph as match variable. If match changes, can uncomment to add to results + //$target_user_userid = array_distinct($file.target.user.userid) + $target_file_sha256 = array_distinct($file.target.file.sha256) + $target_file_full_path = array_distinct($file.target.file.full_path) + $target_url = array_distinct($http.target.url) + + condition: + $http and $file and $vt +} +/* + * Copyright 2023 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +rule whois_expired_domain_executable_downloaded { + + meta: + author = "Google Cloud Security" + description = "Detect web traffic to a recently expired domain followed by an exe file creation event" + rule_id = "mr_ce0a1979-ec95-40d4-8107-748ee6d1e93f" + rule_name = "WHOIS Expired Domain Executable Downloaded" + type = "alert" + tags = "whois" + data_source = "zscalar, microsoft sysmon" + platform = "Windows" + severity = "Low" + priority = "Low" + + events: + $access.metadata.event_type = "NETWORK_HTTP" + $access.principal.hostname = $hostname + $access.target.hostname = $domain + + // join access event to entity graph to use WHOIS data + $whois.graph.entity.domain.name = $domain + + // Whois domains provided by GCTI Feed + $whois.graph.metadata.entity_type = "DOMAIN_NAME" + $whois.graph.metadata.vendor_name = "WHOIS" + $whois.graph.metadata.product_name = "WHOISXMLAPI Simple Whois" + $whois.graph.metadata.source_type = "GLOBAL_CONTEXT" + // Filter out domains without expiration time + $whois.graph.entity.domain.expiration_time.seconds > 0 + // Domain expired before the event + $whois.graph.entity.domain.expiration_time.seconds < $access.metadata.event_timestamp.seconds + + // join access event with executable file creation event by principal hostname + $creation.principal.hostname = $hostname + $creation.metadata.event_type = "FILE_CREATION" + $creation.target.file.full_path = /\.exe/ nocase + + // file creation comes after network event + $creation.metadata.event_timestamp.seconds > $access.metadata.event_timestamp.seconds + + match: + $hostname over 1h + + outcome: + $risk_score = max(20) + // added to populate alert graph with additional context + // Commented out principal.hostname because it is already represented in graph as match variable. If match changes, can uncomment to add to results + //$principal_hostname = array_distinct($access.principal.hostname) + $target_hostname = array_distinct($access.target.hostname) + $principal_process_pid = array_distinct($access.principal.process.pid) + $principal_process_command_line = array_distinct($access.principal.process.command_line) + $principal_process_file_sha256 = array_distinct($access.principal.process.file.sha256) + $principal_process_file_full_path = array_distinct($access.principal.process.file.full_path) + $principal_process_product_specific_process_id = array_distinct($access.principal.process.product_specific_process_id) + $principal_process_parent_process_product_specific_process_id = array_distinct($access.principal.process.parent_process.product_specific_process_id) + $target_process_pid = array_distinct($access.target.process.pid) + $target_process_command_line = array_distinct($access.target.process.command_line) + $target_process_file_sha256 = array_distinct($access.target.process.file.sha256) + $target_process_file_full_path = array_distinct($access.target.process.file.full_path) + $target_process_product_specific_process_id = array_distinct($access.target.process.product_specific_process_id) + $target_process_parent_process_product_specific_process_id = array_distinct($access.target.process.parent_process.product_specific_process_id) + $principal_user_userid = array_distinct($access.principal.user.userid) + $target_user_userid = array_distinct($access.target.user.userid) + $target_url = array_distinct($access.target.url) + $target_file_sha256 = array_distinct($creation.target.file.sha256) + $target_file_full_path = array_distinct($creation.target.file.full_path) + + condition: + $access and $whois and $creation +} diff --git a/blueprints/secops-ai-migration-helper/recommender_curated_community/resources/example_recommendation_curated_community_rules.csv b/blueprints/secops-ai-migration-helper/recommender_curated_community/resources/example_recommendation_curated_community_rules.csv new file mode 100644 index 0000000..03b0e3f --- /dev/null +++ b/blueprints/secops-ai-migration-helper/recommender_curated_community/resources/example_recommendation_curated_community_rules.csv @@ -0,0 +1,5 @@ +ucid,title,description,curated rules,curated rules coverage,curated rationale,community rules,community rules coverage,community rationale +9901,Rare Scripting Software Detected,"Because powershell and cmd prompt are so closely watched and have so many alarms put up to catch misuse, hackers are starting to avoid using them. This detects scripting tools that are utilised and found in the Event log that aren't approved software by your environment.","Applied Threat Intelligence - Curated Prioritization/High Priority Host Indicators/ATI High Priority Rule Match for File IoCs (principal.process.file.sha256),Applied Threat Intelligence - Curated Prioritization/High Priority Host Indicators/ATI High Priority Rule Match for File IoCs (target.process.file.sha256),Applied Threat Intelligence - Curated Prioritization/High Priority Host Indicators/ATI High Priority Rule Match for File IoCs (target.file.sha256),Applied Threat Intelligence - Curated Prioritization/High Priority Host Indicators/ATI High Priority Rule Match for File IoCs (about.file.sha256)",very good,"The security objective is to detect malicious scripting activity that avoids common tools. The suggested curated rules are part of the 'Applied Threat Intelligence - Curated Prioritization' set and will trigger if the hash of a running process or a file on disk matches a known malicious indicator from Google's threat intelligence. This effectively detects known malicious or rare scripting tools without relying on potentially noisy keyword matching. Log Data Sources: EDR logs such as Microsoft Sysmon (WINDOWS_SYSMON), Crowdstrike Falcon (CS_EDR), SentinelOne (SENTINEL_EDR), Carbon Black (CB_EDR).","recon_suspicious_commands_cisa_report,mitre_attack_T1140_encoded_powershell_command,gcti_remote_access_tools,recon_environment_enumeration_system_cisa_report,google_safebrowsing_file_process_creation",very good,"The selected community rules collectively detect the execution of suspicious or unauthorized tools and scripts, aligning with the input rule's objective. The `recon_suspicious_commands_cisa_report` and `recon_environment_enumeration_system_cisa_report` rules use specific, intelligence-driven command-line patterns to identify a wide range of malicious activities. The `mitre_attack_T1140_encoded_powershell_command` rule targets a common evasion technique used with scripting tools. Furthermore, `gcti_remote_access_tools` and `google_safebrowsing_file_process_creation` leverage threat intelligence feeds to detect known malicious tools by their file hashes, offering a more robust detection method than the input rule's generic keyword matching. Log Data Sources: Microsoft Sysmon, Microsoft Windows Events, CrowdStrike, SentinelOne, Microsoft Defender ATP." +9902,Rare or Never Seen Events EventID Logged,This requires a watchlist of every event ID from this table and one of rare event IDs,Risk Analytics for UEBA/New Login by User to Device/First Time Interactive Service Account Login by Principal User ID and Target Service Account,partially,"The curated rule detects the first time a user interactively logs in with a service account, which aligns with the input rule's objective of identifying new or rare events. While the input rule is generic and looks for any new EventID, the curated rule applies the 'first seen' concept to a specific, high-value security scenario. Log Data Sources: Windows Security Events (WINDOWS_EVENT_LOG), Linux logs (NIX_SYSTEM), or various cloud/SaaS application logs that produce USER_LOGIN events.","hash_prevalence,domain_prevalence,ip_target_prevalence,network_connection_first_seen_in_past_day,low_prevalence_hash_on_process_launch_low_prevalence_domain_accessed",very good,"The input rule's objective is to detect rare or never-before-seen Windows Event IDs, which is a form of anomaly detection based on event frequency. The suggested community rules achieve the same security objective by applying prevalence and first-seen logic to other critical security data points. 'hash_prevalence', 'domain_prevalence', and 'ip_target_prevalence' directly use prevalence calculations to find rare file hashes, domains, and IP addresses, respectively. 'network_connection_first_seen_in_past_day' detects new IP addresses, aligning with the 'never seen' aspect of the input rule. 'low_prevalence_hash_on_process_launch_low_prevalence_domain_accessed' provides a high-fidelity signal by combining two prevalence checks. Collectively, these rules provide robust coverage for detecting rare and potentially malicious activities through anomaly detection. Log Data Sources: EDR logs (e.g., Microsoft Sysmon, CrowdStrike), DNS logs, and Network/Firewall logs (e.g., Zeek, GCP Firewall)." +9903,New Run/RunOnce Scheduled Task,Shell-Core EventID 9706/9707/9708,N/A,no,"No equivalent curated rule was found that specifically detects persistence through the creation or modification of Run/RunOnce registry keys. The provided curated rules focus on IOC matching or high-level UEBA detections like anomalous logins and network traffic, which do not cover this specific persistence technique.","mitre_attack_T1053_005_windows_creation_of_scheduled_task,suspicious_unusual_location_lnk_file",partially,"The input rule detects persistence via Run/RunOnce registry keys (T1547.001). The community rules cover similar persistence objectives. 'mitre_attack_T1053_005_windows_creation_of_scheduled_task' detects the creation of scheduled tasks (T1053.005), another common method for autostart execution. 'suspicious_unusual_location_lnk_file' detects the creation of shortcut files in startup folders, which is also part of the T1547 technique family. While the specific implementation differs, the overall goal of detecting persistence is addressed. Log Data Sources: Microsoft Sysmon, SentinelOne, or other EDR logs providing process launch and file events." +9904,Unusual binary shutting down endpoint,Malware may cause shutdowns on this EID as well as EventID 6006 too,"Applied Threat Intelligence - Curated Prioritization/Active Breach Priority Host Indicators/ATI Active Breach Rule Match for File IoCs (principal.process.file.sha256),Applied Threat Intelligence - Curated Prioritization/High Priority Host Indicators/ATI High Priority Rule Match for File IoCs (target.file.sha256),Applied Threat Intelligence - Curated Prioritization/Medium Priority Host Indicators/ATI Medium Priority Rule Match for File IoCs (principal.process.file.sha256),Applied Threat Intelligence - Curated Prioritization/Medium Priority Host Indicators/ATI Medium Priority Rule Match for File IoCs (target.file.sha256)",very good,"The security objective is to detect malware initiating a system shutdown. While there isn't a specific curated rule for the shutdown event (EventID 1074), the Applied Threat Intelligence rules provide excellent coverage by detecting the malicious binary itself based on its file hash when it is executed or written to disk. This often provides an earlier detection of the threat. Log Data Sources: EDR (Carbon Black, Crowdstrike, SentinelOne, Microsoft Sysmon).",N/A,no,N/A diff --git a/blueprints/secops-ai-migration-helper/recommender_curated_community/resources/example_recommendation_curated_community_rules.json b/blueprints/secops-ai-migration-helper/recommender_curated_community/resources/example_recommendation_curated_community_rules.json new file mode 100644 index 0000000..3ea86bf --- /dev/null +++ b/blueprints/secops-ai-migration-helper/recommender_curated_community/resources/example_recommendation_curated_community_rules.json @@ -0,0 +1,46 @@ +[ + { + "ucid": "9901", + "title": "Rare Scripting Software Detected", + "description": "Because powershell and cmd prompt are so closely watched and have so many alarms put up to catch misuse, hackers are starting to avoid using them. This detects scripting tools that are utilised and found in the Event log that aren't approved software by your environment.", + "curated rules": "Applied Threat Intelligence - Curated Prioritization/High Priority Host Indicators/ATI High Priority Rule Match for File IoCs (principal.process.file.sha256),Applied Threat Intelligence - Curated Prioritization/High Priority Host Indicators/ATI High Priority Rule Match for File IoCs (target.process.file.sha256),Applied Threat Intelligence - Curated Prioritization/High Priority Host Indicators/ATI High Priority Rule Match for File IoCs (target.file.sha256),Applied Threat Intelligence - Curated Prioritization/High Priority Host Indicators/ATI High Priority Rule Match for File IoCs (about.file.sha256)", + "curated rules coverage": "very good", + "curated rationale": "The security objective is to detect malicious scripting activity that avoids common tools. The suggested curated rules are part of the 'Applied Threat Intelligence - Curated Prioritization' set and will trigger if the hash of a running process or a file on disk matches a known malicious indicator from Google's threat intelligence. This effectively detects known malicious or rare scripting tools without relying on potentially noisy keyword matching. Log Data Sources: EDR logs such as Microsoft Sysmon (WINDOWS_SYSMON), Crowdstrike Falcon (CS_EDR), SentinelOne (SENTINEL_EDR), Carbon Black (CB_EDR).", + "community rules": "recon_suspicious_commands_cisa_report,mitre_attack_T1140_encoded_powershell_command,gcti_remote_access_tools,recon_environment_enumeration_system_cisa_report,google_safebrowsing_file_process_creation", + "community rules coverage": "very good", + "community rationale": "The selected community rules collectively detect the execution of suspicious or unauthorized tools and scripts, aligning with the input rule's objective. The `recon_suspicious_commands_cisa_report` and `recon_environment_enumeration_system_cisa_report` rules use specific, intelligence-driven command-line patterns to identify a wide range of malicious activities. The `mitre_attack_T1140_encoded_powershell_command` rule targets a common evasion technique used with scripting tools. Furthermore, `gcti_remote_access_tools` and `google_safebrowsing_file_process_creation` leverage threat intelligence feeds to detect known malicious tools by their file hashes, offering a more robust detection method than the input rule's generic keyword matching. Log Data Sources: Microsoft Sysmon, Microsoft Windows Events, CrowdStrike, SentinelOne, Microsoft Defender ATP." + }, + { + "ucid": "9902", + "title": "Rare or Never Seen Events EventID Logged", + "description": "This requires a watchlist of every event ID from this table and one of rare event IDs", + "curated rules": "Risk Analytics for UEBA/New Login by User to Device/First Time Interactive Service Account Login by Principal User ID and Target Service Account", + "curated rules coverage": "partially", + "curated rationale": "The curated rule detects the first time a user interactively logs in with a service account, which aligns with the input rule's objective of identifying new or rare events. While the input rule is generic and looks for any new EventID, the curated rule applies the 'first seen' concept to a specific, high-value security scenario. Log Data Sources: Windows Security Events (WINDOWS_EVENT_LOG), Linux logs (NIX_SYSTEM), or various cloud/SaaS application logs that produce USER_LOGIN events.", + "community rules": "hash_prevalence,domain_prevalence,ip_target_prevalence,network_connection_first_seen_in_past_day,low_prevalence_hash_on_process_launch_low_prevalence_domain_accessed", + "community rules coverage": "very good", + "community rationale": "The input rule's objective is to detect rare or never-before-seen Windows Event IDs, which is a form of anomaly detection based on event frequency. The suggested community rules achieve the same security objective by applying prevalence and first-seen logic to other critical security data points. 'hash_prevalence', 'domain_prevalence', and 'ip_target_prevalence' directly use prevalence calculations to find rare file hashes, domains, and IP addresses, respectively. 'network_connection_first_seen_in_past_day' detects new IP addresses, aligning with the 'never seen' aspect of the input rule. 'low_prevalence_hash_on_process_launch_low_prevalence_domain_accessed' provides a high-fidelity signal by combining two prevalence checks. Collectively, these rules provide robust coverage for detecting rare and potentially malicious activities through anomaly detection. Log Data Sources: EDR logs (e.g., Microsoft Sysmon, CrowdStrike), DNS logs, and Network/Firewall logs (e.g., Zeek, GCP Firewall)." + }, + { + "ucid": "9903", + "title": "New Run/RunOnce Scheduled Task", + "description": "Shell-Core EventID 9706/9707/9708", + "curated rules": "N/A", + "curated rules coverage": "no", + "curated rationale": "No equivalent curated rule was found that specifically detects persistence through the creation or modification of Run/RunOnce registry keys. The provided curated rules focus on IOC matching or high-level UEBA detections like anomalous logins and network traffic, which do not cover this specific persistence technique.", + "community rules": "mitre_attack_T1053_005_windows_creation_of_scheduled_task,suspicious_unusual_location_lnk_file", + "community rules coverage": "partially", + "community rationale": "The input rule detects persistence via Run/RunOnce registry keys (T1547.001). The community rules cover similar persistence objectives. 'mitre_attack_T1053_005_windows_creation_of_scheduled_task' detects the creation of scheduled tasks (T1053.005), another common method for autostart execution. 'suspicious_unusual_location_lnk_file' detects the creation of shortcut files in startup folders, which is also part of the T1547 technique family. While the specific implementation differs, the overall goal of detecting persistence is addressed. Log Data Sources: Microsoft Sysmon, SentinelOne, or other EDR logs providing process launch and file events." + }, + { + "ucid": "9904", + "title": "Unusual binary shutting down endpoint", + "description": "Malware may cause shutdowns on this EID as well as EventID 6006 too", + "curated rules": "Applied Threat Intelligence - Curated Prioritization/Active Breach Priority Host Indicators/ATI Active Breach Rule Match for File IoCs (principal.process.file.sha256),Applied Threat Intelligence - Curated Prioritization/High Priority Host Indicators/ATI High Priority Rule Match for File IoCs (target.file.sha256),Applied Threat Intelligence - Curated Prioritization/Medium Priority Host Indicators/ATI Medium Priority Rule Match for File IoCs (principal.process.file.sha256),Applied Threat Intelligence - Curated Prioritization/Medium Priority Host Indicators/ATI Medium Priority Rule Match for File IoCs (target.file.sha256)", + "curated rules coverage": "very good", + "curated rationale": "The security objective is to detect malware initiating a system shutdown. While there isn't a specific curated rule for the shutdown event (EventID 1074), the Applied Threat Intelligence rules provide excellent coverage by detecting the malicious binary itself based on its file hash when it is executed or written to disk. This often provides an earlier detection of the threat. Log Data Sources: EDR (Carbon Black, Crowdstrike, SentinelOne, Microsoft Sysmon).", + "community rules": "N/A", + "community rules coverage": "no", + "community rationale": "N/A" + } +] \ No newline at end of file diff --git a/blueprints/secops-ai-migration-helper/recommender_curated_community/resources/example_recommendation_curated_rulesets.csv b/blueprints/secops-ai-migration-helper/recommender_curated_community/resources/example_recommendation_curated_rulesets.csv new file mode 100644 index 0000000..a4f10d3 --- /dev/null +++ b/blueprints/secops-ai-migration-helper/recommender_curated_community/resources/example_recommendation_curated_rulesets.csv @@ -0,0 +1,12 @@ +curated rulesSet,curated rule,ucid,title,curated rules coverage,curated rationale +Applied Threat Intelligence - Curated Prioritization/High Priority Host Indicators,Applied Threat Intelligence - Curated Prioritization/High Priority Host Indicators/ATI High Priority Rule Match for File IoCs (principal.process.file.sha256),9901,Rare Scripting Software Detected,very good,"The security objective is to detect malicious scripting activity that avoids common tools. The suggested curated rules are part of the 'Applied Threat Intelligence - Curated Prioritization' set and will trigger if the hash of a running process or a file on disk matches a known malicious indicator from Google's threat intelligence. This effectively detects known malicious or rare scripting tools without relying on potentially noisy keyword matching. Log Data Sources: EDR logs such as Microsoft Sysmon (WINDOWS_SYSMON), Crowdstrike Falcon (CS_EDR), SentinelOne (SENTINEL_EDR), Carbon Black (CB_EDR)." +Applied Threat Intelligence - Curated Prioritization/High Priority Host Indicators,Applied Threat Intelligence - Curated Prioritization/High Priority Host Indicators/ATI High Priority Rule Match for File IoCs (target.process.file.sha256),9901,Rare Scripting Software Detected,very good,"The security objective is to detect malicious scripting activity that avoids common tools. The suggested curated rules are part of the 'Applied Threat Intelligence - Curated Prioritization' set and will trigger if the hash of a running process or a file on disk matches a known malicious indicator from Google's threat intelligence. This effectively detects known malicious or rare scripting tools without relying on potentially noisy keyword matching. Log Data Sources: EDR logs such as Microsoft Sysmon (WINDOWS_SYSMON), Crowdstrike Falcon (CS_EDR), SentinelOne (SENTINEL_EDR), Carbon Black (CB_EDR)." +Applied Threat Intelligence - Curated Prioritization/High Priority Host Indicators,Applied Threat Intelligence - Curated Prioritization/High Priority Host Indicators/ATI High Priority Rule Match for File IoCs (target.file.sha256),9901,Rare Scripting Software Detected,very good,"The security objective is to detect malicious scripting activity that avoids common tools. The suggested curated rules are part of the 'Applied Threat Intelligence - Curated Prioritization' set and will trigger if the hash of a running process or a file on disk matches a known malicious indicator from Google's threat intelligence. This effectively detects known malicious or rare scripting tools without relying on potentially noisy keyword matching. Log Data Sources: EDR logs such as Microsoft Sysmon (WINDOWS_SYSMON), Crowdstrike Falcon (CS_EDR), SentinelOne (SENTINEL_EDR), Carbon Black (CB_EDR)." +Applied Threat Intelligence - Curated Prioritization/High Priority Host Indicators,Applied Threat Intelligence - Curated Prioritization/High Priority Host Indicators/ATI High Priority Rule Match for File IoCs (about.file.sha256),9901,Rare Scripting Software Detected,very good,"The security objective is to detect malicious scripting activity that avoids common tools. The suggested curated rules are part of the 'Applied Threat Intelligence - Curated Prioritization' set and will trigger if the hash of a running process or a file on disk matches a known malicious indicator from Google's threat intelligence. This effectively detects known malicious or rare scripting tools without relying on potentially noisy keyword matching. Log Data Sources: EDR logs such as Microsoft Sysmon (WINDOWS_SYSMON), Crowdstrike Falcon (CS_EDR), SentinelOne (SENTINEL_EDR), Carbon Black (CB_EDR)." +Risk Analytics for UEBA/New Login by User to Device,Risk Analytics for UEBA/New Login by User to Device/First Time Interactive Service Account Login by Principal User ID and Target Service Account,9902,Rare or Never Seen Events EventID Logged,partially,"The curated rule detects the first time a user interactively logs in with a service account, which aligns with the input rule's objective of identifying new or rare events. While the input rule is generic and looks for any new EventID, the curated rule applies the 'first seen' concept to a specific, high-value security scenario. Log Data Sources: Windows Security Events (WINDOWS_EVENT_LOG), Linux logs (NIX_SYSTEM), or various cloud/SaaS application logs that produce USER_LOGIN events." +N/A,N/A,9903,New Run/RunOnce Scheduled Task,no,"No equivalent curated rule was found that specifically detects persistence through the creation or modification of Run/RunOnce registry keys. The provided curated rules focus on IOC matching or high-level UEBA detections like anomalous logins and network traffic, which do not cover this specific persistence technique." +N/A,N/A,9206,Audit Log was deleted on domain controller,no,"No curated rule was found to cover the specific security objective of detecting the clearing of Windows Event Logs (EventID 1102), which is a key defense evasion technique. The provided rules focus on different threat vectors like IOC matching, anomalous network behavior, and authentication anomalies." +Applied Threat Intelligence - Curated Prioritization/Active Breach Priority Host Indicators,Applied Threat Intelligence - Curated Prioritization/Active Breach Priority Host Indicators/ATI Active Breach Rule Match for File IoCs (principal.process.file.sha256),9904,Unusual binary shutting down endpoint,very good,"The security objective is to detect malware initiating a system shutdown. While there isn't a specific curated rule for the shutdown event (EventID 1074), the Applied Threat Intelligence rules provide excellent coverage by detecting the malicious binary itself based on its file hash when it is executed or written to disk. This often provides an earlier detection of the threat. Log Data Sources: EDR (Carbon Black, Crowdstrike, SentinelOne, Microsoft Sysmon)." +Applied Threat Intelligence - Curated Prioritization/High Priority Host Indicators,Applied Threat Intelligence - Curated Prioritization/High Priority Host Indicators/ATI High Priority Rule Match for File IoCs (target.file.sha256),9904,Unusual binary shutting down endpoint,very good,"The security objective is to detect malware initiating a system shutdown. While there isn't a specific curated rule for the shutdown event (EventID 1074), the Applied Threat Intelligence rules provide excellent coverage by detecting the malicious binary itself based on its file hash when it is executed or written to disk. This often provides an earlier detection of the threat. Log Data Sources: EDR (Carbon Black, Crowdstrike, SentinelOne, Microsoft Sysmon)." +Applied Threat Intelligence - Curated Prioritization/Medium Priority Host Indicators,Applied Threat Intelligence - Curated Prioritization/Medium Priority Host Indicators/ATI Medium Priority Rule Match for File IoCs (principal.process.file.sha256),9904,Unusual binary shutting down endpoint,very good,"The security objective is to detect malware initiating a system shutdown. While there isn't a specific curated rule for the shutdown event (EventID 1074), the Applied Threat Intelligence rules provide excellent coverage by detecting the malicious binary itself based on its file hash when it is executed or written to disk. This often provides an earlier detection of the threat. Log Data Sources: EDR (Carbon Black, Crowdstrike, SentinelOne, Microsoft Sysmon)." +Applied Threat Intelligence - Curated Prioritization/Medium Priority Host Indicators,Applied Threat Intelligence - Curated Prioritization/Medium Priority Host Indicators/ATI Medium Priority Rule Match for File IoCs (target.file.sha256),9904,Unusual binary shutting down endpoint,very good,"The security objective is to detect malware initiating a system shutdown. While there isn't a specific curated rule for the shutdown event (EventID 1074), the Applied Threat Intelligence rules provide excellent coverage by detecting the malicious binary itself based on its file hash when it is executed or written to disk. This often provides an earlier detection of the threat. Log Data Sources: EDR (Carbon Black, Crowdstrike, SentinelOne, Microsoft Sysmon)." diff --git a/blueprints/secops-ai-migration-helper/recommender_curated_community/resources/sample_input_rules.json b/blueprints/secops-ai-migration-helper/recommender_curated_community/resources/sample_input_rules.json new file mode 100644 index 0000000..14c3e24 --- /dev/null +++ b/blueprints/secops-ai-migration-helper/recommender_curated_community/resources/sample_input_rules.json @@ -0,0 +1,26 @@ +[ + { + "ucid": "9901", + "title": "Rare Scripting Software Detected", + "description": "Because powershell and cmd prompt are so closely watched and have so many alarms put up to catch misuse, hackers are starting to avoid using them. This detects scripting tools that are utilised and found in the Event log that aren't approved software by your environment.", + "rule": "//ucid: 9901\n// Title of Detection: Rare Scripting Software Detected \n// Authorship & Contact: https://allthingscomputers.medium.com https://twitter.com/allthingshandle https://allthingscomputersblog.wordpress.com/ \n// Description of the Detection: Because powershell and cmd prompt are so closely watched and have so many alarms put up to catch misuse, hackers are starting to avoid using them. This detects scripting tools that are utilised and found in the Event log that aren't approved software by your environment.\n// References (if available): \n// The Logic of the Detection or Query Begins Below This Line\n// Source https://github.com/AllThingsComputers/Sentinel-Rules/blob/main/Event%20Logs/Rare%20Scripting%20Software%20Detected.txt\nEvent\n| where (RenderedDescription matches regex@'(?i)(command|shell|execute|script|console|terminal)' or RenderedDescription matches regex @(?i)(Bash|Ksh|Fish|Korn|ZOC|Cmder|ConEmu|Mintty)') and not(RenderedDescription matches regex (Use a regex of your expected tools in your environment to remove false positives))" + }, + { + "ucid": "9902", + "title": "Rare or Never Seen Events EventID Logged", + "description": "This requires a watchlist of every event ID from this table and one of rare event IDs", + "rule": "//ucid: 9902\n// Title of Detection: Rare or Never Seen Events EventID Logged\n// Authorship & Contact: https://allthingscomputers.medium.com https://twitter.com/allthingshandle https://allthingscomputersblog.wordpress.com/ \n// Description of the Detection: This requires a watchlist of every event ID from this table and one of rare event IDs\n// References (if available): \n// The Logic of the Detection or Query Begins Below This Line\n// Source https://github.com/AllThingsComputers/Sentinel-Rules/blob/main/Event%20Logs/Rare%20or%20Never%20Seen%20Events%20EventID%20Logged.txt\nlet time_until = 1d;\nlet SentinelWatchlistOfEveryEIDEver = (_GetWatchlist('AllSeenEventIDsFromEventsLog') | project SearchKey);\nlet rarewatchlist = (_GetWatchlist('WatchlistOfRareEventsEventIDs') | project SearchKey);\nlet EveryEventIDSinceWatchlistCreation = (Event\n| where TimeGenerated between (datetime(2022-07-19T20:00:00)..ago(time_until))\n| summarize by EventID);\nlet RecentRareEventIDs = (Event\n| where TimeGenerated between (ago(90d)..ago(time_until))\n| summarize count() by EventID\n| where count_ <= 1); // Adjust sensitivity\nEvent\n| where TimeGenerated >= ago(1h)\n| extend NewEvent = iff(EventID !in (SentinelWatchlistOfEveryEIDEver.SearchKey) \n and EventID !in (EveryEventIDSinceWatchlistCreation.EventID), \"EID is New\", \"EID is Not New\")\n| extend RareEvent = iff(EventID in (rarewatchlist.SearchKey) \n or EventID in (RecentRareEventIDs.EventID), \"EID is Rare\", \"EID is Not Rare\")\n| where NewEvent == \"EID is New\" or RareEvent == \"EID is Rare\"\n| project TimeGenerated, EventID, NewEvent, RareEvent\n| project-reorder NewEvent, RareEvent" + }, + { + "ucid": "9903", + "title": "New Run/RunOnce Scheduled Task", + "description": "Shell-Core EventID 9706/9707/9708", + "rule": "//ucid: 9903\n// Title of Detection: New Run/RunOnce Scheduled Task\n// Authorship & Contact: https://allthingscomputers.medium.com https://twitter.com/allthingshandle https://allthingscomputersblog.wordpress.com/ \n// Description of the Detection: Shell-Core EventID 9706/9707/9708 \n// References (if available): https://blog.menasec.net/2019/02/threat-hunting-20-runrunonce-EventID.html \n// The Logic of the Detection or Query Begins Below This Line\n// Source https://github.com/AllThingsComputers/Sentinel-Rules/blob/main/Event%20Logs/New%20Run%20or%20RunOnce%20Scheduled%20Task.txt\nEvent\n| where EventID in (12, 13)\n| where ParameterXml matches regex @\"(?i)HK(LM|CU)\\\\.*(\\\\Run\\\\|\\\\RunOnce\\\\).*?<\"\n| extend RunRunonce = trim_end('<', extract(@\"(?i)(HK(LM|CU)\\\\.*(\\\\Run\\\\|\\\\RunOnce\\\\).*?)<\", 1, ParameterXml))\n| where not(RunRunonce matches regex @\"(?i)\\\\{[\\w-]{36}\\\\}exclusions\")" + }, + { + "ucid": "9904", + "title": "Unusual binary shutting down endpoint", + "description": "Malware may cause shutdowns on this EID as well as EventID 6006 too", + "rule": "//ucid: 9904\n// Title of Detection: Unusual binary shutting down endpoint\n// Authorship & Contact: https://allthingscomputers.medium.com https://twitter.com/allthingshandle https://allthingscomputersblog.wordpress.com/ \n// Description of the Detection: Malware may cause shutdowns on this EID as well as EventID 6006 too\n// References (if available): https://attack.mitre.org/techniques/T1529/\n// The Logic of the Detection or Query Begins Below This Line\nEvent\n| where EventID == 1074\n| where Description contains \"has initiated the shutdown\"\n| where not(Description matches regex @\"(expected Process Shutting Down Computer)\")" + } +] \ No newline at end of file diff --git a/blueprints/secops-ai-migration-helper/recommender_curated_community/resources/sample_unstructured_input.csv b/blueprints/secops-ai-migration-helper/recommender_curated_community/resources/sample_unstructured_input.csv new file mode 100644 index 0000000..3324006 --- /dev/null +++ b/blueprints/secops-ai-migration-helper/recommender_curated_community/resources/sample_unstructured_input.csv @@ -0,0 +1,58 @@ +Rule Conditions +"//ucid: 9901 +// Title of Detection: Rare Scripting Software Detected +// Authorship & Contact: https://allthingscomputers.medium.com https://twitter.com/allthingshandle https://allthingscomputersblog.wordpress.com/ +// Description of the Detection: Because powershell and cmd prompt are so closely watched and have so many alarms put up to catch misuse, hackers are starting to avoid using them. This detects scripting tools that are utilised and found in the Event log that aren't approved software by your environment. +// References (if available): +// The Logic of the Detection or Query Begins Below This Line +// Source https://github.com/AllThingsComputers/Sentinel-Rules/blob/main/Event%20Logs/Rare%20Scripting%20Software%20Detected.txt +Event +| where (RenderedDescription matches regex@'(?i)(command|shell|execute|script|console|terminal)' or RenderedDescription matches regex @(?i)(Bash|Ksh|Fish|Korn|ZOC|Cmder|ConEmu|Mintty)') and not(RenderedDescription matches regex (Use a regex of your expected tools in your environment to remove false positives))" +"//ucid: 9902 +// Title of Detection: Rare or Never Seen Events EventID Logged +// Authorship & Contact: https://allthingscomputers.medium.com https://twitter.com/allthingshandle https://allthingscomputersblog.wordpress.com/ +// Description of the Detection: This requires a watchlist of every event ID from this table and one of rare event IDs +// References (if available): +// The Logic of the Detection or Query Begins Below This Line +// Source https://github.com/AllThingsComputers/Sentinel-Rules/blob/main/Event%20Logs/Rare%20or%20Never%20Seen%20Events%20EventID%20Logged.txt +let time_until = 1d; +let SentinelWatchlistOfEveryEIDEver = (_GetWatchlist('AllSeenEventIDsFromEventsLog') | project SearchKey); +let rarewatchlist = (_GetWatchlist('WatchlistOfRareEventsEventIDs') | project SearchKey); +let EveryEventIDSinceWatchlistCreation = (Event +| where TimeGenerated between (datetime(2022-07-19T20:00:00)..ago(time_until)) +| summarize by EventID); +let RecentRareEventIDs = (Event +| where TimeGenerated between (ago(90d)..ago(time_until)) +| summarize count() by EventID +| where count_ <= 1); // Adjust sensitivity +Event +| where TimeGenerated >= ago(1h) +| extend NewEvent = iff(EventID !in (SentinelWatchlistOfEveryEIDEver.SearchKey) + and EventID !in (EveryEventIDSinceWatchlistCreation.EventID), ""EID is New"", ""EID is Not New"") +| extend RareEvent = iff(EventID in (rarewatchlist.SearchKey) + or EventID in (RecentRareEventIDs.EventID), ""EID is Rare"", ""EID is Not Rare"") +| where NewEvent == ""EID is New"" or RareEvent == ""EID is Rare"" +| project TimeGenerated, EventID, NewEvent, RareEvent +| project-reorder NewEvent, RareEvent" +"//ucid: 9903 +// Title of Detection: New Run/RunOnce Scheduled Task +// Authorship & Contact: https://allthingscomputers.medium.com https://twitter.com/allthingshandle https://allthingscomputersblog.wordpress.com/ +// Description of the Detection: Shell-Core EventID 9706/9707/9708 +// References (if available): https://blog.menasec.net/2019/02/threat-hunting-20-runrunonce-EventID.html +// The Logic of the Detection or Query Begins Below This Line +// Source https://github.com/AllThingsComputers/Sentinel-Rules/blob/main/Event%20Logs/New%20Run%20or%20RunOnce%20Scheduled%20Task.txt +Event +| where EventID in (12, 13) +| where ParameterXml matches regex @""(?i)HK(LM|CU)\\.*(\\Run\\|\\RunOnce\\).*?<"" +| extend RunRunonce = trim_end('<', extract(@""(?i)(HK(LM|CU)\\.*(\\Run\\|\\RunOnce\\).*?)<"", 1, ParameterXml)) +| where not(RunRunonce matches regex @""(?i)\{[\w-]{36}\}exclusions"")" +"//ucid: 9904 +// Title of Detection: Unusual binary shutting down endpoint +// Authorship & Contact: https://allthingscomputers.medium.com https://twitter.com/allthingshandle https://allthingscomputersblog.wordpress.com/ +// Description of the Detection: Malware may cause shutdowns on this EID as well as EventID 6006 too +// References (if available): https://attack.mitre.org/techniques/T1529/ +// The Logic of the Detection or Query Begins Below This Line +Event +| where EventID == 1074 +| where Description contains ""has initiated the shutdown"" +| where not(Description matches regex @""(expected Process Shutting Down Computer)"")" diff --git a/blueprints/secops-ai-migration-helper/recommender_curated_community/run_recommender.sh b/blueprints/secops-ai-migration-helper/recommender_curated_community/run_recommender.sh new file mode 100755 index 0000000..c8d8441 --- /dev/null +++ b/blueprints/secops-ai-migration-helper/recommender_curated_community/run_recommender.sh @@ -0,0 +1,121 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +#!/bin/bash + +# ============================================================================== +# SecOps AI Rule Recommendation Helper +# ============================================================================== + +# Save original directory and arguments +ORIGINAL_PWD=$(pwd) +ARG_PATH="$1" + +# If argument provided, resolve to absolute path (if relative) before we cd +if [[ -n "$ARG_PATH" ]]; then + if [[ "$ARG_PATH" != /* ]]; then + ARG_PATH="$ORIGINAL_PWD/$ARG_PATH" + fi +fi + +# 1. Verification & Setup + +# Set the working directory to ./recommender_curated_community +if [ -d "./recommender_curated_community" ]; then + echo "Moving to recommender_curated_community directory..." + cd "./recommender_curated_community" || { echo "Error: Failed to enter directory ./recommender_curated_community"; exit 1; } +elif [ -f "recommender_curated_community.py" ]; then + echo "Notice: Already in recommender_curated_community directory." +else + echo "Error: Directory ./recommender_curated_community not found and recommender_curated_community.py not found in current directory." + echo "Please run this script from the project root." + exit 1 +fi + +# Confirm authentication +read -p "Have you authenticated to Google Cloud (gcloud auth application-default login)? [Y/n]: " auth_confirm +auth_confirm="${auth_confirm:-y}" +if [[ "$auth_confirm" != "y" && "$auth_confirm" != "Y" ]]; then + echo "Please run:gcloud auth application-default login" + exit 1 +fi + +# Check default project +CURRENT_PROJECT=$(gcloud config get-value project 2>/dev/null) +if [[ -z "$CURRENT_PROJECT" ]]; then + echo "Default GCP project is not configured." + read -p "Please enter your GCP Project ID to set it: " prompt_project + if [[ -z "$prompt_project" ]]; then + echo "Error: Project ID is required." + exit 1 + fi + gcloud config set project "$prompt_project" +else + echo "Default GCP project is configured: $CURRENT_PROJECT" +fi + +# Check env vars +check_env_var() { + local var_name=$1 + if [[ -z "${!var_name}" ]]; then + read -p "$var_name is missing. Please enter its value: " var_val + if [[ -z "$var_val" ]]; then + echo "Error: $var_name is required." + exit 1 + fi + export "$var_name"="$var_val" + fi +} + +check_env_var "CONTENTHUB_PROJECT_ID" +check_env_var "CONTENTHUB_LOCATION" +check_env_var "CONTENTHUB_INSTANCE_ID" + +# Activate venv if exists +if [ -d ".venv" ]; then + echo "Found local virtual environment .venv. Activating..." + source .venv/bin/activate +fi + +# Check requirements +if [[ -f "requirements.txt" ]]; then + echo "Checking/Installing requirements..." + python3 -m pip install -r requirements.txt +else + echo "Warning: requirements.txt not found." +fi + +# 2. Execution Preparation + +if [[ -z "$ARG_PATH" ]]; then + echo "Error: Path to customer rules JSON file is missing." + read -p "Please provide the path to the JSON file: " prompt_file + ARG_PATH="$prompt_file" + if [[ -z "$ARG_PATH" ]]; then + echo "Error: JSON file path is required." + exit 1 + fi +fi + +if [[ ! -f "$ARG_PATH" ]]; then + echo "Error: File not found at '$ARG_PATH'" + exit 1 +fi + +export CUSTOMER_RULES_TO_EVALUATE="$ARG_PATH" + +# 3. Execution + +echo "Executing recommender_curated_community.py..." +python3 recommender_curated_community.py diff --git a/blueprints/secops-ai-migration-helper/recommender_curated_community/secops_resources_helper.py b/blueprints/secops-ai-migration-helper/recommender_curated_community/secops_resources_helper.py new file mode 100644 index 0000000..32950b0 --- /dev/null +++ b/blueprints/secops-ai-migration-helper/recommender_curated_community/secops_resources_helper.py @@ -0,0 +1,215 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from secops import SecOpsClient +from google.auth.exceptions import DefaultCredentialsError +import os +import json +import re +import sys +import csv +import subprocess + + +def get_chronicle_client(project_id, location, instance_id): + print( + "Attempting to authenticate using Application Default Credentials with secops SDK..." + ) + + try: + client = SecOpsClient() + chronicle = client.chronicle(customer_id=instance_id, + project_id=project_id, + region=location) + print("Successfully obtained credentials.") + return chronicle + except DefaultCredentialsError: + print("\n--- Authentication Failed ---") + print( + "Please run the following command in your terminal to authenticate:" + ) + print("gcloud auth application-default login") + return None + except Exception as e: + print(f"Error: {e}") + return None + + +def get_curated_rule_sets(chronicle_client): + print(f"\nFetching curated rule sets using secops SDK...") + try: + result = chronicle_client.list_curated_rule_sets(as_list=True) + print(f"Fetched rule sets") + return {"curatedRuleSets": result} + except Exception as e: + print(f"\n--- An Unexpected Error Occurred ---") + print(f"Error: {e}") + return {"curatedRuleSets": []} + + +def get_featured_content_rules(chronicle_client): + """ + Calls the Google Chronicle API to fetch all featured content rules using the secops SDK, + authenticating using Application Default Credentials (ADC), and returns + the results to a JSON. + """ + print(f"\nFetching featured content rules using secops SDK...") + try: + all_rules = chronicle_client.list_featured_content_rules(as_list=True) + print(f"Fetched {len(all_rules)} featured content rules.") + return all_rules + except Exception as e: + print(f"\n--- An Unexpected Error Occurred ---") + print(f"Error: {e}") + return [] + + +# Adding to curated rules the log source extracted from the description of the ruleSet, aka merging +def add_log_sources_to_curated_list(all_curated_ruleset, all_curated_rules): + rule_set_lookup = { + rule_set['name']: rule_set.get('logSources', []) + for rule_set in all_curated_ruleset.get('curatedRuleSets', []) + } + + # Iterate through each rule in the first data set + for rule in all_curated_rules: + # Check if the rule has the necessary structure + if 'ruleSet' in rule and 'curatedRuleSet' in rule['ruleSet']: + rule_set_key = rule['ruleSet']['curatedRuleSet'] + + # Find the matching rule set in our lookup dictionary + if rule_set_key in rule_set_lookup: + # Add the 'logSources' to the rule's 'ruleSet' object + rule['ruleSet']['logSources'] = rule_set_lookup[rule_set_key] + + return all_curated_rules + + +# Extract the unique log sources from the rulesSets +def get_unique_log_sources(parsed_data) -> list[str]: + """ + Parses extract a unique list of logSources. + + Args: + data: JSON data. + + Returns: + A list of unique log source strings. + """ + + # Use a set to automatically handle uniqueness of log sources + unique_sources = set() + + # Iterate through each rule set in the 'curatedRuleSets' list + # .get() is used to avoid errors if 'curatedRuleSets' key is missing + for rule_set in parsed_data.get("curatedRuleSets", []): + # Extend the set with the list of log sources for the current rule set + # .get() is used to avoid errors if 'logSources' key is missing + for source in rule_set.get("logSources", []): + splited_values = source.split( + "," + ) # bug in the documentaiton somce values are one string comma separated + for s in splited_values: + unique_sources.add(s.strip()) + + # Convert the set to a list and return it + return sorted(list(unique_sources)) + + +def filter_curated_rules_log_source(log_sources, allrules): + """ + Filters the all curated list only to provided log sources + """ + filtered_data = [ + element for element in allrules + if 'ruleSet' in element and 'logSources' in element['ruleSet'] and + (any(source in element['ruleSet']['logSources'] + for source in log_sources) or not element['ruleSet']['logSources'] + or "N/A" in element['ruleSet']['logSources']) + ] + + return filtered_data + + +def write_results_file(recommendation_curated_community, + recommendations_json_output_file, + recommendations_csv_output_file, + recommendations_ruleset_csv_output_file): + """ + Export the result to file + """ + # Saving to files + # Export the result to JSON + with open(recommendations_json_output_file, 'w') as f: + json.dump(recommendation_curated_community, f, indent=2) + print( + f"Successfully saved recommendations to {recommendations_json_output_file}" + ) + + # Export the results to CSV + with open(recommendations_csv_output_file, 'w', newline='') as csvfile: + fieldnames = [ + 'ucid', 'title', 'description', 'curated rules', + 'curated rules coverage', 'curated rationale', 'community rules', + 'community rules coverage', 'community rationale' + ] + writer = csv.DictWriter(csvfile, fieldnames=fieldnames) + + writer.writeheader() + + for row in recommendation_curated_community: + writer.writerow(row) + + print( + f"JSON data converted to CSV and saved to {recommendations_csv_output_file}" + ) + + # Generate reverse mapping RuleSet to customer rule + + with open(recommendations_ruleset_csv_output_file, 'w', + newline='') as csvfile: + fieldnames = [ + 'curated rulesSet', 'curated rule', 'ucid', 'title', + 'curated rules coverage', 'curated rationale' + ] + writer = csv.DictWriter(csvfile, fieldnames=fieldnames) + writer.writeheader() + + for row in recommendation_curated_community: + curated_rules = row.get('curated rules', '').split(',') + for curated_rule in curated_rules: + # Extracting ruleSet and rule name from the format "category/ruleset/rule name" + parts = curated_rule.strip().split('/') + curated_ruleset = f"{parts[0]}/{parts[1]}" if len( + parts) > 1 else 'N/A' + rule_name = parts[-1] if parts else 'N/A' + + writer.writerow({ + 'curated rulesSet': + curated_ruleset, + 'curated rule': + curated_rule, + 'ucid': + row.get('ucid', 'N/A'), + 'title': + row.get('title', 'N/A'), + 'curated rules coverage': + row.get('curated rules coverage', 'N/A'), + 'curated rationale': + row.get('curated rationale', 'N/A') + }) + + print( + f"Successfully converted rule sets recommendations to CSV and saved to {recommendations_ruleset_csv_output_file}" + ) diff --git a/blueprints/secops-ai-migration-helper/recommender_curated_community/work_dir/.gitkeep b/blueprints/secops-ai-migration-helper/recommender_curated_community/work_dir/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/blueprints/secops-ai-migration-helper/rules/demo_arcsight_7004/demo_arcsight_7004.yaral b/blueprints/secops-ai-migration-helper/rules/demo_arcsight_7004/demo_arcsight_7004.yaral new file mode 100644 index 0000000..d1b9f29 --- /dev/null +++ b/blueprints/secops-ai-migration-helper/rules/demo_arcsight_7004/demo_arcsight_7004.yaral @@ -0,0 +1,117 @@ +rule demo_arcsight_7004 { +/* + +SOURCE: Intergalactic SOC +RULE PARAMETERS: + - Target Log Type: NETWORK_CONNECTION (e.g., FIREWALL, PROXY, WAF) + - Target Activity: Detects inbound network traffic originating from known Tor exit nodes. + +DEPENDENCIES: + - Log Source: Firewall, Proxy, or WAF logs providing network connection data. + - UDM Fields: + - metadata.event_type + - network.direction + - principal.ip + - target.ip + - target.port + - network.application_protocol + - metadata.product_name + - metadata.vendor_name + - metadata.product_event_type + +TUNING: + - Potential False Positives: Legitimate traffic from Tor users accessing company services or applications. + - Further Tuning: Adjust the 'Tor_Exit_Nodes' reference list for currency, or add exclusions for known-good internal or external source IPs if necessary. + +TESTING: + - Simulate Alert: Generate network traffic logs where 'network.direction' is 'INBOUND' and the 'principal.ip' exists in the 'Tor_Exit_Nodes' reference list. + +DOCS: + - External Reference: https://attack.mitre.org/techniques/T1090/003/ + +NOTES: + - Rationale for Severity: Tor is often used by threat actors for anonymization. Inbound traffic from Tor exit nodes is anomalous and warrants immediate investigation to determine intent. + +SOURCE RULE: + ``` + # Rule: Correlating Tor Sources in Events + + This is a rule that detects incoming network traffic where the source IP address matches a known Tor exit node stored in an Active List. + + ## RuleId + + 7004 + + + ## Matching + + 1 event + + ## Conditions + + (InZone( + event1.,/All Filters/Default Filters/Network/Perimeter/Inbound Traffic)) + And + (InActiveList( + event1.sourceAddress,/All Active Lists/Tor/Tor Exit Nodes)) + + ## Grouped By: + + event1.sourceAddress, event1.destinationAddress, event1.deviceProduct, event1.deviceVendor, event1.destinationPort, event1.applicationProtocol, event1.deviceEventClassId + + ## Execute actions + ### On First Event + · SendToConsole( ) + · Set Severity High + · SetEventField( name, Anonymizer Traffic - Tor Exit Node Detected) + · SetEventField( categoryBehavior, /Communicate/Anonymized) + + ## Source + + [https://medium.com/analytics-vidhya/correlating-tor-sources-in-arcsight-siem-events-using-python-92750617227a](https://medium.com/analytics-vidhya/correlating-tor-sources-in-arcsight-siem-events-using-python-92750617227a) + ``` +*/ + meta: + author = "Google Professional Services" + description = "This is a rule that detects incoming network traffic where the source IP address matches a known Tor exit node stored in an Active List." + title = "Correlating Tor Sources in Events" + mitre_attack_tactic = "TA0001" // Initial Access - assuming Tor is used for initial access + mitre_attack_technique = "T1090.003" // Proxy: Multi-hop Proxy - Tor is a multi-hop proxy + mitre_attack_url = "https://attack.mitre.org/techniques/T1090/003/" + mitre_attack_version = "v14.1" + old_ucid = "7004" + secops_ucid = "7004" + type = "Alert" + data_source = "IIS" // Depends on what log source provides network events + responsible = "SOC1" + creation_date = "" // Source rule does not specify a creation date + last_rework_date = "18.03.2026" + severity = "High" + status = "prototype" + version = "0.5" + + events: + // This rule looks for inbound network traffic from a source IP that is in the Tor exit node list. + // The Arcsight 'InZone' condition for inbound traffic is represented here by checking network direction. + // The 'InActiveList' is represented by a check against a reference in 'Tor_Exit_Nodes'. + $e.metadata.event_type = "NETWORK_CONNECTION" + $e.network.direction = "INBOUND" + $e.principal.ip in %Tor_Exit_Nodes.ip + + match: + // The grouping from the Arcsight rule is used for the match condition. + $sourceAddress over 5m + + outcome: + // The outcome variables are based on the grouping fields in the Arcsight rule. + $Source_ip = array_distinct($e.principal.ip) + $Target_ip = array_distinct($e.target.ip) + $Product_name = array_distinct($e.metadata.product_name) + $Vendor_name = array_distinct($e.metadata.vendor_name) + $Target_port = array_distinct($e.target.port) + $Protocol = array_distinct($e.network.application_protocol) + $Event_id = array_distinct($e.metadata.product_event_type) + + condition: + $e +} \ No newline at end of file diff --git a/blueprints/secops-ai-migration-helper/rules/demo_arcsight_7004/sample_logs/IIS.log b/blueprints/secops-ai-migration-helper/rules/demo_arcsight_7004/sample_logs/IIS.log new file mode 100644 index 0000000..55f7ad6 --- /dev/null +++ b/blueprints/secops-ai-migration-helper/rules/demo_arcsight_7004/sample_logs/IIS.log @@ -0,0 +1 @@ +2026-03-18 10:00:00 192.168.1.100 GET /index.html - 80 - 185.220.101.70 "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.88 Safari/537.36" - 200 0 0 50 \ No newline at end of file diff --git a/blueprints/secops-ai-migration-helper/rules/demo_kql_9102/demo_kql_9102.yaral b/blueprints/secops-ai-migration-helper/rules/demo_kql_9102/demo_kql_9102.yaral new file mode 100644 index 0000000..f1e5c32 --- /dev/null +++ b/blueprints/secops-ai-migration-helper/rules/demo_kql_9102/demo_kql_9102.yaral @@ -0,0 +1,119 @@ +rule demo_kql_9102 { +/* + +SOURCE: Intergalactic SOC +RULE PARAMETERS: + - Target Log Type: Windows Event Logs + - Target Activity: Detection of newly seen or rare Windows event IDs based on established watchlists. + +DEPENDENCIES: + - Log Source: Windows Event Log (WINEVTLOG) + - UDM Fields: + - metadata.product_event_type + - metadata.vendor_name + - metadata.product_name + - principal.hostname + - principal.user.userid + +TUNING: + - Potential False Positives: New legitimate event IDs resulting from system updates or new application deployments. + - Further Tuning: Regularly update the '%AllSeenEventIDsFromEventsLog' data table to include common, non-malicious event IDs. + +TESTING: + - Simulate Alert: Generate a Windows event with an Event ID that is not present in the '%AllSeenEventIDsFromEventsLog' data table or one that is explicitly added to the '%WatchlistOfRareEventsEventIDs' table. + +DOCS: + - External Reference: https://github.com/AllThingsComputers/Sentinel-Rules/blob/main/Event%20Logs/Rare%20or%20Never%20Seen%20Events%20EventID%20Logged.txt + +NOTES: + - Rationale for Severity: The detection of unobserved or rare event IDs can indicate defensive evasion or unauthorized activity, but it also has a high potential for false positives in dynamic environments, hence a "Medium" severity. + +SOURCE RULE: + // ucid: 9102 + // Title of Detection: Rare or Never Seen Events EventID Logged + // Authorship & Contact: https://allthingscomputers.medium.com https://twitter.com/allthingshandle https://allthingscomputersblog.wordpress.com/ + // Description of the Detection: This requires a watchlist of every event ID from this table and one of rare event IDs + // References (if available): + // The Logic of the Detection or Query Begins Below This Line + // Source https://github.com/AllThingsComputers/Sentinel-Rules/blob/main/Event%20Logs/Rare%20or%20Never%20Seen%20Events%20EventID%20Logged.txt + + let time_until = 1d; + let SentinelWatchlistOfEveryEIDEver = (_GetWatchlist('AllSeenEventIDsFromEventsLog') | project SearchKey); + let rarewatchlist = (_GetWatchlist('WatchlistOfRareEventsEventIDs') | project SearchKey); + + let EveryEventIDSinceWatchlistCreation = ( + Event + | where TimeGenerated between (datetime(2022-07-19T20:00:00)..ago(time_until)) + | summarize by EventID + ); + + let RecentRareEventIDs = ( + Event + | where TimeGenerated between (ago(90d)..ago(time_until)) + | summarize count() by EventID + | where count_ <= 1 + ); // Adjust sensitivity + + Event + | where TimeGenerated >= ago(1h) + | extend NewEvent = iff( + EventID !in (SentinelWatchlistOfEveryEIDEver.SearchKey) + and EventID !in (EveryEventIDSinceWatchlistCreation.EventID), + "EID is New", + "EID is Not New" + ) + | extend RareEvent = iff( + EventID in (rarewatchlist.SearchKey) + or EventID in (RecentRareEventIDs.EventID), + "EID is Rare", + "EID is Not Rare" + ) + | where NewEvent == "EID is New" or RareEvent == "EID is Rare" + | project TimeGenerated, EventID, NewEvent, RareEvent + | project-reorder NewEvent, RareEvent +*/ + meta: + author = "Google Professional Services" + description = "Detects Windows Event IDs that are either newly seen or exist in a rare event ID watchlist." + title = "Rare or Never Seen Windows Event ID Logged" + mitre_attack_tactic = "TA0005" + mitre_attack_technique = "T1070" + mitre_attack_url = "https://attack.mitre.org/techniques/T1070/" + mitre_attack_version = "v1.0" + old_ucid = "9102" + secops_ucid = "9102" + version = "1.0" + type = "Alert" + data_source = "Windows" + severity = "Medium" + status = "prototype" + responsible = "SOC1" + creation_date = "2026-03-17" + last_rework_date = "" + + events: + $e.metadata.vendor_name = "Microsoft" + $e.metadata.product_name = "Windows" + $event_id = $e.metadata.product_event_type + + // Logic: Trigger if Event ID is NOT in the 'all seen' list OR IS in the 'rare' list + ( + not $event_id in %AllSeenEventIDsFromEventsLog.SearchKey + or + $event_id in %WatchlistOfRareEventsEventIDs.SearchKey + ) + + match: + $event_id over 1h + + outcome: + $Count_logs = count_distinct($e.metadata.id) + $Source_user = array_distinct($e.principal.user.userid) + $Source_hostname = array_distinct($e.principal.hostname) + $Event_id = array_distinct($e.metadata.product_event_type) + $Product_name = array_distinct($e.metadata.product_name) + $Vendor_name = array_distinct($e.metadata.vendor_name) + + condition: + $e +} \ No newline at end of file diff --git a/blueprints/secops-ai-migration-helper/rules/demo_kql_9102/sample_logs/WINEVTLOG.log b/blueprints/secops-ai-migration-helper/rules/demo_kql_9102/sample_logs/WINEVTLOG.log new file mode 100644 index 0000000..64a9770 --- /dev/null +++ b/blueprints/secops-ai-migration-helper/rules/demo_kql_9102/sample_logs/WINEVTLOG.log @@ -0,0 +1,27 @@ +<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event"> + <System> + <Provider Name="Microsoft-Windows-Security-Auditing" Guid="{54849625-5478-4994-A5BA-3E3B0328C30D}" /> + <EventID>9102</EventID> + <Version>0</Version> + <Level>4</Level> + <Task>12290</Task> + <Opcode>0</Opcode> + <Keywords>0x8020000000000000</Keywords> + <TimeCreated SystemTime="2026-03-17T10:15:30.9876543Z" /> + <EventRecordID>123456</EventRecordID> + <Correlation /> + <Execution ProcessID="4" ThreadID="100" /> + <Channel>Security</Channel> + <Computer>WIN-DC-01.example.com</Computer> + <Security /> + </System> + <EventData> + <Data Name="SubjectUserSid">S-1-5-18</Data> + <Data Name="SubjectUserName">WIN-DC-01$</Data> + <Data Name="SubjectDomainName">EXAMPLE</Data> + <Data Name="SubjectLogonId">0x3e7</Data> + <Data Name="TargetUserName">rareuser</Data> + <Data Name="TargetDomainName">EXAMPLE</Data> + <Data Name="TargetSid">S-1-5-21-123456789-012345678-901234567-5000</Data> + </EventData> +</Event> \ No newline at end of file diff --git a/blueprints/secops-ai-migration-helper/rules/rule_01234_azure_unusual_cluster_failed_logins_geo/rule_01234_azure_unusual_cluster_failed_logins_geo.yaral b/blueprints/secops-ai-migration-helper/rules/rule_01234_azure_unusual_cluster_failed_logins_geo/rule_01234_azure_unusual_cluster_failed_logins_geo.yaral new file mode 100644 index 0000000..6beeca7 --- /dev/null +++ b/blueprints/secops-ai-migration-helper/rules/rule_01234_azure_unusual_cluster_failed_logins_geo/rule_01234_azure_unusual_cluster_failed_logins_geo.yaral @@ -0,0 +1,103 @@ +rule rule_01234_azure_unusual_cluster_failed_logins_geo { + /* +SOURCE: DEMO SOC + +PARAMETER: + - none + + Dependencies: + - UDM fields: principal.location.city, security_result.action, security_result.detection_fields["riskState"] + +TUNING: + - Time window for clustering: The '24h' in the 'match' section can be adjusted to change the time window for clustering failed logins by city. + - Risk State: The regex '/atRisk|COMPROMISED/' in the 'events' section can be modified to include or exclude specific risk states. + +TESTING: + - Sample Logs: Use 'sample_logs/AZURE_AD_SIGNIN.log' to test the rule. + - Expected Behavior: The rule should trigger when there are multiple failed login attempts from the same city within a 24-hour period, where the login attempts have a 'riskState' of 'atRisk' or 'COMPROMISED'. + - Verification: Ensure that the 'principal.location.city' field is correctly mapped in the UDM events from the sample logs. + +DOCS: + - MITRE ATT&CK: + - Tactic: TA0001 (Initial Access) + - Technique: T1003.002 (OS Credential Dumping: Security Account Manager) + - URL: https://attack.mitre.org/versions/v17/techniques/T1003/ +NOTES: + - Original KQL rule: + "//ucid: 01234 + //author: Test Musterman + //title: Cluster of Failed Logins from same Geo + //severity: Medium + //description: This rule looks for multiple logins from single geo like City + //technique: T1003.002 + //contributor: + + //3 or more different account risky/failed logins from a single geo location + //and where those accounts haven't logged in successfully from that geo location in the last week + //CityWhitelist is pre-identified list of cities where there is high levels of legitimate traffic + let CityWhitelistDyn = CityWhitelist + | summarize make_set(CityName); + let FailedLogins = SigninLogs + | where TimeGenerated > ago(1d) + | where RiskState in~ (\"confirmedCompromised\", \"atRisk\") + | extend City = tostring(LocationDetails.city) + | where City !in (CityWhitelistDyn) + | summarize Users=make_set(tostring(Identity)), count() by City + | where isnotempty(City) + | where array_length(Users) > 3 + ;//FailedLogins + //below query dynamically creates list of additional cities that can be excluded + SigninLogs + | where TimeGenerated > ago(1d) + | where ResultType == \"0\" + | summarize Users=make_set(tostring(Identity)), CityCount = count() by City=tostring(LocationDetails.city) + | where isnotempty(City) + | where CityCount > 50 or array_length(Users) > 10 + | join kind=rightanti FailedLogins on City + | project City, tostring(atRiskUsers=Users), UserCount=array_length(Users) + + Summarize this table + + - Current YARA-L implementation focuses on clustering failed login events by `principal.location.city` and filtering by `security_result.action = "BLOCK"` and `security_result.detection_fields["riskState"]` matching 'atRisk' or 'COMPROMISED'. + */ + + + meta: + author = "Google Professional Services" + description = "This rule looks for multiple logins from single geo like City + title = "Cluster of Failed Logins from same Geo" + responsible = "SOC1" + creation_date = "16.07.2025" + last_rework_date = "16.07.2025" + old_ucid = "21c1233" + secops_ucid = "01234" + version = "0.5" + mitre_attack_tactic = "2.2" + mitre_attack_technique = "T1003.002" + mitre_attack_url = "https://attack.mitre.org/versions/v17/techniques/T1003/" + mitre_attack_version = "" + type = "Alert" + data_source = "Azure" + severity = "Medium" + status = "prototype" + + events: + $failure.metadata.event_type = "USER_LOGIN" + $failure.security_result.action = "BLOCK" + $uid = $failure.target.user.userid + $failure.security_result.detection_fields["riskState"] = /atRisk|COMPROMISED/ nocase + $city = $failure.principal.location.city + + match: + $city over 24h + + outcome: + $risk_score = 35 + $Count_logs = count_distinct($failure.metadata.id) + $Source_user = array_distinct($failure.target.user.userid) + $Location = array_distinct($failure.principal.location.city) + + condition: + $failure + +} diff --git a/blueprints/secops-ai-migration-helper/rules/rule_01234_azure_unusual_cluster_failed_logins_geo/sample_logs/AZURE_AD_SIGNIN.log b/blueprints/secops-ai-migration-helper/rules/rule_01234_azure_unusual_cluster_failed_logins_geo/sample_logs/AZURE_AD_SIGNIN.log new file mode 100644 index 0000000..b48dbce --- /dev/null +++ b/blueprints/secops-ai-migration-helper/rules/rule_01234_azure_unusual_cluster_failed_logins_geo/sample_logs/AZURE_AD_SIGNIN.log @@ -0,0 +1,3 @@ +{"metadata":{"event_type":"USER_LOGIN"},"security_result":{"action":"BLOCK","detection_fields":{"riskState":"atRisk"}},"target":{"user":{"userid":"user1@example.com"}},"principal":{"location":{"city":"London"}}} +{"metadata":{"event_type":"USER_LOGIN"},"security_result":{"action":"BLOCK","detection_fields":{"riskState":"COMPROMISED"}},"target":{"user":{"userid":"user2@example.com"}},"principal":{"location":{"city":"London"}}} +{"metadata":{"event_type":"USER_LOGIN"},"security_result":{"action":"BLOCK","detection_fields":{"riskState":"atRisk"}},"target":{"user":{"userid":"user3@example.com"}},"principal":{"location":{"city":"London"}}} \ No newline at end of file diff --git a/blueprints/secops-ai-migration-helper/rules/rule_01235_windows_ad_account_created_deleted_1day/rule_01235_windows_ad_account_created_deleted_1day.yaral b/blueprints/secops-ai-migration-helper/rules/rule_01235_windows_ad_account_created_deleted_1day/rule_01235_windows_ad_account_created_deleted_1day.yaral new file mode 100644 index 0000000..3abc19a --- /dev/null +++ b/blueprints/secops-ai-migration-helper/rules/rule_01235_windows_ad_account_created_deleted_1day/rule_01235_windows_ad_account_created_deleted_1day.yaral @@ -0,0 +1,106 @@ +rule rule_01235_windows_ad_account_created_deleted_1day { + /* + +SOURCE: DEMO SOC + +PARAMETER: + - none + + Dependencies: + - UDM fields: metadata.vendor_name, metadata.product_event_type, target.user.user_display_name, metadata.event_timestamp.seconds, target.group.windows_sid, target.user.windows_sid + - Windows Event IDs: 4720, 624 (account created); 4728, 4732, 4756, 632, 636, 660 (account added to group); 4726, 630 (account deleted). + +TUNING: + - Time window: The '36h' in the 'match' section defines the maximum time difference between the account creation, group addition, and deletion events. This can be adjusted based on organizational policies and observed threat actor behavior. + - Event IDs: Additional Windows Event IDs related to account creation, modification, or deletion can be added to the 'events' section to broaden or narrow the rule's scope. + +TESTING: + - Sample Logs: Use 'sample_logs/WINEVTLOG.log' to test the rule. + - Expected Behavior: The rule should trigger when a user account is created (Event ID 4720 or 624), then added to a security group (Event ID 4728, 4732, 4756, 632, 636, or 660), and subsequently deleted (Event ID 4726 or 630), all within a 36-hour period for the same user. + - Verification: Ensure that the sequence and timing of these events are correctly identified by the rule. + +DOCS: + - Description: This rule detects a suspicious sequence of events where a user account is created, added to a security group, and then deleted within a short timeframe (36 hours). This pattern can indicate malicious activity such as privilege escalation followed by an attempt to cover tracks. + - Title: User account created, added to group, and deleted in a short period (36 hours) + - MITRE ATT&CK: + - Tactic: TA0003 (Persistence) + - Technique: T1136.002 (Create Account: Domain Account) + - URL: https://attack.mitre.org/versions/v17/techniques/T1136.002/ + - Data Source: Windows Active Directory + - Severity: High + - Reference: The rule monitors specific Windows Event IDs related to account lifecycle management in Active Directory. + +NOTES: + - This rule correlates three distinct Windows Active Directory events: account creation, account addition to a security group, and account deletion. The correlation is based on the same user display name and a configurable time window of 36 hours. This pattern is often indicative of an attacker creating temporary accounts for malicious purposes and then removing them to evade detection. + +*/ + + meta: + + + author = "Google Professional Services" + description = "Detects accounts that have been created, added to dedicated deleted within a day" + title = "User created and deleted in short period (1 day)" + responsible = "SOC1" + creation_date = "08.06.2025" + last_rework_date = "" + old_ucid = "b123" + secops_ucid = "01235" + version = "0.5" + mitre_attack_tactic = "TA0003" + mitre_attack_technique = "T1136.002" + mitre_attack_url = "https://attack.mitre.org/versions/v17/techniques/T1136.002/" + mitre_attack_version = "17" + type = "Alert" + data_source = "Windows" + severity = "High" + status = "prototype" + + events: + $account_created.metadata.vendor_name = "Microsoft" + ( + $account_created.metadata.product_event_type = "4720" or //A user account was created + $account_created.metadata.product_event_type = "624" + ) + $account_created.target.user.user_display_name = $displayname + + $account_created.metadata.event_timestamp.seconds < $account_added.metadata.event_timestamp.seconds + + $account_added.metadata.vendor_name = "Microsoft" + ( + $account_added.metadata.product_event_type = "4728" or //A member was added to a security-enabled global group + $account_added.metadata.product_event_type = "4732" or //A member was added to a security-enabled domain local group. + $account_added.metadata.product_event_type = "4756" or //A member was added to a security-enabled universal group. + + //Legacy (Pre-Vista/2008) + $account_added.metadata.product_event_type = "632" or //A member was added to a security-enabled global group + $account_added.metadata.product_event_type = "636" or //A member was added to a security-enabled domain local group. + $account_added.metadata.product_event_type = "660" //A member was added to a security-enabled universal group. + ) + $account_added.target.user.user_display_name = $displayname + $account_added.target.group.windows_sid = $group + + $account_added.metadata.event_timestamp.seconds < $account_deleted.metadata.event_timestamp.seconds + + $account_deleted.metadata.vendor_name = "Microsoft" + ( + $account_deleted.metadata.product_event_type = "4726" or //A user account was deleted + //Legacy (Pre-Vista/2008) + $account_deleted.metadata.product_event_type = "630" //A user account was deleted + ) + + $account_deleted.target.user.user_display_name = $displayname + $account_deleted.target.user.windows_sid = $target_user + + + match: + $displayname over 36h + + + outcome: + $Source_user = array_distinct($displayname) + $Event_id = array_distinct($account_added.metadata.product_event_type) + + condition: + $account_created and $account_added and $account_deleted +} diff --git a/blueprints/secops-ai-migration-helper/rules/rule_01235_windows_ad_account_created_deleted_1day/sample_logs/WINEVTLOG.log b/blueprints/secops-ai-migration-helper/rules/rule_01235_windows_ad_account_created_deleted_1day/sample_logs/WINEVTLOG.log new file mode 100644 index 0000000..a2afa98 --- /dev/null +++ b/blueprints/secops-ai-migration-helper/rules/rule_01235_windows_ad_account_created_deleted_1day/sample_logs/WINEVTLOG.log @@ -0,0 +1,2 @@ +<Event xmlns='http://schemas.microsoft.com/win/2004/08/events/event'><System><Provider Name='Microsoft-Windows-Security-Auditing' Guid='{54849625-5478-4994-a5ba-3e3b0328c30d}'></Provider><EventID Qualifiers=''>4720</EventID><Version>0</Version><Level>0</Level><Task>13824</Task><Opcode>0</Opcode><Keywords>0x8020000000000000</Keywords><TimeCreated SystemTime='2025-06-07T13:53:23.356167Z'></TimeCreated><EventRecordID>1945943</EventRecordID><Correlation ActivityID='{38068009-512d-0000-22-11}' RelatedActivityID=''></Correlation><Execution ProcessID='556' ThreadID='596'></Execution><Channel>Security</Channel><Computer>fs01.TESTSEC.lan</Computer><Security UserID=''></Security></System><EventData><Data Name=''>test_user</Data><Data Name='TargetDomainName'>FS01</Data><Data Name='TargetSid'>S-1-5-21-1081258321-37805170-3511562335-1001</Data><Data Name='SubjectUserSid'>S-1-5-21-444444-33333-222222-1111</Data><Data Name='SubjectUserName'>test_user</Data><Data Name='SubjectDomainName'>TESTSEC</Data><Data Name='SubjectLogonId'>0x000000000046b7b4</Data><Data Name='PrivilegeList'>-</Data><Data Name='SamAccountName'>test_user</Data><Data Name='DisplayName'>%%1793</Data><Data Name='UserPrincipalName'>-</Data><Data Name='HomeDirectory'>%%1793</Data><Data Name='HomePath'>%%1793</Data><Data Name='ScriptPath'>%%1793</Data><Data Name='ProfilePath'>%%1793</Data><Data Name='UserWorkstations'>%%1793</Data><Data Name='PasswordLastSet'>%%1794</Data><Data Name='AccountExpires'>%%1794</Data><Data Name='PrimaryGroupId'>513</Data><Data Name='AllowedToDelegateTo'>-</Data><Data Name='OldUacValue'>0x0</Data><Data Name='NewUacValue'>0x15</Data><Data Name='UserAccountControl'>\t\t%%2080\t\t%%2082\t\t%%2084</Data><Data Name='UserParameters'>%%1793</Data><Data Name='SidHistory'>-</Data><Data Name='LogonHours'>%%1797</Data></EventData></Event> +<Event xmlns='http://schemas.microsoft.com/win/2004/08/events/event'><System><Provider Name='Microsoft-Windows-Security-Auditing' Guid='{54849625-5478-4994-a5ba-3e3b0328c30d}'></Provider><EventID Qualifiers=''>4726</EventID><Version>0</Version><Level>0</Level><Task>13824</Task><Opcode>0</Opcode><Keywords>0x8020000000000000</Keywords><TimeCreated SystemTime='2025-06-07T13:42:39.620649Z'></TimeCreated><EventRecordID>1934526</EventRecordID><Correlation ActivityID='' RelatedActivityID=''></Correlation><Execution ProcessID='480' ThreadID='1496'></Execution><Channel>Security</Channel><Computer>testlan.lan</Computer><Security UserID=''></Security></System><EventData><Data Name='TargetUserName'>test_user</Data><Data Name='TargetDomainName'>DOM1</Data><Data Name='TargetSid'>S-1-5-21-2721507831-1374043488-2540227515-1008</Data><Data Name='SubjectUserSid'>S-1-5-21-444444-33333-222222-1111</Data><Data Name='SubjectUserName'>test_user</Data><Data Name='SubjectDomainName'>TESTSEC</Data><Data Name='SubjectLogonId'>0x0000000014f509e2</Data><Data Name='PrivilegeList'>-</Data></EventData></Event>ßßß diff --git a/blueprints/secops-ai-migration-helper/rules/rule_0500_iis_incident_observed_path_webshell/rule_0500_iis_incident_observed_path_webshell.yaral b/blueprints/secops-ai-migration-helper/rules/rule_0500_iis_incident_observed_path_webshell/rule_0500_iis_incident_observed_path_webshell.yaral new file mode 100644 index 0000000..e1536cc --- /dev/null +++ b/blueprints/secops-ai-migration-helper/rules/rule_0500_iis_incident_observed_path_webshell/rule_0500_iis_incident_observed_path_webshell.yaral @@ -0,0 +1,138 @@ +rule rule_0500_iis_incident_observed_path_webshell { +/* + +SOURCE: DEMO SOC + +PARAMETER: + + - This rule doesn't have time-based `match` section parameters to adjust. Its detection relies on web server access logs. + - Known Web Shell Paths (`KnownWebShells`): The rule relies on a static list of known webshell paths (`KnownWebShells`). Regular maintenance of this list is vital to ensure it remains up-to-date with new threats. + +Dependencies: + + - W3C IIS Log files. + - Ensure `csUriStem` and `csMethod` fields are consistently populated in your IIS logs. + - Availability of `FullAddress` for URI parsing. + +TUNING: + - False Positives: + - This rule targets specific URI paths associated with known webshells. While these paths are indicative of malicious activity, it's crucial to ensure that no legitimate applications or services utilize these exact paths. + - Known Exceptions: + - HTTP Status Code Exclusions: The rule explicitly excludes events with `scStatus` codes "404" (Not Found), "405" (Method Not Allowed), and "500" (Internal Server Error). This helps reduce false positives by focusing on successful or partially successful connections to the webshell paths. + - Further Tuning: + - Maintain `KnownWebShells` List: It is critical to regularly review and maintain the `KnownWebShells` list. Any new legitimate applications or services that might unexpectedly use these paths should be thoroughly evaluated and, if safe, excluded or the list updated. + - Contextual Analysis: For alerts, investigate the full web server logs, the client IP (`clientIP`), User Agent (`UserAgent`), and the server IP (`sIP`) to determine legitimacy and identify the source of the connection. + - Refine URI Parsing: If the `getPageURI` logic proves too broad or narrow for specific scenarios (e.g., if there are variations in how `.aspx` is used), consider refining the URI parsing. + +TESTING: + + - Simulate Access to Known Webshell Paths: + - On a test web server (IIS) that is configured to log to W3C format: + - Example (using `curl` or `Postman` to simulate POST requests to known paths): + ```bash + curl -X POST http://[your_iis_server]/owa/auth/current/themes/resource.aspx -d "testdata=123" + curl -X POST http://[your_iis_server]/test.aspx/abc/cdf -d "payload=attack" + ``` + - Verify Event Log Entries: + - After executing the commands, check your W3C IIS logs. + - Confirm that entries are created with `csMethod` as "POST" and `csUriStem` matching the simulated paths. + - Also, test with `scStatus` codes like 404, 405, 500 to ensure they are properly filtered out. + - Verify Alert Generation: + - Confirm that an alert is generated by this rule for the simulated suspicious activity. + * Check the `outcome` fields in the generated alert to ensure that relevant fields like `clientIP`, `UserAgent`, `csUriStem`, `csMethod`, `sIP`, `scStatus` are populated correctly. + - Verify Known Exceptions: + - Simulate POST requests to known webshell paths that result in 404, 405, or 500 status codes. Verify that no alerts are generated. + + DOCS: + + - MITRE ATT&CK - Web Shell (T1505.003): https://attack.mitre.org/techniques/T1505/003/ + - W3C Extended Log File Format: https://www.w3.org/TR/WD-logfile.html + +NOTES: + - This rule is designed to detect connections to known webshell paths, indicating potential compromise or reconnaissance activities targeting web servers. + - The severity is set to High, as successful access to webshells can lead to significant compromise. + - Robust logging of IIS access logs, including `csUriStem` and `csMethod`, is essential for this rule's effectiveness. + - The rule uses string matching and a custom function to normalize URI paths for accurate detection. + - Upon an alert, immediate incident response actions are required: Isolate the affected host, investigate the source IP, user agent, and assess for malicious intent or potential compromise. + - This rule is based on historical KQL rule. + - KQL rule: + //ucid: 0500 + //author: Peter Mustermann + //title: Path indicating Webshell with HTTP POST + //severity: High + //description: This rule detects connections to malicious URLs and webshells known to be associated with the SilverBirch campaign. A trigger on a asset signifies a potential compromise related to this threat + //technique: T1505.003 + //date created: 1/1/2019 + //date reviewed: 13/07/2020 + + + let getPageURI = (FullAddress:string) { + substring(FullAddress, 0, indexof(FullAddress,\".aspx\")) + }; + //the list of knwon webshell paths received from DH team (Sinon) + let KnownWebShells = dynamic ([ + \"/owa/auth/current/themes/resource.aspx\", + \"/owa/auth/current/scripts/premium/flogon.aspx\", + //\"/owa/auth/logon.aspx\", //removed after discussing with Sinon + \"/owa/auth/autherror.aspx\", + \"/owa/auth/errorfe.aspx\", + \"/autodiscover/global.aspx\", + \"/autodiscover/services.aspx\", + \"/test.aspx\", + \"/_login/defaults.aspx\" + ]); + W3CIISLog + | where TimeGenerated > ago(1d) + | where csMethod =~ \"POST\" + | extend getPageURIToLower = strcat(tolower(getPageURI(csUriStem)),\".aspx\") + | where getPageURIToLower in (KnownWebShells) + | summarize clientIP=make_set(cIP), UserAgent=make_set(csUserAgent), count() by csUriStem, csMethod, sIP, scStatus + | summarize by tostring(clientIP), tostring(UserAgent), csUriStem, csMethod, sIP, scStatus + | where not (scStatus has_any (\"404\",\"405\",\"500\")) //Not Found, Method Not Allowed, Internal Server Error //AI 86819 & 88154 +*/ + + meta: + author = "Google Professional Services" + description = "This rule detects connections to malicious URLs and webshells known to be associated with the SilverBirch campaign. A trigger on a asset signifies a potential compromise related to this threat" + responsible = "SOC1" + creation_date = "10.01.2025" + last_rework_date = "15.01.2025" + version = "0.5" + old_ucid = "0a1" + secops_ucid = "0500" + mitre_attack_tactic = "TA0003" + mitre_attack_technique = "T1505.003" + mitre_attack_url = "https://attack.mitre.org/techniques/T1505/003/" + mitre_attack_version = "1.5" + type = "Alert" + data_source = "Web Server (IIS) Logs" + severity = "High" + status = "prototype" + + events: + $Windows_IIS.target.ip = $target_ip + $Windows_IIS.metadata.log_type = "IIS" + $Windows_IIS.metadata.vendor_name = "Microsoft" + $Windows_IIS.network.http.method = "POST" + $Windows_IIS.target.url = /^\/(owa\/auth\/current\/themes\/resource\.aspx|owa\/auth\/current\/scripts\/premium\/flogon\.aspx|owa\/auth\/autherror\.aspx|owa\/auth\/errorfe\.aspx|autodiscover\/global\.aspx|autodiscover\/services\.aspx|test\.aspx|_login\/defaults\.aspx)$/ + $Windows_IIS.network.http.response_code != 404 + $Windows_IIS.network.http.response_code != 405 + $Windows_IIS.network.http.response_code != 500 + + match: + + $target_ip over 1h + outcome: + $Event_count = count($Windows_IIS.metadata.id) + $Network_Direction = array_distinct($Windows_IIS.network.direction) + $User_Agent = array_distinct($Windows_IIS.network.http.user_agent) + $Product_name = array_distinct($Windows_IIS.metadata.product_name) + $Target_Url = array_distinct($Windows_IIS.target.url) + $Target_ip = array_distinct($Windows_IIS.target.ip) + $Method = array_distinct($Windows_IIS.network.http.method) + $Protocol = array_distinct($Windows_IIS.network.application_protocol) + $Response_Code = array_distinct($Windows_IIS.network.http.response_code) + + condition: + $Windows_IIS +} diff --git a/blueprints/secops-ai-migration-helper/rules/rule_0500_iis_incident_observed_path_webshell/sample_logs/IIS.log b/blueprints/secops-ai-migration-helper/rules/rule_0500_iis_incident_observed_path_webshell/sample_logs/IIS.log new file mode 100644 index 0000000..4d67dce --- /dev/null +++ b/blueprints/secops-ai-migration-helper/rules/rule_0500_iis_incident_observed_path_webshell/sample_logs/IIS.log @@ -0,0 +1,4 @@ +2025-07-09 10:00:00 192.168.1.100 POST /owa/auth/current/themes/resource.aspx - 80 - 10.0.0.5 "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.88 Safari/537.36" - 200 0 0 150 +2025-07-09 10:05:00 192.168.1.101 POST /test.aspx/upload/shell.php - 80 - 10.0.0.6 "curl/7.81.0" - 200 0 0 75 +2025-07-09 10:10:00 192.168.1.102 POST /autodiscover/global.aspx - 80 - 10.0.0.7 "Python/3.9 aiohttp/3.8.1" - 200 0 0 200 +2025-07-09 10:15:00 192.168.1.103 POST /owa/auth/current/scripts/premium/flogon.aspx - 80 - 10.0.0.8 "Mozilla/5.0" - 200 0 0 100 \ No newline at end of file