beskar 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +796 -18
- data/app/controllers/concerns/beskar/controllers/security_tracking.rb +70 -0
- data/app/models/beskar/banned_ip.rb +152 -0
- data/app/models/beskar/security_event.rb +50 -0
- data/config/locales/en.yml +10 -0
- data/db/migrate/20251016000001_create_beskar_security_events.rb +25 -0
- data/db/migrate/20251016000002_create_beskar_banned_ips.rb +23 -0
- data/lib/beskar/configuration.rb +200 -0
- data/lib/beskar/engine.rb +105 -0
- data/lib/beskar/middleware/request_analyzer.rb +230 -0
- data/lib/beskar/middleware.rb +4 -0
- data/lib/beskar/models/security_trackable.rb +25 -0
- data/lib/beskar/models/security_trackable_authenticable.rb +167 -0
- data/lib/beskar/models/security_trackable_devise.rb +82 -0
- data/lib/beskar/models/security_trackable_generic.rb +355 -0
- data/lib/beskar/services/account_locker.rb +263 -0
- data/lib/beskar/services/device_detector.rb +250 -0
- data/lib/beskar/services/geolocation_service.rb +392 -0
- data/lib/beskar/services/ip_whitelist.rb +113 -0
- data/lib/beskar/services/rate_limiter.rb +257 -0
- data/lib/beskar/services/waf.rb +322 -0
- data/lib/beskar/templates/beskar_initializer.rb +107 -0
- data/lib/beskar/version.rb +1 -1
- data/lib/beskar.rb +31 -1
- data/lib/tasks/beskar_tasks.rake +112 -4
- metadata +108 -4
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
Beskar.configure do |config|
|
|
4
|
+
# ============================================================================
|
|
5
|
+
# Web Application Firewall (WAF) - ENABLED IN MONITOR MODE BY DEFAULT
|
|
6
|
+
# ============================================================================
|
|
7
|
+
# Detects and logs vulnerability scanning attempts (WordPress, phpMyAdmin, etc.)
|
|
8
|
+
# Start in monitor-only mode to observe patterns before enabling blocking.
|
|
9
|
+
#
|
|
10
|
+
config.waf = {
|
|
11
|
+
enabled: true, # Master switch for WAF
|
|
12
|
+
monitor_only: true, # LOG ONLY - does not block (recommended to start)
|
|
13
|
+
auto_block: true, # Auto-block IPs after threshold (when monitor_only=false)
|
|
14
|
+
block_threshold: 3, # Number of violations before blocking
|
|
15
|
+
violation_window: 1.hour, # Time window for counting violations
|
|
16
|
+
block_durations: [1.hour, 6.hours, 24.hours, 7.days], # Escalating ban durations
|
|
17
|
+
permanent_block_after: 5, # Permanent ban after N violations (nil = never)
|
|
18
|
+
create_security_events: true # Log violations to SecurityEvent table
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
# After monitoring for 24-48 hours, review logs and disable monitor_only:
|
|
22
|
+
# config.waf[:monitor_only] = false
|
|
23
|
+
|
|
24
|
+
# View WAF activity in logs:
|
|
25
|
+
# tail -f log/production.log | grep "Beskar::WAF"
|
|
26
|
+
|
|
27
|
+
# Query violations that would be blocked:
|
|
28
|
+
# Beskar::SecurityEvent.where(event_type: 'waf_violation')
|
|
29
|
+
# .where("metadata->>'would_be_blocked' = ?", 'true').count
|
|
30
|
+
|
|
31
|
+
# ============================================================================
|
|
32
|
+
# IP Whitelisting (RECOMMENDED)
|
|
33
|
+
# ============================================================================
|
|
34
|
+
# Trusted IPs bypass all blocking (bans, rate limits, WAF) while still
|
|
35
|
+
# logging activity for audit purposes.
|
|
36
|
+
#
|
|
37
|
+
# config.ip_whitelist = [
|
|
38
|
+
# "192.168.1.100", # Single IP address
|
|
39
|
+
# "10.0.0.0/24", # CIDR notation - entire subnet
|
|
40
|
+
# "172.16.0.0/16" # Larger CIDR range
|
|
41
|
+
# # Add your office IPs, monitoring services, trusted partners, etc.
|
|
42
|
+
# ]
|
|
43
|
+
|
|
44
|
+
# ============================================================================
|
|
45
|
+
# Security Event Tracking (OPTIONAL)
|
|
46
|
+
# ============================================================================
|
|
47
|
+
# Track authentication events for risk analysis and threat detection.
|
|
48
|
+
# Disable if you don't need historical security event data.
|
|
49
|
+
#
|
|
50
|
+
# config.security_tracking = {
|
|
51
|
+
# enabled: true, # Master switch for all tracking
|
|
52
|
+
# track_successful_logins: true, # Track successful authentications
|
|
53
|
+
# track_failed_logins: true, # Track failed authentication attempts
|
|
54
|
+
# auto_analyze_patterns: true # Enable automatic pattern analysis
|
|
55
|
+
# }
|
|
56
|
+
|
|
57
|
+
# ============================================================================
|
|
58
|
+
# Rate Limiting (OPTIONAL)
|
|
59
|
+
# ============================================================================
|
|
60
|
+
# Protect against brute force attacks by limiting authentication attempts.
|
|
61
|
+
#
|
|
62
|
+
# config.rate_limiting = {
|
|
63
|
+
# ip_attempts: {
|
|
64
|
+
# limit: 10, # Max attempts per IP
|
|
65
|
+
# period: 1.hour, # Time window
|
|
66
|
+
# exponential_backoff: true # Increase delay after each attempt
|
|
67
|
+
# },
|
|
68
|
+
# account_attempts: {
|
|
69
|
+
# limit: 5, # Max attempts per account
|
|
70
|
+
# period: 15.minutes,
|
|
71
|
+
# exponential_backoff: true
|
|
72
|
+
# },
|
|
73
|
+
# global_attempts: {
|
|
74
|
+
# limit: 100, # System-wide limit (DDoS protection)
|
|
75
|
+
# period: 1.minute,
|
|
76
|
+
# exponential_backoff: false
|
|
77
|
+
# }
|
|
78
|
+
# }
|
|
79
|
+
|
|
80
|
+
# ============================================================================
|
|
81
|
+
# Risk-Based Account Locking (OPTIONAL)
|
|
82
|
+
# ============================================================================
|
|
83
|
+
# Automatically lock accounts when authentication risk score is too high.
|
|
84
|
+
# Requires Devise :lockable module.
|
|
85
|
+
#
|
|
86
|
+
# config.risk_based_locking = {
|
|
87
|
+
# enabled: false, # Disabled by default
|
|
88
|
+
# risk_threshold: 75, # Lock if risk score >= this (0-100)
|
|
89
|
+
# lock_strategy: :devise_lockable, # Strategy: :devise_lockable, :custom, :none
|
|
90
|
+
# auto_unlock_time: 1.hour, # Time until automatic unlock
|
|
91
|
+
# notify_user: true, # Send notification on lock
|
|
92
|
+
# log_lock_events: true # Create security events for locks
|
|
93
|
+
# }
|
|
94
|
+
|
|
95
|
+
# ============================================================================
|
|
96
|
+
# IP Geolocation (OPTIONAL)
|
|
97
|
+
# ============================================================================
|
|
98
|
+
# Enhance risk assessment with geographic information.
|
|
99
|
+
# Requires MaxMind GeoLite2-City database (free with registration).
|
|
100
|
+
# Download from: https://dev.maxmind.com/geoip/geolite2-free-geolocation-data
|
|
101
|
+
#
|
|
102
|
+
# config.geolocation = {
|
|
103
|
+
# provider: :maxmind,
|
|
104
|
+
# maxmind_city_db_path: Rails.root.join('db', 'geoip', 'GeoLite2-City.mmdb').to_s,
|
|
105
|
+
# cache_ttl: 4.hours
|
|
106
|
+
# }
|
|
107
|
+
end
|
data/lib/beskar/version.rb
CHANGED
data/lib/beskar.rb
CHANGED
|
@@ -1,6 +1,36 @@
|
|
|
1
1
|
require "beskar/version"
|
|
2
|
+
require "beskar/configuration"
|
|
3
|
+
require "beskar/middleware"
|
|
4
|
+
require "beskar/middleware/request_analyzer"
|
|
5
|
+
require "beskar/models/security_trackable_generic"
|
|
6
|
+
require "beskar/models/security_trackable_devise"
|
|
7
|
+
require "beskar/models/security_trackable_authenticable"
|
|
8
|
+
require "beskar/models/security_trackable"
|
|
9
|
+
require "beskar/services/rate_limiter"
|
|
10
|
+
require "beskar/services/device_detector"
|
|
11
|
+
require "beskar/services/geolocation_service"
|
|
12
|
+
require "beskar/services/account_locker"
|
|
13
|
+
require "beskar/services/ip_whitelist"
|
|
14
|
+
require "beskar/services/waf"
|
|
2
15
|
require "beskar/engine"
|
|
3
16
|
|
|
4
17
|
module Beskar
|
|
5
|
-
|
|
18
|
+
class << self
|
|
19
|
+
attr_accessor :configuration
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def self.configure
|
|
23
|
+
self.configuration ||= Configuration.new
|
|
24
|
+
yield(configuration)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Convenience method to access the rate limiter
|
|
28
|
+
def self.rate_limiter
|
|
29
|
+
Services::RateLimiter
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Check if a request should be rate limited
|
|
33
|
+
def self.rate_limited?(request, user = nil)
|
|
34
|
+
Services::RateLimiter.is_rate_limited?(request, user)
|
|
35
|
+
end
|
|
6
36
|
end
|
data/lib/tasks/beskar_tasks.rake
CHANGED
|
@@ -1,4 +1,112 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
namespace :beskar do
|
|
4
|
+
desc "Install Beskar: copy migrations and create initializer"
|
|
5
|
+
task install: :environment do
|
|
6
|
+
puts "=" * 80
|
|
7
|
+
puts "Installing Beskar Security..."
|
|
8
|
+
puts "=" * 80
|
|
9
|
+
puts
|
|
10
|
+
|
|
11
|
+
# Copy migrations
|
|
12
|
+
puts "📦 Copying migrations..."
|
|
13
|
+
begin
|
|
14
|
+
Rake::Task["beskar:install:migrations"].invoke
|
|
15
|
+
rescue RuntimeError
|
|
16
|
+
# In development/test within the gem, this task might not exist
|
|
17
|
+
# In a real app using the gem, it will work fine
|
|
18
|
+
puts " (Skipping migration copy in gem development mode)"
|
|
19
|
+
end
|
|
20
|
+
puts "✓ Migrations ready"
|
|
21
|
+
puts
|
|
22
|
+
|
|
23
|
+
# Create initializer
|
|
24
|
+
initializer_path = Rails.root.join("config/initializers/beskar.rb")
|
|
25
|
+
|
|
26
|
+
if File.exist?(initializer_path)
|
|
27
|
+
puts "⚠️ Initializer already exists at config/initializers/beskar.rb"
|
|
28
|
+
print " Overwrite? (y/N): "
|
|
29
|
+
response = $stdin.gets.chomp.downcase
|
|
30
|
+
|
|
31
|
+
unless response == 'y' || response == 'yes'
|
|
32
|
+
puts " Skipping initializer creation"
|
|
33
|
+
puts
|
|
34
|
+
next_steps
|
|
35
|
+
exit
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
puts "📝 Creating initializer..."
|
|
40
|
+
template_path = File.expand_path("../beskar/templates/beskar_initializer.rb", __dir__)
|
|
41
|
+
FileUtils.cp(template_path, initializer_path)
|
|
42
|
+
puts "✓ Created config/initializers/beskar.rb"
|
|
43
|
+
puts
|
|
44
|
+
|
|
45
|
+
next_steps
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def next_steps
|
|
49
|
+
puts "=" * 80
|
|
50
|
+
puts "Beskar Security has been installed!"
|
|
51
|
+
puts "=" * 80
|
|
52
|
+
puts
|
|
53
|
+
puts "Next steps:"
|
|
54
|
+
puts
|
|
55
|
+
puts "1. Run migrations to create the security tables:"
|
|
56
|
+
puts
|
|
57
|
+
puts " bin/rails db:migrate"
|
|
58
|
+
puts
|
|
59
|
+
puts "2. Add the SecurityTrackable concern to your User model:"
|
|
60
|
+
puts
|
|
61
|
+
puts " # app/models/user.rb"
|
|
62
|
+
puts " class User < ApplicationRecord"
|
|
63
|
+
puts " include Beskar::SecurityTrackable"
|
|
64
|
+
puts " "
|
|
65
|
+
puts " devise :database_authenticatable, :registerable,"
|
|
66
|
+
puts " :recoverable, :rememberable, :validatable"
|
|
67
|
+
puts " # ... rest of your Devise modules"
|
|
68
|
+
puts " end"
|
|
69
|
+
puts
|
|
70
|
+
puts "3. Review the configuration file:"
|
|
71
|
+
puts
|
|
72
|
+
puts " config/initializers/beskar.rb"
|
|
73
|
+
puts
|
|
74
|
+
puts " By default, WAF is enabled in MONITOR-ONLY MODE. This means:"
|
|
75
|
+
puts " - Vulnerability scans are detected and logged"
|
|
76
|
+
puts " - No requests are blocked yet"
|
|
77
|
+
puts " - Security events are created for analysis"
|
|
78
|
+
puts
|
|
79
|
+
puts "4. Monitor WAF activity (recommended for 24-48 hours):"
|
|
80
|
+
puts
|
|
81
|
+
puts " # View all WAF logs"
|
|
82
|
+
puts " tail -f log/production.log | grep \"Beskar::WAF\""
|
|
83
|
+
puts " "
|
|
84
|
+
puts " # Check what would be blocked"
|
|
85
|
+
puts " rails console"
|
|
86
|
+
puts " > Beskar::SecurityEvent.where(event_type: 'waf_violation')"
|
|
87
|
+
puts " .where(\"metadata->>'would_be_blocked' = ?\", 'true').count"
|
|
88
|
+
puts
|
|
89
|
+
puts "5. When ready to enable blocking:"
|
|
90
|
+
puts
|
|
91
|
+
puts " # config/initializers/beskar.rb"
|
|
92
|
+
puts " config.waf = {"
|
|
93
|
+
puts " enabled: true,"
|
|
94
|
+
puts " monitor_only: false, # <-- Change this to false"
|
|
95
|
+
puts " # ... rest of config"
|
|
96
|
+
puts " }"
|
|
97
|
+
puts
|
|
98
|
+
puts "6. Optional: Add IP whitelist for trusted sources:"
|
|
99
|
+
puts
|
|
100
|
+
puts " # config/initializers/beskar.rb"
|
|
101
|
+
puts " config.ip_whitelist = ["
|
|
102
|
+
puts " \"YOUR_OFFICE_IP\","
|
|
103
|
+
puts " \"YOUR_MONITORING_SERVICE_IP\""
|
|
104
|
+
puts " ]"
|
|
105
|
+
puts
|
|
106
|
+
puts "=" * 80
|
|
107
|
+
puts "Documentation:"
|
|
108
|
+
puts " - README: https://github.com/humadroid-io/beskar"
|
|
109
|
+
puts " - WAF Monitor Mode: See MONITOR_ONLY_MODE.md"
|
|
110
|
+
puts "=" * 80
|
|
111
|
+
end
|
|
112
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: beskar
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Maciej Litwiniuk
|
|
@@ -23,6 +23,90 @@ dependencies:
|
|
|
23
23
|
- - ">="
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
25
|
version: 8.0.0
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: maxminddb
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - "~>"
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '0.1'
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - "~>"
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '0.1'
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: debug
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - ">="
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '0'
|
|
47
|
+
type: :development
|
|
48
|
+
prerelease: false
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - ">="
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: '0'
|
|
54
|
+
- !ruby/object:Gem::Dependency
|
|
55
|
+
name: devise
|
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - ">="
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: '0'
|
|
61
|
+
type: :development
|
|
62
|
+
prerelease: false
|
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - ">="
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: '0'
|
|
68
|
+
- !ruby/object:Gem::Dependency
|
|
69
|
+
name: ostruct
|
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
|
71
|
+
requirements:
|
|
72
|
+
- - ">="
|
|
73
|
+
- !ruby/object:Gem::Version
|
|
74
|
+
version: '0'
|
|
75
|
+
type: :development
|
|
76
|
+
prerelease: false
|
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
78
|
+
requirements:
|
|
79
|
+
- - ">="
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: '0'
|
|
82
|
+
- !ruby/object:Gem::Dependency
|
|
83
|
+
name: factory_bot_rails
|
|
84
|
+
requirement: !ruby/object:Gem::Requirement
|
|
85
|
+
requirements:
|
|
86
|
+
- - ">="
|
|
87
|
+
- !ruby/object:Gem::Version
|
|
88
|
+
version: '0'
|
|
89
|
+
type: :development
|
|
90
|
+
prerelease: false
|
|
91
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
92
|
+
requirements:
|
|
93
|
+
- - ">="
|
|
94
|
+
- !ruby/object:Gem::Version
|
|
95
|
+
version: '0'
|
|
96
|
+
- !ruby/object:Gem::Dependency
|
|
97
|
+
name: mocha
|
|
98
|
+
requirement: !ruby/object:Gem::Requirement
|
|
99
|
+
requirements:
|
|
100
|
+
- - ">="
|
|
101
|
+
- !ruby/object:Gem::Version
|
|
102
|
+
version: '0'
|
|
103
|
+
type: :development
|
|
104
|
+
prerelease: false
|
|
105
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
106
|
+
requirements:
|
|
107
|
+
- - ">="
|
|
108
|
+
- !ruby/object:Gem::Version
|
|
109
|
+
version: '0'
|
|
26
110
|
description: |-
|
|
27
111
|
Rails Security Shield is a comprehensive, Rails-native security engine designed to provide multi-layered protection for modern web applications. It actively defends against common threats by integrating a powerful Web Application Firewall (WAF) to block attacks like SQLi and XSS, an advanced bot detection system using JavaScript challenges and honeypots, and robust account takeover prevention to stop brute-force and credential stuffing attacks.
|
|
28
112
|
|
|
@@ -38,22 +122,42 @@ files:
|
|
|
38
122
|
- Rakefile
|
|
39
123
|
- app/assets/stylesheets/beskar/application.css
|
|
40
124
|
- app/controllers/beskar/application_controller.rb
|
|
125
|
+
- app/controllers/concerns/beskar/controllers/security_tracking.rb
|
|
41
126
|
- app/helpers/beskar/application_helper.rb
|
|
42
127
|
- app/jobs/beskar/application_job.rb
|
|
43
128
|
- app/mailers/beskar/application_mailer.rb
|
|
44
129
|
- app/models/beskar/application_record.rb
|
|
130
|
+
- app/models/beskar/banned_ip.rb
|
|
131
|
+
- app/models/beskar/security_event.rb
|
|
45
132
|
- app/views/layouts/beskar/application.html.erb
|
|
133
|
+
- config/locales/en.yml
|
|
46
134
|
- config/routes.rb
|
|
135
|
+
- db/migrate/20251016000001_create_beskar_security_events.rb
|
|
136
|
+
- db/migrate/20251016000002_create_beskar_banned_ips.rb
|
|
47
137
|
- lib/beskar.rb
|
|
138
|
+
- lib/beskar/configuration.rb
|
|
48
139
|
- lib/beskar/engine.rb
|
|
140
|
+
- lib/beskar/middleware.rb
|
|
141
|
+
- lib/beskar/middleware/request_analyzer.rb
|
|
142
|
+
- lib/beskar/models/security_trackable.rb
|
|
143
|
+
- lib/beskar/models/security_trackable_authenticable.rb
|
|
144
|
+
- lib/beskar/models/security_trackable_devise.rb
|
|
145
|
+
- lib/beskar/models/security_trackable_generic.rb
|
|
146
|
+
- lib/beskar/services/account_locker.rb
|
|
147
|
+
- lib/beskar/services/device_detector.rb
|
|
148
|
+
- lib/beskar/services/geolocation_service.rb
|
|
149
|
+
- lib/beskar/services/ip_whitelist.rb
|
|
150
|
+
- lib/beskar/services/rate_limiter.rb
|
|
151
|
+
- lib/beskar/services/waf.rb
|
|
152
|
+
- lib/beskar/templates/beskar_initializer.rb
|
|
49
153
|
- lib/beskar/version.rb
|
|
50
154
|
- lib/tasks/beskar_tasks.rake
|
|
51
|
-
homepage: https://humadroid.io/
|
|
155
|
+
homepage: https://humadroid.io/beskar
|
|
52
156
|
licenses:
|
|
53
157
|
- MIT
|
|
54
158
|
metadata:
|
|
55
|
-
homepage_uri: https://humadroid.io/
|
|
56
|
-
source_code_uri: https://github.com/
|
|
159
|
+
homepage_uri: https://humadroid.io/beskar
|
|
160
|
+
source_code_uri: https://github.com/humadroid-io/beskar
|
|
57
161
|
rdoc_options: []
|
|
58
162
|
require_paths:
|
|
59
163
|
- lib
|