From 3e0112454e4926c12ad7c190dc2d8b2769727d70 Mon Sep 17 00:00:00 2001 From: 7908837174 <7908837174@github.com> Date: Wed, 23 Jul 2025 04:28:42 +0530 Subject: [PATCH] Add Sigma Translator App v1.1.0 - Modern pySigma Implementation - Complete rewrite using modern pySigma framework instead of legacy sigmatools - Support for 12+ SIEM platforms (Splunk, Elasticsearch, Microsoft Sentinel, QRadar, etc.) - New actions: translate_sigma_rule, validate_sigma_rule, list_supported_platforms, convert_rule_file - Multiple output formats: default, JSON, YAML - Improved error handling and validation - Updated to use shuffle_sdk instead of walkoff_app_sdk - Addresses issue #148: Create Sigma translator app Supported platforms: - Splunk (SPL queries) - Elasticsearch (Lucene queries) - Microsoft Sentinel (KQL queries) - IBM QRadar (AQL queries) - LogPoint, CrowdStrike, Carbon Black, InsightIDR, Panther, OpenSearch, Loki, SQLite This implementation provides a modern, maintainable solution for translating Sigma detection rules to various SIEM query languages, similar to uncoder.io functionality. --- sigma/1.1.0/Dockerfile | 7 + sigma/1.1.0/README.md | 89 ++++++++++ sigma/1.1.0/api.yaml | 130 ++++++++++++++ sigma/1.1.0/requirements.txt | 16 ++ sigma/1.1.0/src/app.py | 334 +++++++++++++++++++++++++++++++++++ 5 files changed, 576 insertions(+) create mode 100644 sigma/1.1.0/Dockerfile create mode 100644 sigma/1.1.0/README.md create mode 100644 sigma/1.1.0/api.yaml create mode 100644 sigma/1.1.0/requirements.txt create mode 100644 sigma/1.1.0/src/app.py diff --git a/sigma/1.1.0/Dockerfile b/sigma/1.1.0/Dockerfile new file mode 100644 index 00000000..55a84ba5 --- /dev/null +++ b/sigma/1.1.0/Dockerfile @@ -0,0 +1,7 @@ +FROM shuffle/shuffle:app_sdk + +COPY requirements.txt /tmp/requirements.txt +RUN pip install -r /tmp/requirements.txt + +COPY src /app +WORKDIR /app diff --git a/sigma/1.1.0/README.md b/sigma/1.1.0/README.md new file mode 100644 index 00000000..ef071eac --- /dev/null +++ b/sigma/1.1.0/README.md @@ -0,0 +1,89 @@ +# Sigma Translator App v1.1.0 + +A modern Sigma rule translator for Shuffle that converts Sigma detection rules to various SIEM query languages using the pySigma framework. + +## Features + +- **Modern pySigma Integration**: Uses the latest pySigma library instead of legacy sigmatools +- **Multiple SIEM Support**: Supports 12+ SIEM platforms including Splunk, Elasticsearch, Microsoft Sentinel, QRadar, and more +- **Rule Validation**: Validates Sigma rules for syntax and structure +- **Multiple Output Formats**: Supports default, JSON, and YAML output formats +- **File Integration**: Works with Shuffle's file storage system + +## Supported Platforms + +- **Splunk**: SPL queries +- **Elasticsearch**: Lucene queries +- **Microsoft Sentinel**: KQL queries +- **IBM QRadar**: AQL queries +- **LogPoint**: LogPoint queries +- **CrowdStrike**: CrowdStrike queries +- **Carbon Black**: Carbon Black queries +- **Rapid7 InsightIDR**: LEQL queries +- **Panther**: Panther queries +- **OpenSearch**: Lucene queries +- **Grafana Loki**: LogQL queries +- **SQLite**: SQL queries + +## Actions + +### translate_sigma_rule +Translates a Sigma rule to a specific SIEM query language. + +**Parameters:** +- `sigma_rule` (required): The Sigma rule in YAML format +- `target_platform` (required): Target SIEM platform (e.g., "splunk", "elasticsearch") +- `output_format` (optional): Output format ("default", "json", "yaml") + +### validate_sigma_rule +Validates a Sigma rule for syntax and structure. + +**Parameters:** +- `sigma_rule` (required): The Sigma rule in YAML format to validate + +### list_supported_platforms +Lists all supported SIEM platforms and their capabilities. + +**Parameters:** None + +### convert_rule_file +Converts a Sigma rule file from Shuffle file storage. + +**Parameters:** +- `file_id` (required): The Shuffle file ID containing the Sigma rule +- `target_platform` (required): Target SIEM platform + +## Example Usage + +### Basic Translation +```yaml +title: Suspicious Process Creation +logsource: + category: process_creation + product: windows +detection: + selection: + Image|endswith: '\cmd.exe' + CommandLine|contains: 'whoami' + condition: selection +``` + +This rule can be translated to Splunk SPL, Elasticsearch Lucene, Microsoft Sentinel KQL, and other supported formats. + +## Dependencies + +- pySigma v0.11.23+ +- Multiple pySigma backend packages +- PyYAML for YAML processing +- JSONSchema for validation + +## Version History + +- **v1.1.0**: Complete rewrite using modern pySigma framework +- **v1.0.0**: Legacy implementation using sigmatools (deprecated) + +## Related Links + +- [Sigma Detection Format](https://sigmahq.io/) +- [pySigma Documentation](https://sigmahq-pysigma.readthedocs.io/) +- [Shuffle Documentation](https://shuffler.io/docs) diff --git a/sigma/1.1.0/api.yaml b/sigma/1.1.0/api.yaml new file mode 100644 index 00000000..c0fe7033 --- /dev/null +++ b/sigma/1.1.0/api.yaml @@ -0,0 +1,130 @@ +--- +app_version: 1.1.0 +name: Sigma +description: Modern Sigma rule translator for SIEM platforms using pySigma. Converts Sigma rules to various SIEM query languages like Splunk, Elasticsearch, Microsoft Sentinel, and more. +tags: + - SIEM + - Detection + - Security + - Translation +categories: + - SIEM +contact_info: + name: "@frikkylikeme" + url: https://shuffler.io + email: frikky@shuffler.io +actions: + - name: translate_sigma_rule + description: Translates a Sigma rule to a specific SIEM query language + parameters: + - name: sigma_rule + description: The Sigma rule in YAML format to translate + required: true + multiline: true + example: | + title: Suspicious Process Creation + logsource: + category: process_creation + product: windows + detection: + selection: + Image|endswith: '\cmd.exe' + CommandLine|contains: 'whoami' + condition: selection + schema: + type: string + - name: target_platform + description: The target SIEM platform to translate to + required: true + options: + - splunk + - elasticsearch + - microsoft-sentinel + - qradar + - logpoint + - crowdstrike + - carbonblack + - insightidr + - panther + - opensearch + - loki + - sqlite + example: 'splunk' + schema: + type: string + - name: output_format + description: The output format for the translated query + required: false + options: + - default + - json + - yaml + example: 'default' + schema: + type: string + returns: + schema: + type: string + + - name: validate_sigma_rule + description: Validates a Sigma rule for syntax and structure + parameters: + - name: sigma_rule + description: The Sigma rule in YAML format to validate + required: true + multiline: true + example: | + title: Test Rule + logsource: + category: process_creation + product: windows + detection: + selection: + Image: test.exe + condition: selection + schema: + type: string + returns: + schema: + type: string + + - name: list_supported_platforms + description: Lists all supported SIEM platforms and their capabilities + parameters: [] + returns: + schema: + type: string + + - name: convert_rule_file + description: Converts a Sigma rule file from Shuffle file storage + parameters: + - name: file_id + description: The Shuffle file ID containing the Sigma rule + required: true + example: "file_12345" + schema: + type: string + - name: target_platform + description: The target SIEM platform to translate to + required: true + options: + - splunk + - elasticsearch + - microsoft-sentinel + - qradar + - logpoint + - crowdstrike + - carbonblack + - insightidr + - panther + - opensearch + - loki + - sqlite + example: 'splunk' + schema: + type: string + returns: + schema: + type: string + +large_image: data:image/jpg;base64,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t0tWyq+TyD5fVUlHH07rjI7wAwPapO0ppm16cpvI0MWZH/xZ38Xyd56B2Dgsay9wxMxEdZ3RZ2nRGrqZAaluozjnefAfdXGlbNTWGzU9tpuIjGXvxxe8+k495WVQADkFRypz3ue4ucckrrMUTIWCNgwBsC+NbUQ0tPJUVEjY4Y2F73O5ADmVzlq+8yX/UFTcngtY87sLT9WMeiO/p7ytx2t6wbXPdYbbLvU8bv3qVp4SOH1B2A8+3uUbq22OgMTfjP3nd4Ll2mF7bVSCkhOWt3nmfb6oiIp9UlFtOzLTzr9qOMyx5oqUiWcnkcei3xPsBWv2qgqrncIaCiiMs8zt1rR7z1AdJXQ2jNP02nLNFQQ4fJ6c8uOMjzzPd0DsUPeK8U0Wo09p3Qc1adFrK6vqRK8f22bT3ngPv7rNNGF6RFSV2JEREREREREREREREREREWHuGp9P0O8Kq80Mbm8C3yoJHgOK1K+7VLPTtcy1081fL0OcPJx+s8T6lsxUc8xwxhKjqq70VICZpQPnk+Q2qQKmaKCB800jI42DLnvdgNHWSok2g7RDVsktdgkc2F3my1Y4F46QzqHb6lp+ptU3nUMn7/U4gBy2ni82MeHSe05WEVkoLG2Ih8+08uHuue3zTB9U0w0mWt4nifDl9fBEReo2PkkEcbHPe44DWjJPcArCSAqQAScBeVeWe2V13r2UVvp3TzP6ByA6yegdq23S2zW83QsnuINtpTx88ZlcOxvR4+pS3p2wWyw0fya20wiB9N54veetx6VC116igBbF2ndFbbNolU1jhJUDUZ1PgOHiVi9A6QpNNUe87E1fKPpp8cB+FvU33ra0RU+WV8zy95ySuq0tLFSRCGEYaEREXmthERERERERERERERERERERYa8aYsV3ya+100rz/ADA3df8AmGCtUr9k9kmJNJW1tL2FwkHtGfapERbMNZPD+h5Cjqq0UNUczRAnnjb5jaonm2QSZ+hvrSPx03wcvUGyA/z77+Sm+LlKyLa/GKz+fQfZR35UtOc/C6n7qP7fspsEDg6qnrawjmHSBjT4NGfatstFhtNoZu223U1N1uYzzj3u5rKItSarnm/yPJUlS2qipDmGIA88bfPeqNGBhVRFrqQREREREREREREREREREREREREREREREREREREREREREREREREREREREREX/9k= \ No newline at end of file diff --git a/sigma/1.1.0/requirements.txt b/sigma/1.1.0/requirements.txt new file mode 100644 index 00000000..33868b2e --- /dev/null +++ b/sigma/1.1.0/requirements.txt @@ -0,0 +1,16 @@ +requests==2.32.4 +pysigma==0.11.23 +pysigma-backend-splunk==1.2.0 +pysigma-backend-elasticsearch==1.1.3 +pysigma-backend-kusto==0.4.0 +pysigma-backend-qradar==0.4.0 +pysigma-backend-logpoint==0.2.0 +pysigma-backend-crowdstrike==0.3.0 +pysigma-backend-carbonblack==0.2.0 +pysigma-backend-insightidr==0.2.0 +pysigma-backend-panther==0.2.0 +pysigma-backend-opensearch==1.1.0 +pysigma-backend-loki==1.0.0 +pysigma-backend-sqlite==0.1.0 +pyyaml==6.0.2 +jsonschema==4.23.0 diff --git a/sigma/1.1.0/src/app.py b/sigma/1.1.0/src/app.py new file mode 100644 index 00000000..313c8c22 --- /dev/null +++ b/sigma/1.1.0/src/app.py @@ -0,0 +1,334 @@ +import os +import json +import yaml +import tempfile +import traceback +from typing import Dict, List, Optional, Any + +from shuffle_sdk import AppBase + +# pySigma imports +from sigma.rule import SigmaRule +from sigma.collection import SigmaCollection +from sigma.exceptions import SigmaError, SigmaParseError + +# Backend imports +try: + from sigma.backends.splunk import SplunkBackend + from sigma.pipelines.splunk import splunk_windows_pipeline +except ImportError: + SplunkBackend = None + +try: + from sigma.backends.elasticsearch import LuceneBackend + from sigma.pipelines.elasticsearch import ecs_windows_pipeline +except ImportError: + LuceneBackend = None + +try: + from sigma.backends.kusto import KustoBackend + from sigma.pipelines.microsoft365defender import microsoft_365_defender_pipeline +except ImportError: + KustoBackend = None + +try: + from sigma.backends.qradar import QRadarBackend +except ImportError: + QRadarBackend = None + +try: + from sigma.backends.logpoint import LogPointBackend +except ImportError: + LogPointBackend = None + +try: + from sigma.backends.crowdstrike import CrowdStrikeBackend +except ImportError: + CrowdStrikeBackend = None + +try: + from sigma.backends.carbonblack import CarbonBlackBackend +except ImportError: + CarbonBlackBackend = None + +try: + from sigma.backends.insightidr import InsightIDRBackend +except ImportError: + InsightIDRBackend = None + +try: + from sigma.backends.panther import PantherBackend +except ImportError: + PantherBackend = None + +try: + from sigma.backends.opensearch import OpensearchLuceneBackend +except ImportError: + OpensearchLuceneBackend = None + +try: + from sigma.backends.loki import LokiBackend +except ImportError: + LokiBackend = None + +try: + from sigma.backends.sqlite import SqliteBackend +except ImportError: + SqliteBackend = None + + +class Sigma(AppBase): + __version__ = "1.1.0" + app_name = "sigma" + + def __init__(self, redis, logger, console_logger=None): + """ + Initialize the Sigma app with Redis and logging. + """ + super().__init__(redis, logger, console_logger) + + # Define supported backends + self.backends = { + "splunk": { + "backend": SplunkBackend, + "pipeline": splunk_windows_pipeline if 'splunk_windows_pipeline' in globals() else None, + "description": "Splunk SPL queries" + }, + "elasticsearch": { + "backend": LuceneBackend, + "pipeline": ecs_windows_pipeline if 'ecs_windows_pipeline' in globals() else None, + "description": "Elasticsearch Lucene queries" + }, + "microsoft-sentinel": { + "backend": KustoBackend, + "pipeline": microsoft_365_defender_pipeline if 'microsoft_365_defender_pipeline' in globals() else None, + "description": "Microsoft Sentinel KQL queries" + }, + "qradar": { + "backend": QRadarBackend, + "pipeline": None, + "description": "IBM QRadar AQL queries" + }, + "logpoint": { + "backend": LogPointBackend, + "pipeline": None, + "description": "LogPoint queries" + }, + "crowdstrike": { + "backend": CrowdStrikeBackend, + "pipeline": None, + "description": "CrowdStrike queries" + }, + "carbonblack": { + "backend": CarbonBlackBackend, + "pipeline": None, + "description": "Carbon Black queries" + }, + "insightidr": { + "backend": InsightIDRBackend, + "pipeline": None, + "description": "Rapid7 InsightIDR LEQL queries" + }, + "panther": { + "backend": PantherBackend, + "pipeline": None, + "description": "Panther queries" + }, + "opensearch": { + "backend": OpensearchLuceneBackend, + "pipeline": None, + "description": "OpenSearch Lucene queries" + }, + "loki": { + "backend": LokiBackend, + "pipeline": None, + "description": "Grafana Loki LogQL queries" + }, + "sqlite": { + "backend": SqliteBackend, + "pipeline": None, + "description": "SQLite queries" + } + } + + def _parse_sigma_rule(self, sigma_rule: str) -> SigmaRule: + """ + Parse a Sigma rule from YAML string. + """ + try: + # Parse YAML + rule_dict = yaml.safe_load(sigma_rule) + + # Create SigmaRule object + sigma_rule_obj = SigmaRule.from_dict(rule_dict) + return sigma_rule_obj + + except yaml.YAMLError as e: + raise SigmaParseError(f"Invalid YAML format: {str(e)}") + except Exception as e: + raise SigmaError(f"Failed to parse Sigma rule: {str(e)}") + + def _get_backend(self, platform: str): + """ + Get the appropriate backend for the target platform. + """ + if platform not in self.backends: + available_platforms = list(self.backends.keys()) + raise ValueError(f"Unsupported platform '{platform}'. Available platforms: {available_platforms}") + + backend_info = self.backends[platform] + backend_class = backend_info["backend"] + + if backend_class is None: + raise ImportError(f"Backend for '{platform}' is not available. Please install the required package.") + + # Initialize backend + backend = backend_class() + + # Apply pipeline if available + pipeline = backend_info["pipeline"] + if pipeline: + backend.pipeline = pipeline + + return backend + + def translate_sigma_rule(self, sigma_rule: str, target_platform: str, output_format: str = "default") -> str: + """ + Translate a Sigma rule to a specific SIEM query language. + """ + try: + self.logger.info(f"Translating Sigma rule to {target_platform}") + + # Parse the Sigma rule + rule = self._parse_sigma_rule(sigma_rule) + + # Get the appropriate backend + backend = self._get_backend(target_platform) + + # Convert the rule + queries = backend.convert(rule) + + # Format output + if output_format == "json": + result = { + "platform": target_platform, + "queries": queries, + "rule_title": rule.title if hasattr(rule, 'title') else "Unknown", + "rule_id": str(rule.id) if hasattr(rule, 'id') else None + } + return json.dumps(result, indent=2) + elif output_format == "yaml": + result = { + "platform": target_platform, + "queries": queries, + "rule_title": rule.title if hasattr(rule, 'title') else "Unknown", + "rule_id": str(rule.id) if hasattr(rule, 'id') else None + } + return yaml.dump(result, default_flow_style=False) + else: + # Default format - return queries as string + if isinstance(queries, list): + return "\n".join(queries) + else: + return str(queries) + + except Exception as e: + error_msg = f"Translation failed: {str(e)}\n{traceback.format_exc()}" + self.logger.error(error_msg) + return f"Error: {str(e)}" + + def validate_sigma_rule(self, sigma_rule: str) -> str: + """ + Validate a Sigma rule for syntax and structure. + """ + try: + self.logger.info("Validating Sigma rule") + + # Parse the rule + rule = self._parse_sigma_rule(sigma_rule) + + # Basic validation checks + validation_results = { + "valid": True, + "title": getattr(rule, 'title', None), + "id": str(getattr(rule, 'id', None)) if getattr(rule, 'id', None) else None, + "status": getattr(rule, 'status', None), + "level": getattr(rule, 'level', None), + "logsource": getattr(rule, 'logsource', None), + "detection": bool(getattr(rule, 'detection', None)), + "warnings": [] + } + + # Check for required fields + if not validation_results["title"]: + validation_results["warnings"].append("Missing title field") + + if not validation_results["detection"]: + validation_results["warnings"].append("Missing or invalid detection section") + + if not validation_results["logsource"]: + validation_results["warnings"].append("Missing logsource section") + + return json.dumps(validation_results, indent=2) + + except Exception as e: + error_result = { + "valid": False, + "error": str(e), + "details": traceback.format_exc() + } + return json.dumps(error_result, indent=2) + + def list_supported_platforms(self) -> str: + """ + List all supported SIEM platforms and their capabilities. + """ + try: + platforms = {} + + for platform, info in self.backends.items(): + platforms[platform] = { + "description": info["description"], + "available": info["backend"] is not None, + "has_pipeline": info["pipeline"] is not None + } + + result = { + "supported_platforms": platforms, + "total_count": len(platforms), + "available_count": sum(1 for p in platforms.values() if p["available"]) + } + + return json.dumps(result, indent=2) + + except Exception as e: + return f"Error listing platforms: {str(e)}" + + def convert_rule_file(self, file_id: str, target_platform: str) -> str: + """ + Convert a Sigma rule file from Shuffle file storage. + """ + try: + self.logger.info(f"Converting rule file {file_id} to {target_platform}") + + # Get file content from Shuffle + file_content = self.get_file(file_id) + + if not file_content: + return "Error: Could not retrieve file content" + + # Convert bytes to string if necessary + if isinstance(file_content, bytes): + file_content = file_content.decode('utf-8') + + # Translate the rule + return self.translate_sigma_rule(file_content, target_platform) + + except Exception as e: + error_msg = f"File conversion failed: {str(e)}" + self.logger.error(error_msg) + return f"Error: {str(e)}" + + +if __name__ == "__main__": + Sigma.run()