shodan_analyzer.py aktualisiert
This commit is contained in:
parent
4fd7bc0fbc
commit
db302f4a55
@ -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)
|
Loading…
x
Reference in New Issue
Block a user