Overview
Security incident response encompasses the systematic process of detecting, analyzing, containing, eradicating, and recovering from security events that threaten system integrity, confidentiality, or availability. An incident represents any event that violates security policies or poses risk to organizational assets. The response process transforms reactive crisis management into structured procedures that minimize damage, reduce recovery time, and prevent recurrence.
Modern software systems face constant security threats ranging from automated vulnerability scanning to targeted attacks. Without structured incident response capabilities, organizations experience prolonged exposure to threats, increased damage from security breaches, and regulatory compliance failures. The incident response process integrates with development workflows, operational procedures, and business continuity planning.
The incident response lifecycle follows six phases: preparation, detection, analysis, containment, eradication, and recovery. Each phase requires specific technical capabilities, defined roles, and documented procedures. Preparation establishes monitoring infrastructure and response procedures before incidents occur. Detection identifies potential security events through automated monitoring and manual observation. Analysis determines incident scope, impact, and attack vectors. Containment limits damage while preserving evidence. Eradication removes threat actors and vulnerabilities. Recovery restores normal operations while maintaining enhanced monitoring.
Ruby applications require incident response capabilities tailored to web application architectures, database interactions, and API endpoints. Response procedures must address common vulnerabilities in Ruby web frameworks, dependency chains, and deployment configurations. The Ruby ecosystem provides tools for security monitoring, logging, vulnerability scanning, and automated response actions.
Key Principles
Security incident response operates on several fundamental principles that guide effective detection and resolution. These principles apply across different incident types, system architectures, and organizational contexts.
Rapid Detection and Response: Time between compromise and detection directly correlates with damage severity. Attackers establish persistence, move laterally, and exfiltrate data during undetected access periods. Detection systems monitor application logs, system metrics, network traffic, and user behavior for anomalies indicating security incidents. Response procedures activate immediately upon detection, minimizing attacker dwell time.
Evidence Preservation: Incident investigation requires maintaining evidence integrity throughout the response process. Evidence includes log files, memory dumps, disk images, network captures, and system configurations. Response actions must preserve evidence before making system changes. Evidence supports forensic analysis, legal proceedings, and post-incident reviews. Chain of custody documentation tracks evidence handling from collection through analysis.
Containment Before Eradication: Containment prevents incident spread before removing the threat. Immediate eradication risks losing attack vector information and allowing attacker migration to undetected systems. Short-term containment isolates affected systems while maintaining monitoring capabilities. Long-term containment implements temporary fixes enabling business continuity during investigation.
Documented Procedures: Security incidents create high-stress situations requiring rapid decisions with incomplete information. Documented response procedures provide decision frameworks, contact information, and action checklists. Procedures define roles, responsibilities, escalation paths, and communication protocols. Documentation enables consistent response across different incident types and response team members.
Defense in Depth: No single security control prevents all incidents. Defense in depth implements multiple security layers ensuring that control failures at one layer do not compromise entire systems. Incident response assumes breach and prepares detection and response capabilities throughout infrastructure layers. Multiple detection mechanisms identify different attack stages and techniques.
Continuous Improvement: Post-incident analysis identifies security gaps, process failures, and improvement opportunities. Lessons learned feed back into security controls, monitoring capabilities, and response procedures. Regular incident response exercises test procedures and identify weaknesses before actual incidents. Metrics track detection time, response effectiveness, and recurrence rates.
Communication Management: Effective incident response coordinates multiple stakeholders including technical teams, management, legal counsel, and potentially affected parties. Communication protocols define who receives incident notifications, what information to share, and when to communicate. External communication requirements vary based on incident type, data exposure, and regulatory obligations.
Implementation Approaches
Organizations implement incident response capabilities through structured programs combining technical infrastructure, defined processes, and trained personnel. Implementation approaches vary based on organization size, risk profile, and resource availability.
Centralized Response Team: Dedicated security teams handle all incident response activities. Team members possess specialized skills in digital forensics, malware analysis, and threat intelligence. Centralized teams maintain deep expertise and consistent response quality across incidents. This approach requires significant investment in specialized personnel and tools. Organizations with high security risk profiles or regulatory requirements typically adopt centralized response teams. The team develops playbooks for common incident types, maintains forensic tools and infrastructure, and conducts regular training exercises.
Distributed Response Model: Technical teams throughout the organization receive incident response training and handle incidents within their domains. Development teams respond to application security incidents, infrastructure teams handle system compromises, and network teams address network-based attacks. Security teams provide coordination, guidance, and specialized support. This approach scales better for large organizations with multiple technical teams. Distributed models require consistent training, clear escalation procedures, and strong coordination mechanisms. Response quality varies based on individual team capabilities and experience levels.
Hybrid Approach: Organizations combine centralized security teams with distributed response capabilities. Security teams handle high-severity incidents, provide specialized analysis, and coordinate complex responses. Technical teams manage routine security events within established procedures and escalate complex incidents to central teams. Hybrid models balance expertise depth with organizational scale. Security teams develop response procedures and provide training to technical teams. Technical teams handle first-level response and evidence collection, escalating when incidents exceed defined thresholds.
Outsourced Security Operations: Organizations engage external security operations centers (SOCs) or managed detection and response (MDR) providers for incident response capabilities. External providers monitor security events, conduct initial analysis, and coordinate response activities. This approach provides 24/7 monitoring without internal staffing requirements. Organizations maintain internal security teams for strategic direction, procedure development, and system knowledge. Outsourcing works well for organizations lacking specialized security expertise or requiring continuous monitoring coverage. Effective outsourcing requires clear service level agreements, well-defined escalation procedures, and regular coordination between internal and external teams.
Automated Response Platform: Automated systems detect security events, analyze incidents, and execute response actions without human intervention. Security orchestration, automation, and response (SOAR) platforms integrate security tools, execute playbooks, and coordinate response workflows. Automation handles high-volume, low-complexity incidents enabling human analysts to focus on complex investigations. Automated response requires careful implementation to avoid false positives triggering inappropriate actions. Organizations gradually expand automation scope as procedures mature and confidence increases. The approach combines automated data collection, analysis, and containment with human decision-making for critical actions.
Ruby Implementation
Ruby applications implement incident response capabilities through logging infrastructure, monitoring integrations, and automated response mechanisms. The implementation focuses on detection, evidence collection, and containment actions.
# Centralized security event logging
class SecurityLogger
def initialize
@logger = Logger.new('log/security.log', 'daily')
@logger.level = Logger::INFO
@logger.formatter = proc do |severity, datetime, progname, msg|
{
timestamp: datetime.iso8601,
severity: severity,
event_type: progname,
details: msg,
host: Socket.gethostname,
pid: Process.pid
}.to_json + "\n"
end
end
def log_authentication_failure(user_id, ip_address, reason)
@logger.warn('authentication_failure') do
{
user_id: user_id,
ip_address: ip_address,
reason: reason,
user_agent: request_user_agent
}
end
end
def log_suspicious_activity(activity_type, details)
@logger.error('suspicious_activity') do
{
activity_type: activity_type,
details: details,
stack_trace: caller[0..5]
}
end
end
def log_data_access(user_id, resource_type, resource_id, action)
@logger.info('data_access') do
{
user_id: user_id,
resource_type: resource_type,
resource_id: resource_id,
action: action
}
end
end
end
This logging implementation captures security-relevant events in structured JSON format enabling automated analysis. The daily rotation prevents log files from growing unbounded while maintaining historical data for forensic analysis. Structured logging enables parsing by log aggregation systems and security information and event management (SIEM) platforms.
# Real-time security event monitoring
class SecurityMonitor
def initialize
@redis = Redis.new
@threshold_window = 300 # 5 minutes
@alert_channel = ENV['SECURITY_ALERT_CHANNEL']
end
def track_failed_login(ip_address)
key = "failed_login:#{ip_address}"
count = @redis.incr(key)
@redis.expire(key, @threshold_window)
if count >= 5
trigger_alert(
type: 'brute_force_attempt',
ip_address: ip_address,
attempt_count: count,
time_window: @threshold_window
)
block_ip_address(ip_address)
end
end
def detect_sql_injection(params)
sql_patterns = [
/(\bOR\b|\bAND\b).*?=.*?=/i,
/UNION.*?SELECT/i,
/;\s*DROP\s+TABLE/i,
/--/,
/\/\*.*?\*\//
]
params.each do |key, value|
next unless value.is_a?(String)
sql_patterns.each do |pattern|
if value.match?(pattern)
trigger_alert(
type: 'sql_injection_attempt',
parameter: key,
value: value[0..100],
pattern: pattern.source
)
return true
end
end
end
false
end
def monitor_unusual_data_access(user_id, access_count, time_period)
key = "data_access:#{user_id}:#{Time.now.to_i / time_period}"
current = @redis.incr(key)
@redis.expire(key, time_period * 2)
baseline = get_user_baseline(user_id)
if current > baseline * 3
trigger_alert(
type: 'unusual_data_access',
user_id: user_id,
current_count: current,
baseline: baseline,
deviation: current.to_f / baseline
)
end
end
private
def trigger_alert(details)
alert = {
timestamp: Time.now.iso8601,
severity: determine_severity(details[:type]),
**details
}
@redis.publish(@alert_channel, alert.to_json)
SecurityLogger.new.log_suspicious_activity(details[:type], details)
end
def block_ip_address(ip_address)
# Implement IP blocking through firewall or application layer
# This could integrate with cloud provider APIs or local iptables
end
def get_user_baseline(user_id)
# Retrieve historical access patterns for the user
@redis.get("baseline:#{user_id}").to_i || 50
end
def determine_severity(event_type)
severity_map = {
'brute_force_attempt' => 'high',
'sql_injection_attempt' => 'critical',
'unusual_data_access' => 'medium'
}
severity_map[event_type] || 'low'
end
end
The monitoring system detects attack patterns in real-time by tracking event frequencies and comparing current behavior against baselines. Redis provides fast access to counters and temporary data enabling sub-second threat detection. The alert system publishes to message channels allowing multiple response systems to react simultaneously.
# Automated incident response actions
class IncidentResponder
def initialize
@logger = SecurityLogger.new
@notifier = SlackNotifier.new(ENV['INCIDENT_WEBHOOK_URL'])
end
def respond_to_incident(incident_type, context)
incident = create_incident_record(incident_type, context)
case incident_type
when 'unauthorized_access'
handle_unauthorized_access(incident, context)
when 'data_exfiltration'
handle_data_exfiltration(incident, context)
when 'malware_detection'
handle_malware_detection(incident, context)
when 'privilege_escalation'
handle_privilege_escalation(incident, context)
end
notify_security_team(incident)
end
private
def handle_unauthorized_access(incident, context)
# Immediate containment
revoke_user_sessions(context[:user_id])
disable_account(context[:user_id])
# Evidence collection
collect_access_logs(context[:user_id], lookback: 24.hours)
snapshot_current_state(context)
# Analysis
identify_accessed_resources(context[:user_id])
check_data_modifications(context[:user_id])
incident.update(
status: 'contained',
actions_taken: [
'revoked_sessions',
'disabled_account',
'collected_evidence'
]
)
end
def handle_data_exfiltration(incident, context)
# Rate limiting
apply_network_throttle(context[:ip_address])
# Block further access
add_ip_to_blocklist(context[:ip_address])
revoke_api_keys(context[:user_id])
# Evidence preservation
capture_network_traffic(context[:session_id])
log_data_access_trail(context[:user_id])
# Impact assessment
affected_records = identify_exfiltrated_data(context)
incident.update(
impact: {
record_count: affected_records.count,
data_types: affected_records.map(&:type).uniq,
sensitivity: determine_data_sensitivity(affected_records)
}
)
end
def revoke_user_sessions(user_id)
# Clear all active sessions
Session.where(user_id: user_id).destroy_all
# Invalidate authentication tokens
AuthToken.where(user_id: user_id).update_all(revoked_at: Time.now)
@logger.log_security_action('session_revocation', user_id: user_id)
end
def collect_access_logs(user_id, lookback:)
start_time = Time.now - lookback
logs = AccessLog.where(user_id: user_id)
.where('created_at > ?', start_time)
.order(created_at: :desc)
# Store in incident evidence collection
evidence_file = "evidence/access_logs_#{user_id}_#{Time.now.to_i}.json"
File.write(evidence_file, logs.to_json)
evidence_file
end
def notify_security_team(incident)
message = format_incident_notification(incident)
@notifier.send_alert(message, severity: incident.severity)
# Page on-call if critical
if incident.severity == 'critical'
PagerDutyService.trigger_incident(
title: "Critical Security Incident: #{incident.type}",
details: incident.to_hash
)
end
end
end
Automated response systems execute containment actions immediately upon incident detection. The response varies by incident type following predefined playbooks. Evidence collection occurs before containment actions when possible, but critical incidents prioritize containment over evidence preservation. Response actions log to audit trails supporting post-incident analysis.
# Incident management and tracking
class SecurityIncident < ApplicationRecord
enum status: {
detected: 0,
analyzing: 1,
contained: 2,
eradicating: 3,
recovering: 4,
closed: 5
}
enum severity: {
low: 0,
medium: 1,
high: 2,
critical: 3
}
has_many :incident_actions, dependent: :destroy
has_many :incident_notes, dependent: :destroy
has_many :evidence_items, dependent: :destroy
def escalate!(new_severity, reason)
transaction do
update!(severity: new_severity)
incident_notes.create!(
author: 'system',
content: "Escalated to #{new_severity}: #{reason}",
note_type: 'escalation'
)
SecurityMailer.escalation_notification(self).deliver_later
end
end
def add_evidence(evidence_type, data, source)
evidence_items.create!(
evidence_type: evidence_type,
data: data,
source: source,
collected_at: Time.now,
chain_of_custody: [
{
action: 'collected',
by: source,
at: Time.now.iso8601
}
]
)
end
def timeline
[
{ event: 'detected', timestamp: created_at },
*incident_actions.order(:created_at).map do |action|
{ event: action.action_type, timestamp: action.created_at }
end,
{ event: 'closed', timestamp: updated_at } if closed?
]
end
def generate_report
{
incident_id: id,
type: incident_type,
severity: severity,
detected_at: created_at,
resolved_at: updated_at,
duration: time_to_resolve,
timeline: timeline,
actions_taken: incident_actions.pluck(:action_type),
evidence_collected: evidence_items.count,
notes: incident_notes.pluck(:content),
lessons_learned: lessons_learned_summary
}
end
private
def time_to_resolve
return nil unless closed?
((updated_at - created_at) / 3600.0).round(2) # hours
end
end
Incident tracking systems maintain complete records of detection, response, and resolution. The status progression follows the incident lifecycle from detection through closure. Evidence items track chain of custody ensuring admissibility in legal proceedings. Timeline reconstruction supports post-incident analysis and lessons learned documentation.
Practical Examples
Real-world incident scenarios demonstrate response procedures across common security event types. Each example follows the detection, analysis, containment, eradication, and recovery phases.
SQL Injection Attack Detection and Response
An application monitoring system detects repeated database errors with unusual SQL syntax. The security monitor identifies potential SQL injection attempts through parameter pattern matching.
# Detection phase
monitor = SecurityMonitor.new
incident_detected = false
params = {
user_search: "admin' OR '1'='1",
filter: "'; DROP TABLE users; --"
}
if monitor.detect_sql_injection(params)
incident_detected = true
# Create incident record
incident = SecurityIncident.create!(
incident_type: 'sql_injection',
severity: :critical,
status: :detected,
source_ip: request.remote_ip,
affected_resource: 'user_search_endpoint',
initial_details: {
parameters: params,
user_id: current_user&.id,
timestamp: Time.now.iso8601
}
)
# Immediate response
responder = IncidentResponder.new
# Block the attacking IP
responder.block_ip_address(request.remote_ip)
# Collect evidence
incident.add_evidence(
'request_logs',
RequestLog.where(ip_address: request.remote_ip)
.where('created_at > ?', 1.hour.ago)
.to_json,
'application_logs'
)
# Check for successful exploitation
suspicious_queries = DatabaseQueryLog.where(
'query LIKE ? OR query LIKE ?',
'%DROP TABLE%',
"%OR '1'='1%"
).where('created_at > ?', 24.hours.ago)
if suspicious_queries.any?
incident.escalate!(:critical, 'Potential successful SQL injection detected')
# Enable enhanced database auditing
ActiveRecord::Base.connection.execute(
"SET log_statement = 'all'"
)
end
end
The response blocks the attacking IP immediately, preventing further exploitation attempts. Evidence collection captures request logs before containment actions modify system state. Database query logs identify whether the attack succeeded in executing unauthorized SQL commands. Enhanced auditing enables detailed forensic analysis during investigation.
Authentication Compromise and Lateral Movement
Multiple failed login attempts from geographically dispersed locations indicate credential stuffing attacks. Successful authentication from unusual locations suggests account compromise.
class AuthenticationIncidentDetector
def initialize
@monitor = SecurityMonitor.new
@geoip = GeoIP.new('geoip_database.dat')
end
def analyze_login_pattern(user_id, current_ip)
recent_logins = Login.where(user_id: user_id)
.where('created_at > ?', 24.hours.ago)
.order(created_at: :desc)
return nil if recent_logins.count < 2
# Check for impossible travel
current_location = @geoip.lookup(current_ip)
last_login = recent_logins.second
last_location = @geoip.lookup(last_login.ip_address)
distance = calculate_distance(current_location, last_location)
time_diff = (Time.now - last_login.created_at) / 3600.0 # hours
max_possible_speed = distance / time_diff # km/h
if max_possible_speed > 1000 # Faster than commercial flight
create_compromise_incident(
user_id: user_id,
suspicious_ip: current_ip,
previous_ip: last_login.ip_address,
reason: 'impossible_travel',
details: {
distance_km: distance,
time_hours: time_diff,
implied_speed: max_possible_speed
}
)
end
# Check for simultaneous sessions
active_sessions = Session.where(user_id: user_id)
.where('updated_at > ?', 15.minutes.ago)
if active_sessions.count > 1
session_ips = active_sessions.pluck(:ip_address).uniq
if session_ips.count > 1
create_compromise_incident(
user_id: user_id,
suspicious_ip: current_ip,
reason: 'simultaneous_sessions',
details: {
active_sessions: session_ips,
session_count: active_sessions.count
}
)
end
end
end
private
def create_compromise_incident(attrs)
incident = SecurityIncident.create!(
incident_type: 'account_compromise',
severity: :high,
status: :detected,
affected_user: attrs[:user_id],
source_ip: attrs[:suspicious_ip],
initial_details: attrs
)
# Immediate containment
responder = IncidentResponder.new
responder.respond_to_incident('unauthorized_access', attrs)
# Force password reset
user = User.find(attrs[:user_id])
user.update!(
password_reset_required: true,
password_reset_token: SecureRandom.urlsafe_base64(32)
)
# Notify user
UserMailer.security_alert(user, incident).deliver_now
incident
end
def calculate_distance(loc1, loc2)
# Haversine formula for great circle distance
lat1, lon1 = loc1[:latitude], loc1[:longitude]
lat2, lon2 = loc2[:latitude], loc2[:longitude]
rad_per_deg = Math::PI / 180
rkm = 6371 # Earth radius in kilometers
dlat_rad = (lat2 - lat1) * rad_per_deg
dlon_rad = (lon2 - lon1) * rad_per_deg
lat1_rad = lat1 * rad_per_deg
lat2_rad = lat2 * rad_per_deg
a = Math.sin(dlat_rad / 2)**2 +
Math.cos(lat1_rad) * Math.cos(lat2_rad) *
Math.sin(dlon_rad / 2)**2
c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a))
rkm * c
end
end
Geographic analysis detects physically impossible login patterns indicating credential compromise. The system forces immediate password resets and session termination upon compromise detection. User notification enables legitimate users to secure their accounts and report unauthorized access.
Data Breach Response and Impact Assessment
Unusual database queries accessing large data volumes trigger data exfiltration alerts. The response must determine what data was accessed, contain ongoing access, and assess regulatory notification requirements.
class DataBreachResponder
def investigate_potential_breach(incident_id)
incident = SecurityIncident.find(incident_id)
# Analyze database access patterns
suspicious_user = incident.affected_user
start_time = incident.created_at - 1.hour
accessed_records = AuditLog.where(user_id: suspicious_user)
.where('created_at > ?', start_time)
.where(action: ['read', 'export'])
# Categorize accessed data
data_inventory = categorize_accessed_data(accessed_records)
# Assess regulatory implications
regulatory_impact = assess_regulatory_impact(data_inventory)
# Update incident with impact assessment
incident.update!(
impact_assessment: {
records_accessed: accessed_records.count,
data_categories: data_inventory.keys,
pii_exposed: data_inventory[:personal_information].present?,
phi_exposed: data_inventory[:health_information].present?,
pci_exposed: data_inventory[:payment_information].present?,
regulatory_notifications_required: regulatory_impact[:notifications],
estimated_affected_individuals: calculate_affected_individuals(accessed_records)
}
)
# Trigger notification workflow if required
if regulatory_impact[:notifications].any?
trigger_breach_notification_workflow(incident, regulatory_impact)
end
# Preserve evidence
create_forensic_image(suspicious_user)
collect_network_logs(incident.source_ip)
incident
end
private
def categorize_accessed_data(audit_logs)
categories = Hash.new { |h, k| h[k] = [] }
audit_logs.each do |log|
record = log.auditable
if record.respond_to?(:data_classification)
category = record.data_classification
categories[category] << log
end
end
categories
end
def assess_regulatory_impact(data_inventory)
notifications = []
# GDPR assessment
if data_inventory[:personal_information].any?
notifications << {
regulation: 'GDPR',
deadline: 72.hours.from_now,
authority: 'EU Data Protection Authority'
}
end
# HIPAA assessment
if data_inventory[:health_information].any?
notifications << {
regulation: 'HIPAA',
deadline: 60.days.from_now,
authority: 'HHS Office for Civil Rights'
}
end
{ notifications: notifications }
end
def trigger_breach_notification_workflow(incident, impact)
BreachNotificationWorkflow.create!(
incident: incident,
required_notifications: impact[:notifications],
legal_review_required: true,
pr_coordination_required: incident.impact_assessment[:estimated_affected_individuals] > 500
)
# Alert legal team
LegalTeamMailer.breach_notification_required(incident, impact).deliver_now
end
end
Breach response prioritizes impact assessment to determine regulatory obligations. Data classification guides notification requirements based on affected data types. The system preserves evidence while conducting forensic analysis to determine breach scope and attack methods.
Tools & Ecosystem
Ruby applications integrate with security tools and platforms for comprehensive incident response capabilities. The ecosystem includes monitoring tools, log aggregation platforms, vulnerability scanners, and security automation frameworks.
Security Monitoring and SIEM Integration
Security information and event management platforms aggregate logs from multiple sources, correlate security events, and generate alerts. Ruby applications integrate through structured logging and API connections.
# Syslog integration for centralized logging
require 'syslog/logger'
class SyslogSecurityLogger
def initialize
@logger = Syslog::Logger.new('myapp')
end
def log_security_event(event_type, severity, details)
priority = map_severity_to_priority(severity)
message = {
event_type: event_type,
severity: severity,
timestamp: Time.now.iso8601,
application: 'myapp',
environment: Rails.env,
details: details
}.to_json
@logger.send(priority, message)
end
private
def map_severity_to_priority(severity)
{
'critical' => :crit,
'high' => :error,
'medium' => :warn,
'low' => :info
}[severity] || :info
end
end
# Splunk HTTP Event Collector integration
class SplunkLogger
def initialize
@endpoint = ENV['SPLUNK_HEC_ENDPOINT']
@token = ENV['SPLUNK_HEC_TOKEN']
end
def send_event(event_data)
event = {
time: Time.now.to_f,
host: Socket.gethostname,
source: 'ruby_application',
sourcetype: 'security_event',
event: event_data
}
HTTParty.post(
@endpoint,
headers: {
'Authorization' => "Splunk #{@token}",
'Content-Type' => 'application/json'
},
body: event.to_json
)
end
end
Centralized logging enables cross-application correlation and long-term event retention. Syslog integration provides standardized log transport to SIEM platforms. HTTP event collectors support direct API integration with cloud-based security platforms.
Vulnerability Scanning and Dependency Management
Ruby applications use automated scanning tools to identify security vulnerabilities in application code and dependencies. Integration into CI/CD pipelines enables continuous security validation.
The bundler-audit gem scans Gemfile dependencies against vulnerability databases. Brakeman performs static analysis of Rails applications identifying common security issues. These tools integrate into development workflows providing early vulnerability detection.
# Automated security scanning in CI/CD pipeline
namespace :security do
desc 'Run security scans'
task scan: :environment do
results = {
timestamp: Time.now.iso8601,
scans: []
}
# Dependency vulnerability scan
bundler_output = `bundle-audit check --update`
results[:scans] << {
tool: 'bundler-audit',
status: $?.success? ? 'passed' : 'failed',
output: bundler_output
}
# Static code analysis
brakeman_output = `brakeman -f json -q`
brakeman_results = JSON.parse(brakeman_output)
results[:scans] << {
tool: 'brakeman',
status: brakeman_results['warnings'].empty? ? 'passed' : 'failed',
warnings: brakeman_results['warnings'].count,
output: brakeman_results
}
# Report to security dashboard
SecurityDashboard.report_scan_results(results)
# Fail build on critical vulnerabilities
critical_count = count_critical_issues(results)
if critical_count > 0
puts "Security scan failed: #{critical_count} critical issues found"
exit 1
end
end
def count_critical_issues(results)
results[:scans].sum do |scan|
case scan[:tool]
when 'bundler-audit'
scan[:output].scan(/Criticality: Critical/).count
when 'brakeman'
scan[:output]['warnings']&.count { |w| w['confidence'] == 'High' } || 0
else
0
end
end
end
end
Automated scanning identifies vulnerabilities before production deployment. Critical findings block deployment until remediation occurs. Regular scanning detects newly disclosed vulnerabilities in existing deployments.
Intrusion Detection and Web Application Firewalls
Ruby applications deploy behind web application firewalls (WAF) providing layer 7 attack protection. WAF integration requires configuring application behavior and monitoring WAF logs for blocked requests.
Rack middleware implements application-level attack detection and blocking. The middleware inspects requests before application processing, rejecting malicious requests at the edge.
# Custom Rack middleware for attack detection
class SecurityMiddleware
def initialize(app)
@app = app
@detector = ThreatDetector.new
end
def call(env)
request = Rack::Request.new(env)
# Check for common attack patterns
threat_level = @detector.analyze_request(request)
if threat_level >= ThreatDetector::BLOCK_THRESHOLD
log_blocked_request(request, threat_level)
return [
403,
{ 'Content-Type' => 'application/json' },
[{ error: 'Request blocked by security policy' }.to_json]
]
elsif threat_level >= ThreatDetector::WARN_THRESHOLD
log_suspicious_request(request, threat_level)
end
@app.call(env)
end
private
def log_blocked_request(request, threat_level)
SecurityIncident.create!(
incident_type: 'blocked_request',
severity: :medium,
status: :contained,
source_ip: request.ip,
initial_details: {
path: request.path,
method: request.request_method,
threat_level: threat_level,
user_agent: request.user_agent
}
)
end
end
class ThreatDetector
BLOCK_THRESHOLD = 80
WARN_THRESHOLD = 50
def analyze_request(request)
score = 0
# SQL injection patterns
score += 30 if detect_sql_injection_patterns(request.params)
# XSS patterns
score += 30 if detect_xss_patterns(request.params)
# Path traversal
score += 40 if detect_path_traversal(request.path)
# Suspicious user agents
score += 20 if suspicious_user_agent?(request.user_agent)
score
end
private
def detect_sql_injection_patterns(params)
patterns = [
/(\bOR\b|\bAND\b)\s+\d+\s*=\s*\d+/i,
/UNION.*SELECT/i,
/;\s*DROP\s+TABLE/i
]
params.values.any? do |value|
next false unless value.is_a?(String)
patterns.any? { |pattern| value.match?(pattern) }
end
end
def detect_xss_patterns(params)
patterns = [
/<script[^>]*>.*?<\/script>/i,
/javascript:/i,
/on\w+\s*=/i # Event handlers
]
params.values.any? do |value|
next false unless value.is_a?(String)
patterns.any? { |pattern| value.match?(pattern) }
end
end
def detect_path_traversal(path)
path.include?('../') || path.include?('..\\')
end
def suspicious_user_agent?(user_agent)
return false if user_agent.nil?
suspicious_patterns = [
/sqlmap/i,
/nikto/i,
/nmap/i,
/masscan/i
]
suspicious_patterns.any? { |pattern| user_agent.match?(pattern) }
end
end
Middleware-based protection operates before application logic executes, preventing exploit attempts from reaching vulnerable code. Threat scoring enables graduated responses from logging through request blocking based on attack severity.
Common Pitfalls
Security incident response faces numerous challenges leading to delayed detection, inadequate containment, and incomplete resolution. Understanding these pitfalls enables proactive mitigation.
Insufficient Logging and Monitoring: Applications lacking comprehensive logging cannot detect security incidents or reconstruct attack timelines. Missing authentication logs, data access logs, and system change logs create blind spots in security monitoring. Inadequate log retention prevents historical analysis and pattern detection. Applications must log security-relevant events including authentication attempts, authorization failures, data access, configuration changes, and system errors. Logs require structured formats enabling automated parsing and analysis. Retention periods must support forensic analysis and regulatory requirements.
Alert Fatigue and False Positives: Security monitoring systems generating excessive false alerts cause analysts to ignore legitimate incidents. Poorly tuned detection rules trigger on normal application behavior. Organizations must baseline normal activity, tune detection thresholds, and implement graduated alert severity levels. Alert consolidation and correlation reduce duplicate notifications. Regular review of alert accuracy identifies rules requiring refinement.
Delayed Incident Detection: Organizations discovering incidents weeks or months after initial compromise face extensive damage and complicated forensics. Delayed detection allows attackers to establish persistence, move laterally, and exfiltrate data. Real-time monitoring, anomaly detection, and behavioral analysis reduce detection time. Organizations must measure and track time-to-detection metrics, implementing improvements to reduce detection lag.
Evidence Destruction During Response: Containment actions that immediately shut down systems or revoke credentials destroy forensic evidence. Evidence in memory, temporary files, and active network connections disappears when systems reboot. Response procedures must preserve evidence before containment actions. Critical incidents require forensic image creation and memory dump collection before system changes. Chain of custody documentation tracks evidence handling maintaining admissibility.
Inadequate Containment Scope: Incomplete containment allows attackers to maintain access through undetected backdoors or compromised accounts. Organizations must identify all affected systems, compromised credentials, and attack vectors. Containment actions must address lateral movement paths and persistence mechanisms. Incomplete eradication enables attackers to regain access after initial containment.
Communication Failures: Security incidents require coordination across technical teams, management, legal, and public relations. Inadequate communication leads to conflicting actions, regulatory violations, and reputational damage. Organizations require predefined communication protocols, escalation procedures, and notification templates. External communication requires legal review and public relations coordination. Premature disclosure risks regulatory penalties and litigation.
Missing Incident Response Plans: Organizations without documented response procedures make inconsistent decisions under pressure. Ad-hoc responses miss critical steps, destroy evidence, and prolong resolution. Incident response plans document roles, procedures, contact information, and decision frameworks. Plans require regular testing through tabletop exercises and simulations. Updates incorporate lessons learned from actual incidents and evolving threats.
Reference
Incident Severity Classification
| Severity | Criteria | Response Time | Escalation |
|---|---|---|---|
| Critical | System compromise, data breach, service outage | Immediate | Security team, management, on-call |
| High | Unsuccessful breach attempt, privilege escalation, malware detection | 15 minutes | Security team, on-call |
| Medium | Multiple failed authentications, suspicious activity, policy violation | 1 hour | Security team |
| Low | Single failed authentication, minor policy violation | 4 hours | Security monitoring |
Common Incident Types
| Incident Type | Description | Primary Response |
|---|---|---|
| Unauthorized Access | Account compromise, credential theft | Revoke sessions, reset passwords, block IP |
| Data Breach | Unauthorized data access or exfiltration | Contain access, assess impact, legal notification |
| Malware Infection | Virus, ransomware, trojan detection | Isolate system, remove malware, restore from backup |
| Denial of Service | Service disruption from attack | Rate limiting, traffic filtering, upstream mitigation |
| SQL Injection | Database attack attempt | Block request, patch vulnerability, audit data |
| Cross-Site Scripting | XSS attack attempt | Sanitize input, implement CSP, block request |
| Privilege Escalation | Unauthorized permission elevation | Revoke elevated access, patch vulnerability |
| Insider Threat | Malicious employee activity | Evidence preservation, access revocation, HR coordination |
Response Phase Checklist
| Phase | Key Actions | Deliverables |
|---|---|---|
| Detection | Monitor alerts, analyze anomalies, validate incidents | Incident ticket, initial classification |
| Analysis | Determine scope, identify attack vector, assess impact | Impact assessment, affected systems list |
| Containment | Isolate systems, revoke access, block threats | Containment confirmation, evidence preservation |
| Eradication | Remove malware, patch vulnerabilities, eliminate backdoors | Vulnerability remediation, clean system confirmation |
| Recovery | Restore systems, validate functionality, enhance monitoring | System restoration, validation testing |
| Lessons Learned | Document timeline, identify improvements, update procedures | Incident report, procedure updates |
Evidence Collection Types
| Evidence Type | Collection Method | Preservation Requirements |
|---|---|---|
| Log Files | Automated export, API retrieval | Write-once storage, hash verification |
| Memory Dumps | Forensic tools, live system capture | Immediate analysis, encrypted storage |
| Disk Images | Forensic imaging, snapshot creation | Chain of custody, read-only mounting |
| Network Traffic | Packet capture, flow logs | Full packet retention, metadata indexing |
| Database Records | Query export, audit logs | Transaction logs, data integrity checks |
| Configuration Files | System backup, version control | Change tracking, baseline comparison |
Ruby Security Gems
| Gem | Purpose | Usage |
|---|---|---|
| bundler-audit | Dependency vulnerability scanning | CI/CD integration, pre-deployment checks |
| brakeman | Static security analysis for Rails | Automated code review, security scanning |
| rack-attack | Rate limiting and throttling | Brute force protection, API rate limiting |
| secure_headers | HTTP security header management | XSS protection, content security policy |
| devise | Authentication framework with security features | User authentication, session management |
| pundit | Authorization framework | Access control, permission management |
Incident Metrics
| Metric | Description | Target |
|---|---|---|
| Mean Time to Detect | Average time from compromise to detection | Under 1 hour |
| Mean Time to Respond | Average time from detection to initial response | Under 15 minutes |
| Mean Time to Contain | Average time from detection to containment | Under 1 hour |
| Mean Time to Resolve | Average time from detection to incident closure | Under 24 hours |
| False Positive Rate | Percentage of alerts that are not real incidents | Under 10 percent |
| Recurrence Rate | Percentage of incidents that recur after resolution | Under 5 percent |
Notification Requirements
| Regulation | Trigger | Timeline | Authority |
|---|---|---|---|
| GDPR | Personal data breach affecting EU residents | 72 hours | National Data Protection Authority |
| CCPA | Breach of California resident data | Without unreasonable delay | California Attorney General |
| HIPAA | Breach of protected health information | 60 days | HHS Office for Civil Rights |
| PCI DSS | Breach of cardholder data | Immediate | Card brands, acquiring bank |
| SOX | Material security incident affecting financial reporting | Immediate | SEC, audit committee |