rules/integrations/azure_openai/azure_openai_model_theft_detection.toml (47 lines of code) (raw):
[metadata]
creation_date = "2025/02/25"
maturity = "production"
updated_date = "2025/02/25"
min_stack_comments = "ES|QL rule type is still in technical preview as of 8.13, however this rule was tested successfully; integration in tech preview"
min_stack_version = "8.13.0"
[rule]
author = ["Elastic"]
description = """
Monitors for suspicious activities that may indicate theft or unauthorized duplication of machine learning (ML) models, such as
unauthorized API calls, atypical access patterns, or large data transfers that are unusual during model interactions.
"""
false_positives = ["Authorized model training", "Legitimate high volume data exchanges during scheduled updates"]
from = "now-60m"
interval = "10m"
language = "esql"
license = "Elastic License v2"
name = "Potential Azure OpenAI Model Theft"
references = [
"https://genai.owasp.org/llmrisk/llm10-model-theft",
"https://atlas.mitre.org/techniques/AML.T0044"
]
risk_score = 47
rule_id = "4021e78d-5293-48d3-adee-a70fa4c18fab"
setup = """## Setup
For more information on
streaming events, see the Azure OpenAI documentation:
https://learn.microsoft.com/en-us/azure/azure-monitor/essentials/stream-monitoring-data-event-hubs
"""
severity = "medium"
tags = [
"Domain: LLM",
"Data Source: Azure OpenAI",
"Data Source: Azure Event Hubs",
"Use Case: Model Theft",
"Mitre Atlas: T0044"
]
timestamp_override = "event.ingested"
type = "esql"
query = '''
from logs-azure_openai.logs-*
| where azure.open_ai.operation_name == "ListKey" and azure.open_ai.category == "Audit"
| KEEP @timestamp, azure.open_ai.operation_name , azure.open_ai.category, azure.resource.group, azure.resource.name, azure.open_ai.properties.response_length
| stats count = count(), max_data_transferred = max(azure.open_ai.properties.response_length) by azure.resource.group , azure.resource.name
| where count >= 100 or max_data_transferred >= 1000000
| sort count desc
'''