From db302f4a550a1c7b4fcd5fc1d81f7ce9a2d821de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20St=C3=B6ckl?= Date: Mon, 25 Aug 2025 12:45:48 +0000 Subject: [PATCH] shodan_analyzer.py aktualisiert --- shodan_analyzer.py | 87 ++++++++++++++++++++++++---------------------- 1 file changed, 46 insertions(+), 41 deletions(-) diff --git a/shodan_analyzer.py b/shodan_analyzer.py index d6c6449..08d11cb 100644 --- a/shodan_analyzer.py +++ b/shodan_analyzer.py @@ -4,6 +4,7 @@ import requests import json from datetime import datetime import ipaddress +import os class ShodanEnrichmentAnalyzer(interface.BaseAnalyzer): """Analyzer to enrich IP addresses with Shodan data.""" @@ -15,14 +16,13 @@ class ShodanEnrichmentAnalyzer(interface.BaseAnalyzer): def __init__(self, index_name, sketch_id, timeline_id=None): super().__init__(index_name, sketch_id, timeline_id) - # Get API key from config or environment - config = self.get_config() - self.shodan_api_key = config.get('api_key', '') - self.max_time_diff_hours = config.get('max_time_diff_hours', 24) - self.rate_limit_delay = config.get('rate_limit_delay', 1) + # Get API key from environment variables + self.shodan_api_key = os.environ.get('SHODAN_API_KEY', '') + self.max_time_diff_hours = 24 + self.rate_limit_delay = 1 if not self.shodan_api_key: - self.logger.error("Shodan API key not configured") + self.logger.error("Shodan API key not configured in environment variables") def run(self): """Main analyzer logic.""" @@ -48,6 +48,7 @@ class ShodanEnrichmentAnalyzer(interface.BaseAnalyzer): timestamp = event.source.get('timestamp') if source_ip and self._is_public_ip(source_ip): + self.logger.info(f"Processing IP: {source_ip}") shodan_data = self._get_shodan_data(source_ip) if shodan_data: self._enrich_event(event, shodan_data) @@ -68,55 +69,58 @@ class ShodanEnrichmentAnalyzer(interface.BaseAnalyzer): 'history': 'true' } + self.logger.info(f"Querying Shodan API for IP: {ip}") response = requests.get(url, params=params, timeout=10) if response.status_code == 200: + self.logger.info(f"Successfully retrieved Shodan data for {ip}") return response.json() elif response.status_code == 404: self.logger.debug(f'No Shodan data found for {ip}') return None else: - self.logger.warning(f'Shodan API error for {ip}: {response.status_code}') + self.logger.warning(f'Shodan API error for {ip}: {response.status_code} - {response.text}') return None - except requests.exceptions.RequestException as e: - self.logger.warning(f'Request error for {ip}: {e}') - return None - except json.JSONDecodeError as e: - self.logger.warning(f'JSON decode error for {ip}: {e}') + except Exception as e: + self.logger.warning(f'Error fetching Shodan data for {ip}: {e}') return None def _enrich_event(self, event, shodan_data): """Add Shodan data to the event.""" - enrichment = { - 'shodan_ports': shodan_data.get('ports', []), - 'shodan_org': shodan_data.get('org', ''), - 'shodan_isp': shodan_data.get('isp', ''), - 'shodan_country': shodan_data.get('location', {}).get('country_name', ''), - 'shodan_city': shodan_data.get('location', {}).get('city', ''), - 'shodan_hostnames': shodan_data.get('hostnames', []), - 'shodan_last_update': shodan_data.get('last_update', ''), - '__ts_analyzer_shodan_enrichment': True - } - - # Add service banners from latest scan - if shodan_data.get('data'): - latest_scan = shodan_data['data'][0] # Most recent scan - enrichment['shodan_services'] = [] + try: + enrichment = { + 'shodan_ports': shodan_data.get('ports', []), + 'shodan_org': shodan_data.get('org', ''), + 'shodan_isp': shodan_data.get('isp', ''), + 'shodan_country': shodan_data.get('location', {}).get('country_name', ''), + 'shodan_city': shodan_data.get('location', {}).get('city', ''), + 'shodan_hostnames': shodan_data.get('hostnames', []), + 'shodan_last_update': shodan_data.get('last_update', ''), + '__ts_analyzer_shodan_enrichment': True + } - for service in shodan_data.get('data', []): - service_info = { - 'port': service.get('port'), - 'protocol': service.get('transport', 'tcp'), - 'service': service.get('product', ''), - 'version': service.get('version', ''), - 'timestamp': service.get('timestamp', '') - } - enrichment['shodan_services'].append(service_info) - - event.add_attributes(enrichment) - event.add_tags(['shodan-enriched']) - event.commit() + # Add service information from latest scan + if shodan_data.get('data'): + services = [] + for service in shodan_data.get('data', [])[:5]: # Limit to first 5 services + service_info = f"Port {service.get('port', 'Unknown')}/{service.get('transport', 'tcp')}" + if service.get('product'): + service_info += f" - {service.get('product', '')}" + if service.get('version'): + service_info += f" {service.get('version', '')}" + services.append(service_info) + + enrichment['shodan_services'] = services + + event.add_attributes(enrichment) + event.add_tags(['shodan-enriched']) + event.commit() + + self.logger.info(f"Successfully enriched event with Shodan data") + + except Exception as e: + self.logger.error(f"Error enriching event: {e}") def _is_public_ip(self, ip): """Check if IP is public (not RFC1918 private ranges).""" @@ -124,7 +128,8 @@ class ShodanEnrichmentAnalyzer(interface.BaseAnalyzer): ip_obj = ipaddress.ip_address(ip) return ip_obj.is_global except (ValueError, ipaddress.AddressValueError): + self.logger.debug(f"Invalid IP address format: {ip}") return False # Register the analyzer -manager.AnalysisManager.register_analyzer(ShodanEnrichmentAnalyzer) +manager.AnalysisManager.register_analyzer(ShodanEnrichmentAnalyzer) \ No newline at end of file