[FR] Add Hunt Structure and Initial LLM Queries 🚀 (#3637)

This commit is contained in:
Mika Ayenson
2024-05-03 09:33:06 -05:00
committed by GitHub
parent 2668f5f762
commit 00b8a77f50
13 changed files with 463 additions and 0 deletions
+1
View File
@@ -28,6 +28,7 @@ Detection Rules contains more than just static rule files. This repository also
|------------------------------------------------ |------------------------------------------------------------------------------------ |
| [`detection_rules/`](detection_rules) | Python module for rule parsing, validating and packaging |
| [`etc/`](detection_rules/etc) | Miscellaneous files, such as ECS and Beats schemas |
|[`hunting`](./hunting/)|Root directory where threat hunting queries are stored|
| [`kibana/`](lib/kibana) | Python library for handling the API calls to Kibana and the Detection Engine |
| [`kql/`](lib/kql) | Python library for parsing and validating Kibana Query Language |
| [`rta/`](rta) | Red Team Automation code used to emulate attacker techniques, used for rule testing |
+60
View File
@@ -0,0 +1,60 @@
# Hunt Queries
---
Welcome to the `hunting` folder within the `detection-rules` repository! This directory houses a curated collection of threat hunting queries designed to enhance security monitoring and threat detection capabilities using the Elastic Stack. Each file in this directory provides a query tailored for identifying specific security threats or suspicious activities.
These queries are designed for use with the Elastic Security platform, part of the broader Elastic Stack, enabling security teams to proactively hunt for potential threats in their environment.
- KQL
- EQL
- ES|QL
- OsQuery
- YARA
## How to Contribute
Contributing to the `hunting` folder is a great way to share your expertise and enhance the security community's capabilities. Heres how you can contribute:
### Adding New Queries
- **TOML File Naming and Organization**: Ensure that any new queries are named descriptively and grouped by the type of threat they address. Place your TOML files inside the `queries` folder and ensure they are named in a way that reflects the nature of the threat or behavior they are designed to detect.
- **TOML Fields**: To ensure the hunt queries are consistent and comprehensive, it's important to structure the threat detection rules with specific fields. When contributing a new rule, please include the following fields in the TOML file to describe and configure the analytic:
- **author**: The name of the individual or organization authoring the rule.
- **integration**: The specific integration or data source the rule applies to, such as `aws_bedrock.invocation`.
- **uuid**: A unique identifier for the rule to maintain version control and tracking.
- **name**: A descriptive name for the rule that clearly indicates its purpose.
- **language**: The query language used in the rule, such as `KQL`, `EQL`, `ES|QL`, `OsQuery`, or `YARA`.
- **query**: The actual query or analytic expression written in the appropriate query language that executes the detection logic.
- **notes**: An array of strings providing detailed insights into the rationale behind the rule, suggestions for further investigation, and tips on distinguishing false positives from true activity.
- **mitre**: Reference to applicable MITRE ATT&CK tactics or techniques that the rule addresses, enhancing the contextual understanding of its security implications.
- **references**: Links to external documents, research papers, or websites that provide additional information or validation for the detection logic.
- **Documentation (Optional)**: Include a `README.md` in each subfolder describing the queries and their purposes. This would include a brief description of the new category.
### Field Usage
Use standardized fields where possible to ensure that queries are compatible across different data environments and sources.
### Review and Pull Requests
Follow the standard [contributing guide](../CONTRIBUTING.md). Please remember to use the generate_markdown.py script to update the documentation after adding or updateing queries.
## Using the Script to Generate Markdown
The `generate_markdown.py` script is provided to automate the creation of Markdown files from TOML rule definitions. Heres how to use it:
- **Generating Markdown**: Run `python generate_markdown.py` from the root of the `hunting` directory. This will generate Markdown files for each TOML file and update the `index.md` to include links to the new Markdown files.
- **Structure**: Rules should be written in TOML and saved under the respective `hunt/*/rules/` directory. The script will automatically convert them into Markdown and save them in the `docs` directory within the respective category folder.
### Sample Directory Structure Example
```config
.
├── README.md
├── generate_markdown.py
├── index.md
└── categorical_folder_name
├── README.md
├── docs
│ └── generated_markdown.md
└── rules
└── hunt_query.toml
```
+4
View File
@@ -0,0 +1,4 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
+80
View File
@@ -0,0 +1,80 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
"""Lightweight builtin toml-markdown converter."""
import tomllib
from dataclasses import dataclass, field
from pathlib import Path
from typing import List, Optional
HUNTING_DIR = Path(__file__).parent
@dataclass
class Hunt:
"""Dataclass to represent a hunt."""
author: str
integration: str
uuid: str
name: str
language: str
query: str
notes: Optional[List[str]] = field(default_factory=list)
mitre: Optional[List[str]] = field(default_factory=list)
references: Optional[List[str]] = field(default_factory=list)
def load_toml(contents: str) -> Hunt:
"""Load and validate TOML content as Hunt dataclass."""
toml_dict = tomllib.loads(contents)
return Hunt(**toml_dict["hunt"])
def load_all_toml(base_path: Path) -> List[tuple[Hunt, Path]]:
"""Load all TOML files from the directory and return a list of Hunt configurations and their paths."""
hunts = []
for toml_file in base_path.rglob("*.toml"):
hunt_config = load_toml(toml_file.read_text())
hunts.append((hunt_config, toml_file))
return hunts
def convert_toml_to_markdown(hunt_config: Hunt, file_path: Path) -> str:
"""Convert Hunt to Markdown format."""
markdown = f"# {hunt_config.name}\n\n---\n\n"
markdown += "## Metadata\n\n"
markdown += f"- **Author:** {hunt_config.author}\n"
markdown += f"- **UUID:** `{hunt_config.uuid}`\n"
markdown += f"- **Integration:** `{hunt_config.integration}`\n"
markdown += f"- **Language:** `{hunt_config.language}`\n\n"
markdown += "## Query\n\n"
markdown += f"```sql\n{hunt_config.query}```\n\n"
if hunt_config.notes:
markdown += "## Notes\n\n" + "\n".join(f"- {note}" for note in hunt_config.notes)
if hunt_config.mitre:
markdown += "\n## MITRE ATT&CK Techniques\n\n" + "\n".join(
f"- [{tech}](https://atlas.mitre.org/techniques/{tech})\n" for tech in hunt_config.mitre
)
if hunt_config.references:
markdown += "\n## References\n\n" + "\n".join(f"- {ref}" for ref in hunt_config.references)
markdown += f"\n- [{hunt_config.name}]({Path('../queries') / file_path.name})"
return markdown
def process_toml_files(base_path: Path) -> None:
"""Process all TOML files in the directory recursively and convert them to Markdown."""
hunts = load_all_toml(base_path)
for hunt_config, toml_file in hunts:
markdown_content = convert_toml_to_markdown(hunt_config, toml_file)
markdown_path = toml_file.parent.parent / "docs" / f"{toml_file.stem}.md"
markdown_path.parent.mkdir(parents=True, exist_ok=True)
markdown_path.write_text(markdown_content, encoding="utf-8")
print(f"Markdown generated: {markdown_path}")
if __name__ == "__main__":
process_toml_files(HUNTING_DIR)
+8
View File
@@ -0,0 +1,8 @@
# List of Available Queries
Here are the queries currently available:
## llm
- [Denial of Service or Resource Exhaustion Attacks Detection](llm/queries/docs/llm_dos_resource_exhaustion_detection.md) (ES|QL)
- [Monitoring for Latency Anomalies](llm/queries/docs/llm_latency_anomalies_detection.md) (ES|QL)
- [Sensitive Content Refusal Detection](llm/queries/docs/llm_sensitive_content_refusal_detection.md) (ES|QL)
+43
View File
@@ -0,0 +1,43 @@
# LLM Threat Hunting Queries
Welcome to the `LLM` subfolder within the `hunting` directory of the `detection-rules` repository. This specialized section is dedicated to threat hunting queries designed for Large Language Model (LLM) applications, targeting the unique security challenges these systems face.
## Emphasis on OWASP Top 10 for LLMs
Our queries are developed with a keen awareness of the [OWASP Top 10 risks for Large Language Model Applications](https://owasp.org/www-project-top-10-for-large-language-model-applications/). This crucial resource outlines the predominant security risks for LLMs, guiding our efforts in crafting queries that proactively address these vulnerabilities and ensure comprehensive threat mitigation.
## Emphasis on MITRE ATLAS
The [ATLAS Matrix](https://atlas.mitre.org/matrices/ATLAS/) covers the progression of tactics used in attacks with ML techniques belonging to different tactics.
- Reconnaissance
- Resource Development
- Initial Access
- ML Model Access
- Execution
- Persistence
- Privilege Escalation
- Defense Evasion
- Credential Access
- Discovery
- Collection
- ML Attack Staging
- Exfiltration
- Impact
## Scope of Threats and Protections
The queries in this folder are tailored to monitor and protect against a broad spectrum of threats to LLMs:
- **Sensitive Content Refusal**: Monitors LLM interactions to ensure compliance with ethical standards, particularly in refusing to process sensitive topics.
- **Denial of Service (DoS) and Resource Exhaustion**: Aims to prevent disruptions in LLM operations by detecting patterns indicative of DoS attacks or resource exhaustion scenarios.
- **Latency Anomalies**: Tracks processing delays that could signal underlying performance issues or security threats, maintaining operational efficiency and safeguarding against potential attacks like DDoS.
### Benefits of These Queries
These queries assist organizations in:
- Detecting and mitigating misuse or attacks that threaten data integrity or disrupt services.
- Ensuring that LLMs adhere strictly to operational and ethical boundaries through continuous monitoring.
- Maintaining high performance and reliability of LLMs by preemptively identifying and resolving factors that cause inefficiencies.
For more details, read our blog on [LLM Detections](https://www.elastic.co/security-labs/elastic-advances-llm-security).
@@ -0,0 +1,44 @@
# Denial of Service or Resource Exhaustion Attacks Detection
---
## Metadata
- **Author:** Elastic
- **UUID:** `dc181967-c32c-46c9-b84b-ec4c8811c6a0`
- **Integration:** `aws_bedrock.invocation`
- **Language:** `ES|QL`
## Query
```sql
from logs-aws_bedrock.invocation-*
| WHERE @timestamp > NOW() - 1 DAY
AND (
gen_ai.usage.prompt_tokens > 8000 OR
gen_ai.usage.completion_tokens > 8000 or
gen_ai.performance.request_size > 8000
)
| STATS max_prompt_tokens = max(gen_ai.usage.prompt_tokens),
max_request_tokens = max(gen_ai.performance.request_size),
max_completion_tokens = max(gen_ai.usage.completion_tokens),
request_count = count() BY cloud.account.id
| WHERE request_count > 1
| SORT max_prompt_tokens, max_request_tokens, max_completion_tokens DESC
```
## Notes
- This query identifies unusual spikes in token usage that may indicate malicious attempts to disrupt services. High token usage can strain system resources and degrade performance, aligning with tactics observed in DoS attacks.
- Consider reviewing the context of high token requests to differentiate between legitimate heavy usage and potential abuse. Monitor the source of requests and patterns over time for better assessment.
- Ensure logging and monitoring are correctly configured to capture detailed metrics on token usage. This will facilitate accurate detection and allow for a quick response to potential threats.
- Collect evidence from logs that detail the timestamp, user ID, session information, and token counts for incidents flagged by this analytic. This information will be crucial for forensic analysis in the event of a security incident.
## MITRE ATT&CK Techniques
- [AML.T0034](https://atlas.mitre.org/techniques/AML.T0034)
## References
- https://www.elastic.co/security-labs/elastic-advances-llm-security
- https://owasp.org/www-project-top-10-for-large-language-model-applications/
- [Denial of Service or Resource Exhaustion Attacks Detection](../queries/llm_dos_resource_exhaustion_detection.toml)
@@ -0,0 +1,39 @@
# Monitoring for Latency Anomalies
---
## Metadata
- **Author:** Elastic
- **UUID:** `3708787b-811b-43b1-b2e7-c7276b8db48c`
- **Integration:** `aws_bedrock.invocation`
- **Language:** `ES|QL`
## Query
```sql
from logs-aws_bedrock.invocation-*
| WHERE @timestamp > NOW() - 1 DAY
| EVAL response_delay_seconds = gen_ai.performance.start_response_time / 1000
| WHERE response_delay_seconds > 5
| STATS max_response_delay = max(response_delay_seconds),
request_count = count() BY gen_ai.user.id
| WHERE request_count > 3
| SORT max_response_delay DESC
```
## Notes
- This analytic helps identify delays in LLM responses that are outside expected performance parameters, possibly due to malicious disruptions like DDoS attacks or from operational inefficiencies.
- Review the incidents flagged by this analytic to understand the context and potential sources of latency. This can include network configurations, resource allocation, or external network pressures.
- Effective logging and monitoring setup are essential to capture relevant latency metrics accurately. Ensure system clocks and time syncing are properly configured to avoid false positives.
- Gather comprehensive logs that detail the request and response timestamps, user IDs, and session details for thorough investigation and evidence collection in case of security incidents.
## MITRE ATT&CK Techniques
- [AML.T0029](https://atlas.mitre.org/techniques/AML.T0029)
## References
- https://www.elastic.co/security-labs/elastic-advances-llm-security
- https://owasp.org/www-project-top-10-for-large-language-model-applications/
- [Monitoring for Latency Anomalies](../queries/llm_latency_anomalies_detection.toml)
@@ -0,0 +1,39 @@
# Sensitive Content Refusal Detection
---
## Metadata
- **Author:** Elastic
- **UUID:** `8fabae86-7ed2-4006-9623-5db28164f374`
- **Integration:** `aws_bedrock.invocation`
- **Language:** `ES|QL`
## Query
```sql
from logs-aws_bedrock.invocation-*
| WHERE @timestamp > NOW() - 1 DAY
AND (
gen_ai.completion LIKE "*I cannot provide any information about*"
AND gen_ai.completion LIKE "*end_turn*"
)
| STATS user_request_count = count() BY gen_ai.user.id
| WHERE user_request_count >= 3
```
## Notes
- This analytic flags multiple instances of LLM refusals to respond to sensitive prompts, helping to maintain ethical guidelines and compliance standards.
- Examine flagged interactions for patterns or anomalies in user requests that may indicate malicious intent or probing of model boundaries.
- Regularly review and update the phrases that trigger refusals to adapt to new ethical guidelines and compliance requirements.
- Ensure that data logs contain enough detail to provide context around the refusal, which will aid in subsequent investigations by security teams.
## MITRE ATT&CK Techniques
- [AML.T0051](https://atlas.mitre.org/techniques/AML.T0051)
## References
- https://www.elastic.co/security-labs/elastic-advances-llm-security
- https://owasp.org/www-project-top-10-for-large-language-model-applications/
- [Sensitive Content Refusal Detection](../queries/llm_sensitive_content_refusal_detection.toml)
@@ -0,0 +1,30 @@
[hunt]
author = "Elastic"
integration = "aws_bedrock.invocation"
uuid = "dc181967-c32c-46c9-b84b-ec4c8811c6a0"
name = "Denial of Service or Resource Exhaustion Attacks Detection"
language = "ES|QL"
query = '''
from logs-aws_bedrock.invocation-*
| WHERE @timestamp > NOW() - 1 DAY
AND (
gen_ai.usage.prompt_tokens > 8000 OR
gen_ai.usage.completion_tokens > 8000 or
gen_ai.performance.request_size > 8000
)
| STATS max_prompt_tokens = max(gen_ai.usage.prompt_tokens),
max_request_tokens = max(gen_ai.performance.request_size),
max_completion_tokens = max(gen_ai.usage.completion_tokens),
request_count = count() BY cloud.account.id
| WHERE request_count > 1
| SORT max_prompt_tokens, max_request_tokens, max_completion_tokens DESC
'''
notes = [
"This query identifies unusual spikes in token usage that may indicate malicious attempts to disrupt services. High token usage can strain system resources and degrade performance, aligning with tactics observed in DoS attacks.",
"Consider reviewing the context of high token requests to differentiate between legitimate heavy usage and potential abuse. Monitor the source of requests and patterns over time for better assessment.",
"Ensure logging and monitoring are correctly configured to capture detailed metrics on token usage. This will facilitate accurate detection and allow for a quick response to potential threats.",
"Collect evidence from logs that detail the timestamp, user ID, session information, and token counts for incidents flagged by this analytic. This information will be crucial for forensic analysis in the event of a security incident."
]
mitre = ["AML.T0034"]
references = ["https://www.elastic.co/security-labs/elastic-advances-llm-security",
"https://owasp.org/www-project-top-10-for-large-language-model-applications/"]
@@ -0,0 +1,25 @@
[hunt]
author = "Elastic"
integration = "aws_bedrock.invocation"
uuid = "3708787b-811b-43b1-b2e7-c7276b8db48c"
name = "Monitoring for Latency Anomalies"
language = "ES|QL"
query = '''
from logs-aws_bedrock.invocation-*
| WHERE @timestamp > NOW() - 1 DAY
| EVAL response_delay_seconds = gen_ai.performance.start_response_time / 1000
| WHERE response_delay_seconds > 5
| STATS max_response_delay = max(response_delay_seconds),
request_count = count() BY gen_ai.user.id
| WHERE request_count > 3
| SORT max_response_delay DESC
'''
notes = [
"This analytic helps identify delays in LLM responses that are outside expected performance parameters, possibly due to malicious disruptions like DDoS attacks or from operational inefficiencies.",
"Review the incidents flagged by this analytic to understand the context and potential sources of latency. This can include network configurations, resource allocation, or external network pressures.",
"Effective logging and monitoring setup are essential to capture relevant latency metrics accurately. Ensure system clocks and time syncing are properly configured to avoid false positives.",
"Gather comprehensive logs that detail the request and response timestamps, user IDs, and session details for thorough investigation and evidence collection in case of security incidents."
]
mitre = ["AML.T0029"]
references = ["https://www.elastic.co/security-labs/elastic-advances-llm-security",
"https://owasp.org/www-project-top-10-for-large-language-model-applications/"]
@@ -0,0 +1,25 @@
[hunt]
author = "Elastic"
integration = "aws_bedrock.invocation"
uuid = "8fabae86-7ed2-4006-9623-5db28164f374"
name = "Sensitive Content Refusal Detection"
language = "ES|QL"
query = '''
from logs-aws_bedrock.invocation-*
| WHERE @timestamp > NOW() - 1 DAY
AND (
gen_ai.completion LIKE "*I cannot provide any information about*"
AND gen_ai.completion LIKE "*end_turn*"
)
| STATS user_request_count = count() BY gen_ai.user.id
| WHERE user_request_count >= 3
'''
notes = [
"This analytic flags multiple instances of LLM refusals to respond to sensitive prompts, helping to maintain ethical guidelines and compliance standards.",
"Examine flagged interactions for patterns or anomalies in user requests that may indicate malicious intent or probing of model boundaries.",
"Regularly review and update the phrases that trigger refusals to adapt to new ethical guidelines and compliance requirements.",
"Ensure that data logs contain enough detail to provide context around the refusal, which will aid in subsequent investigations by security teams."
]
mitre = ["AML.T0051"]
references = ["https://www.elastic.co/security-labs/elastic-advances-llm-security",
"https://owasp.org/www-project-top-10-for-large-language-model-applications/"]
+65
View File
@@ -0,0 +1,65 @@
# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
# or more contributor license agreements. Licensed under the Elastic License
# 2.0; you may not use this file except in compliance with the Elastic License
# 2.0.
"""Test for hunt toml files."""
import unittest
from hunting.generate_markdown import HUNTING_DIR, load_toml
class TestHunt(unittest.TestCase):
"""Test hunt toml files."""
def test_toml_loading(self):
"""Test loading a hunt toml file content."""
example_toml = """
[hunt]
author = "Elastic"
integration = "aws_bedrock.invocation"
uuid = "dc181967-c32c-46c9-b84b-ec4c8811c6a0"
name = "Denial of Service or Resource Exhaustion Attacks Detection"
language = "ES|QL"
query = 'SELECT * FROM logs'
notes = ["High token usage can strain system resources."]
mitre = ["AML.T0034"]
references = ["https://www.elastic.co"]
"""
config = load_toml(example_toml)
self.assertEqual(config.author, "Elastic")
self.assertEqual(config.integration, "aws_bedrock.invocation")
self.assertEqual(config.uuid, "dc181967-c32c-46c9-b84b-ec4c8811c6a0")
self.assertEqual(
config.name, "Denial of Service or Resource Exhaustion Attacks Detection"
)
self.assertEqual(config.language, "ES|QL")
def test_load_toml_files(self):
"""Test loading and validating all Hunt TOML files in the hunting directory."""
for toml_file in HUNTING_DIR.rglob("*.toml"):
toml_contents = toml_file.read_text()
hunt = load_toml(toml_contents)
self.assertTrue(hunt.author)
self.assertTrue(hunt.integration)
self.assertTrue(hunt.uuid)
self.assertTrue(hunt.name)
self.assertTrue(hunt.language)
self.assertTrue(hunt.query)
def test_markdown_existence(self):
"""Ensure each TOML file has a corresponding Markdown file in the docs directory."""
for toml_file in HUNTING_DIR.rglob("*.toml"):
expected_markdown_path = (
toml_file.parent.parent / "docs" / toml_file.with_suffix(".md").name
)
self.assertTrue(
expected_markdown_path.exists(),
f"Markdown file not found for {toml_file} at expected location {expected_markdown_path}",
)
if __name__ == "__main__":
unittest.main()