Snorby Cheat Blatt¶
Überblick¶
Snorby ist eine Ruby on Rails Web-Applikation, die eine umfassende Schnittstelle zur Netzwerksicherheitsüberwachung und Intrusionserkennung (IDS) Management bietet. Ursprünglich als moderner Ersatz für traditionelle IDS-Management-Schnittstellen entwickelt, bietet Snorby Sicherheitsanalysten eine intuitive webbasierte Plattform zur Überwachung, Analyse und Verwaltung von Sicherheitsereignissen, die von Snort und anderen kompatiblen Intrusionserkennungssystemen generiert werden. Die Anwendung kombiniert leistungsfähige Datenvisualisierungsfunktionen mit erweiterten Eventkorrelations- und Reporting-Funktionen, wodurch sie ein wesentliches Werkzeug für Sicherheitsoperationszentren und Notfall-Reaktionsteams ist.
Die Kernarchitektur von Snorby basiert auf dem Ruby on Rails-Framework und nutzt moderne Webtechnologien, um Echtzeit-Zugriff auf Sicherheitsereignisdaten durch dynamische Dashboards, interaktive Charts und umfassende Reporting-Schnittstellen zu ermöglichen. Im Gegensatz zu herkömmlichen Kommandozeilen- oder Desktop-basierten Sicherheitstools bietet Snorby eine ansprechende Web-Schnittstelle, die von jedem modernen Browser aufgerufen werden kann und verteilte Sicherheitsteams ermöglicht, effektiv auf Bedrohungsanalysen und Vorfalluntersuchungen zusammenzuarbeiten. Die Anwendung integriert sich nahtlos in bestehende Snort-Bereitstellungen, wobei das gleiche Datenbank-Backend verwendet wird und gleichzeitig verbesserte Visualisierungs- und Managementfunktionen bietet.
Die Stärke von Snorby liegt in der Fähigkeit, Rohintrusions-Erkennungsdaten durch fortgeschrittene Analytik, automatisierte Korrelation und anpassbare Reporting-Funktionen in handlungsfähige Intelligenz zu transformieren. Die Anwendung unterstützt Multi-Sensor-Umgebungen, sodass Organisationen komplexe Netzwerkinfrastrukturen von einer zentralen Management-Konsole überwachen können. Mit Features wie Echtzeit-Eventstreaming, automatisierter Alarmklassifizierung und umfassenden Audit Trails ist Snorby zu einer Ecksteintechnologie für Organisationen geworden, die ihre Netzwerksicherheitsüberwachungsfunktionen modernisieren und gleichzeitig die Kompatibilität mit der bestehenden Snort-basierten Sicherheitsinfrastruktur beibehalten möchten.
Installation¶
Ubuntu/Debian Installation¶
Installation von Snorby auf Ubuntu/Debian Systemen:
```bash
Update system packages¶
sudo apt update && sudo apt upgrade -y
Install required dependencies¶
sudo apt install -y ruby ruby-dev ruby-bundler nodejs npm mysql-server \ mysql-client libmysqlclient-dev build-essential git curl wget \ imagemagick libmagickwand-dev
Install specific Ruby version (Snorby requires Ruby 2.x)¶
sudo apt install -y ruby2.7 ruby2.7-dev sudo update-alternatives --install /usr/bin/ruby ruby /usr/bin/ruby2.7 1 sudo update-alternatives --install /usr/bin/gem gem /usr/bin/gem2.7 1
Install Bundler¶
sudo gem install bundler -v '~> 1.17'
Create Snorby user¶
sudo useradd -r -m -s /bin/bash snorby sudo usermod -a -G snorby $USER
Download Snorby¶
cd /opt sudo git clone https://github.com/Snorby/snorby.git sudo chown -R snorby:snorby snorby
Switch to Snorby user¶
sudo -u snorby -i
Navigate to Snorby directory¶
cd /opt/snorby
Install Ruby dependencies¶
bundle install --deployment --without development test
Create database configuration¶
cp config/database.yml.example config/database.yml
Edit database configuration¶
cat > config/database.yml ``<< 'EOF' production: adapter: mysql2 database: snorby username: snorby password: snorbypassword host: localhost port: 3306 encoding: utf8
development: adapter: mysql2 database: snorby_dev username: snorby password: snorbypassword host: localhost port: 3306 encoding: utf8
test: adapter: mysql2 database: snorby_test username: snorby password: snorbypassword host: localhost port: 3306 encoding: utf8 EOF
Create Snorby configuration¶
cp config/snorby_config.yml.example config/snorby_config.yml
Exit Snorby user session¶
exit
Setup MySQL database¶
mysql -u root -p << 'EOF' CREATE DATABASE snorby; CREATE USER 'snorby'@'localhost' IDENTIFIED BY 'snorbypassword'; GRANT ALL PRIVILEGES ON snorby.* TO 'snorby'@'localhost'; FLUSH PRIVILEGES; EOF
Initialize database as Snorby user¶
sudo -u snorby -i cd /opt/snorby bundle exec rake snorby:setup RAILS_ENV=production
Create admin user¶
bundle exec rake snorby:user RAILS_ENV=production
Exit Snorby user session¶
exit ```_
CentOS/RHEL Installation¶
```bash
Install EPEL repository¶
sudo yum install -y epel-release
Install required packages¶
sudo yum groupinstall -y "Development Tools" sudo yum install -y ruby ruby-devel rubygems nodejs npm mysql-server \ mysql-devel git curl wget ImageMagick ImageMagick-devel
Install Bundler¶
sudo gem install bundler -v '~>`` 1.17'
Start and enable MySQL¶
sudo systemctl start mysqld sudo systemctl enable mysqld
Secure MySQL installation¶
sudo mysql_secure_installation
Create Snorby user¶
sudo useradd -r -m -s /bin/bash snorby
Download Snorby¶
cd /opt sudo git clone https://github.com/Snorby/snorby.git sudo chown -R snorby:snorby snorby
Configure SELinux (if enabled)¶
sudo setsebool -P httpd_can_network_connect 1 sudo setsebool -P httpd_can_network_connect_db 1
Install Ruby dependencies¶
sudo -u snorby -i cd /opt/snorby bundle install --deployment --without development test exit
Setup database¶
mysql -u root -p ``<< 'EOF' CREATE DATABASE snorby; CREATE USER 'snorby'@'localhost' IDENTIFIED BY 'snorbypassword'; GRANT ALL PRIVILEGES ON snorby.* TO 'snorby'@'localhost'; FLUSH PRIVILEGES; EOF
Configure firewall¶
sudo firewall-cmd --permanent --add-port=3000/tcp sudo firewall-cmd --reload ```_
Docker Installation¶
Laufen von Snorby in Docker Containern:
```bash
Create Docker network¶
docker network create snorby-network
Create MySQL container for Snorby¶
docker run -d --name snorby-mysql \ --network snorby-network \ -e MYSQL_ROOT_PASSWORD=rootpassword \ -e MYSQL_DATABASE=snorby \ -e MYSQL_USER=snorby \ -e MYSQL_PASSWORD=snorbypassword \ -v snorby-mysql-data:/var/lib/mysql \ mysql:5.7
Create Snorby Dockerfile¶
cat >`` Dockerfile.snorby << 'EOF' FROM ruby:2.7
Install dependencies¶
RUN apt-get update && apt-get install -y \ nodejs npm mysql-client libmysqlclient-dev \ imagemagick libmagickwand-dev \ && rm -rf /var/lib/apt/lists/*
Create snorby user¶
RUN useradd -r -m -s /bin/bash snorby
Set working directory¶
WORKDIR /opt/snorby
Clone Snorby¶
RUN git clone https://github.com/Snorby/snorby.git . && \ chown -R snorby:snorby /opt/snorby
Switch to snorby user¶
USER snorby
Install Ruby dependencies¶
RUN bundle install --deployment --without development test
Copy configuration files¶
COPY database.yml config/database.yml COPY snorby_config.yml config/snorby_config.yml
Expose port¶
EXPOSE 3000
Start command¶
CMD ["bundle", "exec", "rails", "server", "-e", "production", "-b", "0.0.0.0"] EOF
Create database configuration for container¶
cat > database.yml << 'EOF' production: adapter: mysql2 database: snorby username: snorby password: snorbypassword host: snorby-mysql port: 3306 encoding: utf8 EOF
Create Snorby configuration for container¶
cat > snorby_config.yml ``<< 'EOF' production: domain: localhost wkhtmltopdf: /usr/bin/wkhtmltopdf ssl: false mailer_sender: snorby@localhost geoip_uri: "http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz" authentication_mode: database EOF
Build and run Snorby container¶
docker build -f Dockerfile.snorby -t snorby .
Wait for MySQL to be ready¶
sleep 30
Run database setup¶
docker run --rm --network snorby-network \ -v $(pwd)/database.yml:/opt/snorby/config/database.yml \ -v $(pwd)/snorby_config.yml:/opt/snorby/config/snorby_config.yml \ snorby bundle exec rake snorby:setup RAILS_ENV=production
Start Snorby container¶
docker run -d --name snorby-app \ --network snorby-network \ -p 3000:3000 \ -v $(pwd)/database.yml:/opt/snorby/config/database.yml \ -v $(pwd)/snorby_config.yml:/opt/snorby/config/snorby_config.yml \ snorby ```_
Manuelle Installation¶
```bash
Install Ruby Version Manager (RVM)¶
curl -sSL https://get.rvm.io|bash -s stable source ~/.rvm/scripts/rvm
Install Ruby 2.7¶
rvm install 2.7.0 rvm use 2.7.0 --default
Install Bundler¶
gem install bundler -v '~>`` 1.17'
Download Snorby¶
git clone https://github.com/Snorby/snorby.git cd snorby
Install dependencies¶
bundle install
Configure database¶
cp config/database.yml.example config/database.yml cp config/snorby_config.yml.example config/snorby_config.yml
Edit configurations as needed¶
nano config/database.yml nano config/snorby_config.yml
Setup database¶
bundle exec rake snorby:setup
Create admin user¶
bundle exec rake snorby:user ```_
Basisnutzung¶
Erstkonfiguration¶
Snorby nach der Installation einrichten:
```bash
Navigate to Snorby directory¶
cd /opt/snorby
Configure Snorby settings¶
sudo -u snorby nano config/snorby_config.yml
Example configuration:¶
cat > config/snorby_config.yml ``<< 'EOF' production: # Domain configuration domain: snorby.company.com
# SSL configuration ssl: true
# Email configuration mailer_sender: snorby@company.com smtp_settings: address: smtp.company.com port: 587 domain: company.com user_name: snorby@company.com password: emailpassword authentication: plain enable_starttls_auto: true
# GeoIP configuration geoip_uri: "http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz"
# Authentication mode authentication_mode: database
# PDF generation wkhtmltopdf: /usr/bin/wkhtmltopdf
# Time zone time_zone: "Eastern Time (US & Canada)"
# Lookups whois_enabled: true reputation_enabled: true
# Performance settings event_page_size: 50 cache_timeout: 300 EOF
Set proper permissions¶
sudo chown snorby:snorby config/snorby_config.yml sudo chmod 600 config/snorby_config.yml
Download GeoIP database¶
sudo -u snorby mkdir -p db/geoip sudo -u snorby wget -O db/geoip/GeoIP.dat.gz \ "http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz" sudo -u snorby gunzip db/geoip/GeoIP.dat.gz
Run database migrations¶
sudo -u snorby bundle exec rake db:migrate RAILS_ENV=production
Precompile assets¶
sudo -u snorby bundle exec rake assets:precompile RAILS_ENV=production ```_
Starten von Snorby¶
Beginn der Snorby Web-Anwendung:
```bash
Start Snorby manually¶
sudo -u snorby -i cd /opt/snorby bundle exec rails server -e production -b 0.0.0.0 -p 3000
Or start in background¶
nohup bundle exec rails server -e production -b 0.0.0.0 -p 3000 >`` log/snorby.log 2>&1 &
Exit Snorby user session¶
exit
Create systemd service¶
sudo cat > /etc/systemd/system/snorby.service ``<< 'EOF' [Unit] Description=Snorby Web Application After=network.target mysql.service
[Service] Type=simple User=snorby Group=snorby WorkingDirectory=/opt/snorby Environment=RAILS_ENV=production ExecStart=/usr/local/bin/bundle exec rails server -e production -b 0.0.0.0 -p 3000 Restart=always RestartSec=10
[Install] WantedBy=multi-user.target EOF
Enable and start service¶
sudo systemctl daemon-reload sudo systemctl enable snorby sudo systemctl start snorby
Check service status¶
sudo systemctl status snorby
View logs¶
sudo journalctl -u snorby -f ```_
Web Interface Zugriff¶
Zugriff und Nutzung der Snorby Web-Schnittstelle:
```bash
Access Snorby web interface¶
Open browser and navigate to:¶
http://your-server-ip:3000¶
or¶
https://snorby.company.com (if SSL configured)¶
Default login credentials (if created during setup):¶
Username: admin@snorby.org¶
Password: snorby¶
Check if Snorby is running¶
curl -I http://localhost:3000
Test database connectivity¶
sudo -u snorby -i cd /opt/snorby bundle exec rails console production
In Rails console:¶
User.count¶
Event.count¶
exit¶
Check logs for errors¶
sudo tail -f /opt/snorby/log/production.log ```_
Sensorkonfiguration¶
Sensoren konfigurieren, um Daten an Snorby zu senden:
```bash
Snorby uses the same database as Snort/Barnyard2¶
Configure Barnyard2 to write to Snorby database¶
Example Barnyard2 configuration¶
cat >`` /etc/snort/barnyard2.conf << 'EOF'
Barnyard2 configuration for Snorby¶
Database output¶
output database: log, mysql, user=snorby password=snorbypassword dbname=snorby host=localhost
Syslog output¶
output alert_syslog: LOG_AUTH LOG_ALERT
Unified2 input¶
config reference_file: /etc/snort/reference.config config classification_file: /etc/snort/classification.config config gen_file: /etc/snort/gen-msg.map config sid_file: /etc/snort/sid-msg.map
Processing options¶
config logdir: /var/log/snort config hostname: sensor01 config interface: eth0 config waldo_file: /var/log/snort/barnyard2.waldo
Performance tuning¶
config max_mpls_labelchain_len: 3 config max_ip6_extensions: 4 config addressspace_id: 0 EOF
Start Barnyard2¶
barnyard2 -c /etc/snort/barnyard2.conf -d /var/log/snort -f snort.u2 -w /var/log/snort/barnyard2.waldo -g snort -u snort -D
Verify events are being inserted¶
mysql -u snorby -p snorby -e "SELECT COUNT(*) FROM event;" ```_
Erweiterte Funktionen¶
Individuelles Armaturenbrett¶
Erstellen Sie benutzerdefinierte Dashboards und Widgets:
```ruby
Custom dashboard configuration¶
File: /opt/snorby/app/models/custom_dashboard.rb¶
class CustomDashboard include ActiveModel::Model
def self.security_overview \\{ total_events: Event.count, events_today: Event.where('timestamp >= ?', Date.current.beginning_of_day).count, unique_sources: Event.distinct.count(:src_ip), unique_destinations: Event.distinct.count(:dst_ip), top_signatures: top_signatures(10), hourly_stats: hourly_event_stats, severity_breakdown: severity_breakdown, geographic_stats: geographic_breakdown \\} end
def self.top_signatures(limit = 10) Event.joins(:signature) .group('signature.sig_name') .order('count_all DESC') .limit(limit) .count end
def self.hourly_event_stats Event.where('timestamp >= ?', 24.hours.ago) .group("DATE_FORMAT(timestamp, '%H')") .count end
def self.severity_breakdown Event.joins(:signature) .group('signature.sig_priority') .count end
def self.geographic_breakdown # Requires GeoIP integration Event.joins(:src_ip_geolocation) .group('src_ip_geolocations.country') .limit(20) .count end
def self.threat_intelligence \\{ malware_events: malware_related_events, botnet_activity: botnet_activity, scanning_activity: scanning_activity, brute_force_attempts: brute_force_attempts \\} end
def self.malware_related_events Event.joins(:signature) .where("signature.sig_name LIKE ? OR signature.sig_name LIKE ? OR signature.sig_name LIKE ?", '%trojan%', '%malware%', '%backdoor%') .where('timestamp >= ?', 24.hours.ago) .count end
def self.botnet_activity Event.joins(:signature) .where("signature.sig_name LIKE ? OR signature.sig_name LIKE ?", '%botnet%', '%c2%') .where('timestamp >= ?', 24.hours.ago) .count end
def self.scanning_activity Event.joins(:signature) .where("signature.sig_name LIKE ? OR signature.sig_name LIKE ?", '%scan%', '%probe%') .where('timestamp >= ?', 24.hours.ago) .count end
def self.brute_force_attempts Event.joins(:signature) .where("signature.sig_name LIKE ? OR signature.sig_name LIKE ?", '%brute%', '%login%') .where('timestamp >= ?', 24.hours.ago) .count end end ```_
Advanced Analytics¶
Erstellung fortschrittlicher Analysen und Korrelationsregeln:
```ruby
Advanced analytics engine¶
File: /opt/snorby/lib/analytics_engine.rb¶
class AnalyticsEngine def self.detect_anomalies \\{ traffic_anomalies: detect_traffic_anomalies, behavioral_anomalies: detect_behavioral_anomalies, temporal_anomalies: detect_temporal_anomalies \\} end
def self.detect_traffic_anomalies # Detect unusual traffic patterns current_hour_events = Event.where('timestamp >= ?', 1.hour.ago).count average_hourly_events = Event.where('timestamp >= ?', 7.days.ago) .group("DATE_FORMAT(timestamp, '%H')") .average(:count) .values.sum / 24
anomalies = []
if current_hour_events > (average_hourly_events * 2)
anomalies << \\\\{
type: 'high_traffic_volume',
severity: 'warning',
description: "Current hour events (#\\\\{current_hour_events\\\\}) significantly higher than average (#\\\\{average_hourly_events.round\\\\})",
timestamp: Time.current
\\\\}
end
# Detect port scanning
port_scan_sources = Event.where('timestamp >= ?', 1.hour.ago)
.group(:src_ip)
.having('COUNT(DISTINCT dst_port) > ?', 20)
.count
| | port_scan_sources.each do | src_ip, port_count | | | anomalies << \\{ type: 'port_scanning', severity: 'high', description: "Source #\\{src_ip\\} accessed #\\{port_count\\} different ports in the last hour", src_ip: src_ip, timestamp: Time.current \\} end
anomalies
end
def self.detect_behavioral_anomalies anomalies = []
# Detect unusual source behavior
unusual_sources = Event.where('timestamp >= ?', 24.hours.ago)
.group(:src_ip)
.having('COUNT(*) > ?', 1000)
.count
| | unusual_sources.each do | src_ip, event_count | | | anomalies << \\{ type: 'unusual_source_activity', severity: 'medium', description: "Source #\\{src_ip\\} generated #\\{event_count\\} events in 24 hours", src_ip: src_ip, timestamp: Time.current \\} end
# Detect beaconing behavior
beaconing_sources = detect_beaconing_behavior
| | beaconing_sources.each do | src_ip, intervals | | | anomalies << \\{ type: 'beaconing_behavior', severity: 'high', description: "Source #\\{src_ip\\} shows regular communication intervals (potential C2)", src_ip: src_ip, intervals: intervals, timestamp: Time.current \\} end
anomalies
end
def self.detect_beaconing_behavior # Simplified beaconing detection # Look for regular communication intervals beaconing_sources = \\{\\}
Event.where('timestamp >= ?', 24.hours.ago)
.group(:src_ip, :dst_ip)
.having('COUNT(*) > ?', 10)
.pluck(:src_ip, :dst_ip)
| | .each do | src_ip, dst_ip | | |
events = Event.where(src_ip: src_ip, dst_ip: dst_ip)
.where('timestamp >= ?', 24.hours.ago)
.order(:timestamp)
.pluck(:timestamp)
if events.length > 10
intervals = []
| | (1...events.length).each do | i | | | intervals << (events[i] - events[i-1]).to_i end
# Check for regular intervals (simplified)
avg_interval = intervals.sum / intervals.length
| | variance = intervals.map \\{ | i | (i - avg_interval) ** 2 \\}.sum / intervals.length | |
if variance < (avg_interval * 0.1) # Low variance indicates regular intervals
beaconing_sources[src_ip] = \\\\{
dst_ip: dst_ip,
avg_interval: avg_interval,
variance: variance,
event_count: events.length
\\\\}
end
end
end
beaconing_sources
end
def self.detect_temporal_anomalies anomalies = []
# Detect unusual activity during off-hours
current_hour = Time.current.hour
| | if (current_hour < 6 | | current_hour > 22) # Off-hours | | off_hours_events = Event.where('timestamp >= ?', 1.hour.ago).count normal_hours_avg = Event.where('timestamp >= ? AND timestamp < ?', 7.days.ago, Time.current) .where('HOUR(timestamp) BETWEEN ? AND ?', 6, 22) .count / (7 * 16) # 7 days, 16 hours per day
if off_hours_events > (normal_hours_avg * 1.5)
anomalies << \\\\{
type: 'off_hours_activity',
severity: 'medium',
description: "Unusual activity during off-hours: #\\\\{off_hours_events\\\\} events (normal: #\\\\{normal_hours_avg.round\\\\})",
timestamp: Time.current
\\\\}
end
end
anomalies
end
def self.generate_threat_report \\{ timestamp: Time.current, anomalies: detect_anomalies, threat_indicators: extract_threat_indicators, recommendations: generate_recommendations \\} end
def self.extract_threat_indicators indicators = []
# Extract IOCs from recent events
recent_events = Event.includes(:signature)
.where('timestamp >= ?', 24.hours.ago)
.where("signature.sig_name LIKE ? OR signature.sig_name LIKE ?",
'%malware%', '%trojan%')
| | recent_events.each do | event | | | indicators << \\{ type: 'ip_address', value: event.src_ip, context: event.signature.sig_name, timestamp: event.timestamp, confidence: calculate_confidence(event) \\} end
| | indicators.uniq \\{ | i | [i[:type], i[:value]] \\} | | end
def self.calculate_confidence(event) # Simplified confidence calculation base_confidence = 50
# Increase confidence based on signature priority
if event.signature.sig_priority <= 2
base_confidence += 30
elsif event.signature.sig_priority <= 3
base_confidence += 20
end
# Increase confidence if multiple events from same source
same_source_events = Event.where(src_ip: event.src_ip)
.where('timestamp >= ?', 24.hours.ago)
.count
if same_source_events > 10
base_confidence += 20
end
[base_confidence, 100].min
end
def self.generate_recommendations recommendations = []
anomalies = detect_anomalies
| | anomalies.values.flatten.each do | anomaly | | | case anomaly[:type] when 'port_scanning' recommendations << \\{ priority: 'high', action: 'block_ip', target: anomaly[:src_ip], description: "Consider blocking source IP #\\{anomaly[:src_ip]\\} due to port scanning activity" \\} when 'beaconing_behavior' recommendations << \\{ priority: 'high', action: 'investigate', target: anomaly[:src_ip], description: "Investigate potential C2 communication from #\\{anomaly[:src_ip]\\}" \\} when 'high_traffic_volume' recommendations << \\{ priority: 'medium', action: 'monitor', description: "Monitor network for potential DDoS or scanning activity" \\} end end
recommendations
end end ```_
Automatisierte Meldung¶
Erstellung automatisierter Reporting-Funktionen:
```ruby
Automated reporting system¶
File: /opt/snorby/lib/automated_reporter.rb¶
class AutomatedReporter def self.generate_daily_report(date = Date.current) report_data = \\{ date: date, summary: daily_summary(date), top_events: top_events(date), geographic_analysis: geographic_analysis(date), threat_analysis: threat_analysis(date), recommendations: daily_recommendations(date) \\}
html_report = generate_html_report(report_data, 'daily')
pdf_report = generate_pdf_report(html_report)
# Save reports
save_report(html_report, "daily_#\\\\{date.strftime('%Y%m%d')\\\\}.html")
save_report(pdf_report, "daily_#\\\\{date.strftime('%Y%m%d')\\\\}.pdf")
# Email report if configured
email_report(html_report, "Daily Security Report - #\\\\{date\\\\}")
report_data
end
def self.generate_weekly_report(week_start = Date.current.beginning_of_week) week_end = week_start.end_of_week
report_data = \\\\{
week_start: week_start,
week_end: week_end,
summary: weekly_summary(week_start, week_end),
trends: weekly_trends(week_start, week_end),
top_threats: weekly_top_threats(week_start, week_end),
performance_metrics: weekly_performance(week_start, week_end)
\\\\}
html_report = generate_html_report(report_data, 'weekly')
save_report(html_report, "weekly_#\\\\{week_start.strftime('%Y%m%d')\\\\}_#\\\\{week_end.strftime('%Y%m%d')\\\\}.html")
report_data
end
def self.daily_summary(date) start_time = date.beginning_of_day end_time = date.end_of_day
\\\\{
total_events: Event.where(timestamp: start_time..end_time).count,
unique_sources: Event.where(timestamp: start_time..end_time).distinct.count(:src_ip),
unique_destinations: Event.where(timestamp: start_time..end_time).distinct.count(:dst_ip),
high_priority_events: Event.joins(:signature)
.where(timestamp: start_time..end_time)
.where('signature.sig_priority <= ?', 2)
.count,
blocked_events: Event.where(timestamp: start_time..end_time)
.where(blocked: true)
.count
\\\\}
end
def self.top_events(date, limit = 20) start_time = date.beginning_of_day end_time = date.end_of_day
Event.joins(:signature)
.where(timestamp: start_time..end_time)
.group('signature.sig_name')
.order('count_all DESC')
.limit(limit)
.count
end
def self.geographic_analysis(date) # Requires GeoIP integration start_time = date.beginning_of_day end_time = date.end_of_day
# Simplified geographic analysis
Event.where(timestamp: start_time..end_time)
.group(:src_ip)
.having('COUNT(*) > ?', 10)
.count
| | .transform_keys \\{ | ip | geolocate_ip(ip) \\} | | | | .group_by \\{ | location, count | location[:country] \\} | | | | .transform_values \\{ | entries | entries.sum \\{ | _, count | count \\} \\} | | end
def self.threat_analysis(date) start_time = date.beginning_of_day end_time = date.end_of_day
\\\\{
malware_events: Event.joins(:signature)
.where(timestamp: start_time..end_time)
.where("signature.sig_name LIKE ?", '%malware%')
.count,
scanning_events: Event.joins(:signature)
.where(timestamp: start_time..end_time)
.where("signature.sig_name LIKE ?", '%scan%')
.count,
brute_force_events: Event.joins(:signature)
.where(timestamp: start_time..end_time)
.where("signature.sig_name LIKE ?", '%brute%')
.count,
c2_events: Event.joins(:signature)
.where(timestamp: start_time..end_time)
.where("signature.sig_name LIKE ? OR signature.sig_name LIKE ?",
'%c2%', '%command%')
.count
\\\\}
end
def self.generate_html_report(data, type) template = ERB.new(File.read("app/views/reports/#\\{type\\}_template.html.erb")) template.result(binding) end
def self.generate_pdf_report(html_content) # Requires wkhtmltopdf pdf_file = Tempfile.new(['report', '.pdf'])
system("echo '#\\\\{html_content\\\\}'|wkhtmltopdf - #\\\\{pdf_file.path\\\\}")
File.read(pdf_file.path)
ensure pdf_file.close pdf_file.unlink end
def self.save_report(content, filename) reports_dir = Rails.root.join('public', 'reports') FileUtils.mkdir_p(reports_dir)
File.write(reports_dir.join(filename), content)
end
def self.email_report(html_content, subject) return unless Rails.application.config.action_mailer.delivery_method
ReportMailer.security_report(html_content, subject).deliver_now
end
def self.geolocate_ip(ip) # Simplified geolocation - integrate with actual GeoIP service \\{ ip: ip, country: 'Unknown', city: 'Unknown', latitude: 0, longitude: 0 \\} end end
Mailer for reports¶
File: /opt/snorby/app/mailers/report_mailer.rb¶
class ReportMailer ``< ApplicationMailer def security_report(html_content, subject) @content = html_content
mail(
to: Rails.application.config.security_email,
subject: subject,
content_type: 'text/html'
)
end end ```_
Automatisierungsskripte¶
Umfassendes Monitoring-Script¶
```bash
!/bin/bash¶
Comprehensive Snorby monitoring and maintenance¶
Configuration¶
SNORBY_DIR="/opt/snorby" LOG_DIR="/var/log/snorby" BACKUP_DIR="/var/backups/snorby" PID_FILE="/var/run/snorby.pid"
Database configuration¶
DB_HOST="localhost" DB_USER="snorby" DB_PASS="snorbypassword" DB_NAME="snorby"
Monitoring thresholds¶
MAX_RESPONSE_TIME="10" MAX_MEMORY_USAGE="80" MAX_DISK_USAGE="90"
Create necessary directories¶
mkdir -p "\(LOG_DIR" "\)BACKUP_DIR"
Logging function¶
log_message() \{ echo "$(date '+%Y-%m-%d %H:%M:%S') - \(1"|tee -a "\)LOG_DIR/monitor.log" \}
Check Snorby web application¶
check_web_application() \{ log_message "Checking Snorby web application..."
local response_time
response_time=$(curl -o /dev/null -s -w '%\\\{time_total\\\}' http://localhost:3000/ 2>``/dev/null)
if [ $? -eq 0 ]; then
log_message "Web application is accessible (response time: $\\\\{response_time\\\\}s)"
# Check if response time is acceptable
if (( $(echo "$response_time > $MAX_RESPONSE_TIME"|bc -l) )); then
log_message "WARNING: Slow response time: $\\\\{response_time\\\\}s (threshold: $\\\\{MAX_RESPONSE_TIME\\\\}s)"
return 1
fi
return 0
else
log_message "ERROR: Web application is not accessible"
return 1
fi
\\}
Check Snorby process¶
check_snorby_process() \\{ log_message "Checking Snorby process..."
if systemctl is-active --quiet snorby; then
log_message "Snorby service is running"
# Check memory usage
local memory_usage
| | memory_usage=$(ps -o %mem -p $(pgrep -f "rails server") | tail -n 1 | tr -d ' ') | |
if [ -n "$memory_usage" ] && (( $(echo "$memory_usage > $MAX_MEMORY_USAGE"|bc -l) )); then
log_message "WARNING: High memory usage: $\\\\{memory_usage\\\\}% (threshold: $\\\\{MAX_MEMORY_USAGE\\\\}%)"
fi
return 0
else
log_message "ERROR: Snorby service is not running"
return 1
fi
\\}
Check database connectivity¶
check_database() \\{ log_message "Checking database connectivity..."
mysql -h "$DB_HOST" -u "$DB_USER" -p"$DB_PASS" "$DB_NAME" -e "SELECT 1;" >/dev/null 2>&1
if [ $? -eq 0 ]; then
log_message "Database connection successful"
# Check recent events
local recent_events
recent_events=$(mysql -h "$DB_HOST" -u "$DB_USER" -p"$DB_PASS" "$DB_NAME" -N -e "
SELECT COUNT(*) FROM event WHERE timestamp >= DATE_SUB(NOW(), INTERVAL 1 HOUR);
" 2>/dev/null)
log_message "Recent events (last hour): $recent_events"
# Check database size
local db_size
db_size=$(mysql -h "$DB_HOST" -u "$DB_USER" -p"$DB_PASS" "$DB_NAME" -N -e "
SELECT ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) AS 'DB Size in MB'
FROM information_schema.tables
WHERE table_schema='$DB_NAME';
" 2>/dev/null)
log_message "Database size: $\\\\{db_size\\\\} MB"
return 0
else
log_message "ERROR: Database connection failed"
return 1
fi
\\}
Check disk space¶
check_disk_space() \\{ log_message "Checking disk space..."
local usage
| | usage=\((df -h "\)SNORBY_DIR" | awk 'NR==2 \\{print $5\\}' | sed 's/%//') | |
log_message "Disk usage: $\\\\{usage\\\\}%"
if [ "$usage" -gt "$MAX_DISK_USAGE" ]; then
log_message "WARNING: High disk usage: $\\\\{usage\\\\}% (threshold: $\\\\{MAX_DISK_USAGE\\\\}%)"
return 1
fi
return 0
\\}
Check log files¶
check_log_files() \\{ log_message "Checking log files..."
local production_log="$SNORBY_DIR/log/production.log"
if [ -f "$production_log" ]; then
# Check for recent errors
local error_count
| | error_count=\((tail -n 100 "\)production_log" | grep -c "ERROR | FATAL" | | echo "0") | |
if [ "$error_count" -gt 5 ]; then
log_message "WARNING: High number of errors in production log: $error_count"
# Show recent errors
log_message "Recent errors:"
| | tail -n 100 "$production_log" | grep "ERROR | FATAL" | tail -n 5 | while read -r line; do | | log_message " $line" done fi
# Rotate large log files
local log_size
| | log_size=\((stat -c%s "\)production_log" 2>/dev/null | | echo "0") | |
if [ "$log_size" -gt 104857600 ]; then # 100MB
log_message "Rotating large production log file"
mv "$production_log" "$\\\\{production_log\\\\}.$(date +%Y%m%d-%H%M%S)"
touch "$production_log"
chown snorby:snorby "$production_log"
fi
fi
\\}
Performance optimization¶
optimize_performance() \\{ log_message "Running performance optimization..."
# Clear Rails cache
sudo -u snorby -i << 'EOF'
cd /opt/snorby bundle exec rake tmp:cache:clear RAILS_ENV=production bundle exec rake assets:clean RAILS_ENV=production EOF
# Optimize database
mysql -h "$DB_HOST" -u "$DB_USER" -p"$DB_PASS" "$DB_NAME" -e "
OPTIMIZE TABLE event;
OPTIMIZE TABLE signature;
ANALYZE TABLE event;
ANALYZE TABLE signature;
" >/dev/null 2>&1
# Clean old sessions
mysql -h "$DB_HOST" -u "$DB_USER" -p"$DB_PASS" "$DB_NAME" -e "
DELETE FROM sessions WHERE updated_at < DATE_SUB(NOW(), INTERVAL 7 DAY);
" >/dev/null 2>&1
log_message "Performance optimization completed"
\\}
Backup Snorby¶
backup_snorby() \\{ log_message "Backing up Snorby..."
local backup_file="$BACKUP_DIR/snorby-backup-$(date +%Y%m%d-%H%M%S).tar.gz"
# Backup application files and database
(
cd /opt
tar -czf "$backup_file" \
snorby/config/ \
snorby/db/migrate/ \
snorby/public/uploads/ \
2>/dev/null
)
# Backup database
mysqldump -h "$DB_HOST" -u "$DB_USER" -p"$DB_PASS" "$DB_NAME"|\
gzip > "$BACKUP_DIR/snorby-db-$(date +%Y%m%d-%H%M%S).sql.gz"
if [ $? -eq 0 ]; then
log_message "Backup created: $backup_file"
# Keep only last 7 days of backups
find "$BACKUP_DIR" -name "snorby-*.tar.gz" -mtime +7 -delete
find "$BACKUP_DIR" -name "snorby-db-*.sql.gz" -mtime +7 -delete
return 0
else
log_message "ERROR: Backup failed"
return 1
fi
\\}
Restart Snorby service¶
restart_snorby() \\{ log_message "Restarting Snorby service..."
systemctl restart snorby
# Wait for service to start
sleep 10
if systemctl is-active --quiet snorby; then
log_message "Snorby service restarted successfully"
return 0
else
log_message "ERROR: Failed to restart Snorby service"
return 1
fi
\\}
Generate health report¶
generate_health_report() \\{ log_message "Generating health report..."
local report_file="$LOG_DIR/health-report-$(date +%Y%m%d-%H%M%S).html"
cat > "$report_file" << EOF
Snorby Health Report
Generated: $(date)
System Status
Component | Status | Details |
---|---|---|
Web Application | OK | Accessible |
Web Application | ERROR | Not accessible |
Snorby Process | OK | Running |
Snorby Process | ERROR | Not running |
Database | OK | Connected |
Database | ERROR | Connection failed |
Disk Space | OK | Usage: $disk_usage |
Recent Activity
| |$(tail -n 20 "$LOG_DIR/monitor.log" 2>/dev/null | | echo "No recent activity logged")| |
EOF
log_message "Health report generated: $report_file"
\\}
Send alert notification¶
send_alert() \\{ local subject="\(1" local message="\)2"
# Send email if mail is configured
if command -v mail >/dev/null 2>&1; then
echo "$message"|mail -s "Snorby Alert: $subject" security@company.com
fi
# Log to syslog
logger -t snorby-monitor "$subject: $message"
log_message "Alert sent: $subject"
\\}
Main monitoring function¶
run_monitoring() \\{ log_message "Starting Snorby monitoring cycle"
local issues=0
# Run all checks
| | check_web_application | | ((issues++)) | | | | check_snorby_process | | ((issues++)) | | | | check_database | | ((issues++)) | | | | check_disk_space | | ((issues++)) | | check_log_files
# Performance optimization (weekly)
if [ "$(date +%u)" -eq 1 ] && [ "$(date +%H)" -eq 2 ]; then
optimize_performance
backup_snorby
fi
# Generate health report (daily)
if [ "$(date +%H)" -eq 6 ]; then
generate_health_report
fi
# Restart service if issues detected
if [ "$issues" -gt 2 ]; then
log_message "Multiple issues detected, attempting service restart"
restart_snorby
fi
# Send alerts if issues found
if [ "$issues" -gt 0 ]; then
send_alert "System Issues Detected" "Found $issues issues during monitoring. Check logs for details."
fi
log_message "Monitoring cycle completed with $issues issues"
return $issues
\\}
Command line interface¶
case "$\\{1:-monitor\\}" in "monitor") run_monitoring ;; "restart") restart_snorby ;; "backup") backup_snorby ;; "optimize") optimize_performance ;; "report") generate_health_report ;; *) | | echo "Usage: $0 \\{monitor | restart | backup | optimize | report\\}" | | echo "" echo "Commands:" echo " monitor - Run complete monitoring cycle (default)" echo " restart - Restart Snorby service" echo " backup - Backup Snorby application and database" echo " optimize - Run performance optimization" echo " report - Generate health report" exit 1 ;; esac ```_
Integrationsbeispiele¶
SIEM Integration¶
```ruby
SIEM integration for Snorby¶
File: /opt/snorby/lib/siem_integration.rb¶
class SiemIntegration def self.export_to_splunk(time_range = 1.hour) events = Event.includes(:signature) .where('timestamp >= ?', time_range.ago)
| | events.find_each do | event | | | splunk_event = \\{ time: event.timestamp.to_i, source: 'snorby', sourcetype: 'snort:alert', index: 'security', event: \\{ sid: event.sid, cid: event.cid, signature: event.signature.sig_name, signature_id: event.signature.sig_id, src_ip: event.src_ip, src_port: event.src_port, dst_ip: event.dst_ip, dst_port: event.dst_port, protocol: event.ip_proto, priority: event.signature.sig_priority, classification: event.signature.sig_class_id \\} \\}
send_to_splunk_hec(splunk_event)
end
end
def self.send_to_splunk_hec(event_data) uri = URI(Rails.application.config.splunk_hec_url) http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true if uri.scheme == 'https'
request = Net::HTTP::Post.new(uri)
request['Authorization'] = "Splunk #\\\\{Rails.application.config.splunk_hec_token\\\\}"
request['Content-Type'] = 'application/json'
request.body = event_data.to_json
response = http.request(request)
unless response.code == '200'
Rails.logger.error "Failed to send event to Splunk: #\\\\{response.code\\\\} #\\\\{response.body\\\\}"
end
end
def self.export_to_elasticsearch(time_range = 1.hour) events = Event.includes(:signature) .where('timestamp >= ?', time_range.ago)
| | events.find_each do | event | | | es_event = \\{ '@timestamp' => event.timestamp.iso8601, source: \\{ ip: event.src_ip, port: event.src_port \\}, destination: \\{ ip: event.dst_ip, port: event.dst_port \\}, network: \\{ protocol: protocol_name(event.ip_proto) \\}, event: \\{ id: "#\\{event.sid\\}-#\\{event.cid\\}", category: 'network', type: 'alert', severity: severity_level(event.signature.sig_priority) \\}, rule: \\{ id: event.signature.sig_id, name: event.signature.sig_name, category: event.signature.sig_class_id \\} \\}
send_to_elasticsearch(es_event)
end
end
def self.send_to_elasticsearch(event_data) index_name = "snorby-#\\{Date.current.strftime('%Y.%m.%d')\\}" doc_id = event_data[:event][:id]
uri = URI("#\\\\{Rails.application.config.elasticsearch_url\\\\}/#\\\\{index_name\\\\}/_doc/#\\\\{doc_id\\\\}")
http = Net::HTTP.new(uri.host, uri.port)
request = Net::HTTP::Put.new(uri)
request['Content-Type'] = 'application/json'
request.body = event_data.to_json
response = http.request(request)
unless ['200', '201'].include?(response.code)
Rails.logger.error "Failed to send event to Elasticsearch: #\\\\{response.code\\\\} #\\\\{response.body\\\\}"
end
end
private
def self.protocol_name(proto_num) case proto_num when 1 then 'icmp' when 6 then 'tcp' when 17 then 'udp' else proto_num.to_s end end
def self.severity_level(priority) case priority when 1..2 then 'high' when 3..4 then 'medium' else 'low' end end end ```_
Fehlerbehebung¶
Gemeinsame Themen¶
Application Wird nicht gestartet: ```bash
Check Ruby version¶
ruby --version
Check Bundler¶
bundle --version
Check dependencies¶
cd /opt/snorby bundle check
Install missing dependencies¶
bundle install
Check database configuration¶
cat config/database.yml
Test database connection¶
bundle exec rails console production
In console: ActiveRecord::Base.connection.active?¶
Check logs¶
tail -f log/production.log ```_
** Probleme der Datenbankverbindung:** ```bash
Test MySQL connection¶
mysql -u snorby -p snorby -e "SELECT COUNT(*) FROM event;"
Check database permissions¶
mysql -u root -p -e "SHOW GRANTS FOR 'snorby'@'localhost';"
Verify database exists¶
mysql -u root -p -e "SHOW DATABASES;"|grep snorby
Check MySQL service¶
sudo systemctl status mysql ```_
Leistungsfragen: ```bash
Check system resources¶
top -p $(pgrep -f "rails server") free -h df -h
Check database performance¶
mysql -u snorby -p snorby -e "SHOW PROCESSLIST;"
Optimize database¶
mysql -u snorby -p snorby -e "OPTIMIZE TABLE event; OPTIMIZE TABLE signature;"
Clear Rails cache¶
cd /opt/snorby sudo -u snorby bundle exec rake tmp:cache:clear RAILS_ENV=production ```_
Leistungsoptimierung¶
Optimierung der Snorby-Leistung:
```bash
Ruby/Rails optimization¶
cat >> /opt/snorby/config/environments/production.rb << 'EOF'
Performance optimizations¶
config.cache_classes = true config.eager_load = true config.consider_all_requests_local = false config.action_controller.perform_caching = true config.cache_store = :memory_store, \\{ size: 64.megabytes \\} config.assets.compile = false config.assets.digest = true config.log_level = :warn EOF
Database optimization¶
mysql -u root -p << 'EOF' -- Optimize Snorby database USE snorby;
-- Add indexes for common queries CREATE INDEX idx_event_timestamp ON event (timestamp); CREATE INDEX idx_event_src_ip_timestamp ON event (src_ip, timestamp); CREATE INDEX idx_event_dst_ip_timestamp ON event (dst_ip, timestamp); CREATE INDEX idx_event_signature_timestamp ON event (sig_id, timestamp);
-- Optimize tables OPTIMIZE TABLE event; OPTIMIZE TABLE signature; ANALYZE TABLE event; ANALYZE TABLE signature; EOF
System optimization¶
echo "vm.swappiness=10" >> /etc/sysctl.conf sysctl -p ```_
Sicherheitsüberlegungen¶
Zugriffskontrolle¶
Web Application Security: - HTTPS implementieren für alle Snorby-Zugriffe - Verwenden Sie starke Authentifizierungsmechanismen - Durchführung von Sitzungszeiten und Management - Regelmäßige Sicherheitsupdates für Ruby und Rails - Überwachen Sie Zugriffsprotokolle für verdächtige Aktivität
** Datenbanksicherheit:** - Verwenden Sie dedizierte Datenbankbenutzer mit minimalen Privilegien - Implementierung der Datenbank-Verbindung Verschlüsselung - Regelmäßige Aktualisierung der Datenbanksicherheit - Datenbankzugriffsprotokolle überwachen - Implementierung der Backup-Verschlüsselung
Datenschutz¶
Ereignisse Datensicherheit: - Verschlüsseln Sie sensible Ereignisdaten im Ruhezustand - Umsetzung von Datenschutzbestimmungen - Sicherer Zugriff auf Paketerfassungsdaten - Regelmäßige Reinigung von temporären Dateien - Implementierung der Zugangsprotokollierung für Ereignisdaten
** Sicherheit:** - Regelmäßige Sicherheitsbewertungen der Snorby-Infrastruktur - Monitor für unberechtigte Zugriffsversuche - Durchführung richtiger Backup- und Recovery-Verfahren - Regelmäßige Aktualisierungen von Snorby und Abhängigkeiten - Incident Response Verfahren für Snorby Kompromiss