feat: add captcha-backed forum security hardening
This commit is contained in:
147
config/forum_bot_protection.php
Normal file
147
config/forum_bot_protection.php
Normal file
@@ -0,0 +1,147 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'enabled' => env('FORUM_BOT_PROTECTION_ENABLED', true),
|
||||
|
||||
'thresholds' => [
|
||||
'allow' => 20,
|
||||
'log' => 20,
|
||||
'captcha' => 40,
|
||||
'moderate' => 60,
|
||||
'block' => 80,
|
||||
],
|
||||
|
||||
'honeypots' => [
|
||||
'fields' => ['homepage_url', 'company_name'],
|
||||
'penalty' => 60,
|
||||
],
|
||||
|
||||
'captcha' => [
|
||||
'provider' => env('FORUM_BOT_CAPTCHA_PROVIDER', 'turnstile'),
|
||||
'actions' => [
|
||||
'register',
|
||||
'login',
|
||||
'forum_topic_create',
|
||||
'forum_reply_create',
|
||||
'forum_post_update',
|
||||
'profile_update',
|
||||
'api_write',
|
||||
],
|
||||
'input' => env('FORUM_BOT_CAPTCHA_INPUT', ''),
|
||||
'message' => 'Complete the captcha challenge to continue.',
|
||||
],
|
||||
|
||||
'behavior' => [
|
||||
'new_account_days' => 7,
|
||||
'rapid_post_window_minutes' => 1,
|
||||
'rapid_post_threshold' => 5,
|
||||
'rapid_thread_threshold' => 2,
|
||||
'recent_action_window_seconds' => 45,
|
||||
'recent_action_threshold' => 6,
|
||||
'login_attempt_window_minutes' => 10,
|
||||
'login_attempt_threshold' => 8,
|
||||
'profile_update_threshold' => 6,
|
||||
'profile_update_window_minutes' => 60,
|
||||
'api_request_window_minutes' => 1,
|
||||
'api_request_threshold' => 100,
|
||||
'repeated_content_penalty' => 50,
|
||||
'new_account_links_penalty' => 30,
|
||||
'rapid_post_penalty' => 40,
|
||||
'recent_action_penalty' => 40,
|
||||
'login_burst_penalty' => 35,
|
||||
'profile_burst_penalty' => 20,
|
||||
'api_burst_penalty' => 60,
|
||||
],
|
||||
|
||||
'account_farm' => [
|
||||
'window_minutes' => 10,
|
||||
'register_attempt_threshold' => 10,
|
||||
'same_ip_users_threshold' => 5,
|
||||
'same_fingerprint_users_threshold' => 3,
|
||||
'same_pattern_users_threshold' => 3,
|
||||
'register_attempt_penalty' => 50,
|
||||
'same_ip_penalty' => 35,
|
||||
'same_fingerprint_penalty' => 40,
|
||||
'same_pattern_penalty' => 45,
|
||||
],
|
||||
|
||||
'ip' => [
|
||||
'cache_ttl_minutes' => 15,
|
||||
'recent_high_risk_window_hours' => 24,
|
||||
'recent_high_risk_threshold' => 3,
|
||||
'recent_high_risk_penalty' => 20,
|
||||
'known_proxy_penalty' => 20,
|
||||
'datacenter_penalty' => 25,
|
||||
'tor_penalty' => 40,
|
||||
'blacklist_penalty' => 100,
|
||||
'known_proxies' => [],
|
||||
'datacenter_ranges' => [],
|
||||
'provider_ranges' => [
|
||||
'aws' => [],
|
||||
'azure' => [],
|
||||
'gcp' => [],
|
||||
'digitalocean' => [],
|
||||
'hetzner' => [],
|
||||
'ovh' => [],
|
||||
],
|
||||
'tor_exit_nodes' => [],
|
||||
],
|
||||
|
||||
'rate_limits' => [
|
||||
'penalties' => [
|
||||
'default' => 35,
|
||||
'minute' => 35,
|
||||
'hour' => 45,
|
||||
],
|
||||
],
|
||||
|
||||
'geo_behavior' => [
|
||||
'enabled' => true,
|
||||
'login_actions' => ['login'],
|
||||
'country_headers' => [
|
||||
'CF-IPCountry',
|
||||
'CloudFront-Viewer-Country',
|
||||
'X-Country-Code',
|
||||
'X-App-Country-Code',
|
||||
],
|
||||
'recent_login_window_minutes' => 60,
|
||||
'country_change_penalty' => 50,
|
||||
],
|
||||
|
||||
'patterns' => [
|
||||
'seo' => [
|
||||
'best seo service',
|
||||
'cheap backlinks',
|
||||
'guaranteed traffic',
|
||||
'rank your website',
|
||||
],
|
||||
'casino' => [
|
||||
'online casino',
|
||||
'jackpot bonus',
|
||||
'slot machine',
|
||||
'betting tips',
|
||||
],
|
||||
'crypto' => [
|
||||
'crypto signal',
|
||||
'double your bitcoin',
|
||||
'guaranteed profit',
|
||||
'token presale',
|
||||
],
|
||||
'affiliate' => [
|
||||
'affiliate link',
|
||||
'promo code',
|
||||
'limited offer',
|
||||
'work from home',
|
||||
],
|
||||
'repeated_phrase_penalty' => 40,
|
||||
'category_penalty' => 30,
|
||||
],
|
||||
|
||||
'scan' => [
|
||||
'lookback_minutes' => 5,
|
||||
'auto_blacklist_attempts' => 10,
|
||||
'auto_blacklist_risk' => 80,
|
||||
'auto_blacklist_reason' => 'Automatically blacklisted by bot activity monitor.',
|
||||
'queue' => env('FORUM_BOT_SCAN_QUEUE', 'forum-moderation'),
|
||||
],
|
||||
];
|
||||
65
config/forum_security.php
Normal file
65
config/forum_security.php
Normal file
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'enabled' => env('FORUM_SECURITY_ENABLED', true),
|
||||
|
||||
'thresholds' => [
|
||||
'safe' => 20,
|
||||
'log' => 20,
|
||||
'captcha' => 40,
|
||||
'moderate' => 60,
|
||||
'block' => 80,
|
||||
'firewall_block' => 70,
|
||||
],
|
||||
|
||||
'queues' => [
|
||||
'moderation' => env('FORUM_SECURITY_MODERATION_QUEUE', 'forum-moderation'),
|
||||
'firewall' => env('FORUM_SECURITY_FIREWALL_QUEUE', 'forum-security'),
|
||||
],
|
||||
|
||||
'firewall' => [
|
||||
'enabled' => true,
|
||||
'request_pattern' => [
|
||||
'window_seconds' => 60,
|
||||
'burst_threshold' => 15,
|
||||
'burst_penalty' => 25,
|
||||
'missing_user_agent_penalty' => 10,
|
||||
'suspicious_path_penalty' => 20,
|
||||
'repeat_route_penalty' => 20,
|
||||
],
|
||||
'spam_wave' => [
|
||||
'window_minutes' => 15,
|
||||
'same_hash_threshold' => 3,
|
||||
'same_hash_penalty' => 30,
|
||||
'same_ip_flagged_threshold' => 4,
|
||||
'same_ip_flagged_penalty' => 25,
|
||||
'same_signature_threshold' => 3,
|
||||
'same_signature_penalty' => 20,
|
||||
],
|
||||
'thread_attack' => [
|
||||
'window_minutes' => 10,
|
||||
'topic_threshold' => 4,
|
||||
'reply_threshold' => 8,
|
||||
'topic_penalty' => 25,
|
||||
'reply_penalty' => 20,
|
||||
],
|
||||
'login_attack' => [
|
||||
'window_minutes' => 15,
|
||||
'login_threshold' => 10,
|
||||
'register_threshold' => 6,
|
||||
'login_penalty' => 30,
|
||||
'register_penalty' => 35,
|
||||
],
|
||||
'scan' => [
|
||||
'lookback_minutes' => 15,
|
||||
'auto_blacklist_attempts' => 4,
|
||||
'auto_blacklist_risk' => 70,
|
||||
'auto_blacklist_reason' => 'Automatically blacklisted by forum firewall activity monitor.',
|
||||
],
|
||||
],
|
||||
|
||||
'logging' => [
|
||||
'store_request_payload' => false,
|
||||
'reason_limit' => 8,
|
||||
],
|
||||
];
|
||||
@@ -43,13 +43,24 @@ return [
|
||||
'enabled' => env('RECAPTCHA_ENABLED', false),
|
||||
'site_key' => env('RECAPTCHA_SITE_KEY'),
|
||||
'secret' => env('RECAPTCHA_SECRET_KEY'),
|
||||
'script_url' => env('RECAPTCHA_SCRIPT_URL', 'https://www.google.com/recaptcha/api.js'),
|
||||
'verify_url' => env('RECAPTCHA_VERIFY_URL', 'https://www.google.com/recaptcha/api/siteverify'),
|
||||
'timeout' => (int) env('RECAPTCHA_TIMEOUT', 5),
|
||||
],
|
||||
|
||||
'hcaptcha' => [
|
||||
'enabled' => env('HCAPTCHA_ENABLED', false),
|
||||
'site_key' => env('HCAPTCHA_SITE_KEY'),
|
||||
'secret' => env('HCAPTCHA_SECRET_KEY'),
|
||||
'script_url' => env('HCAPTCHA_SCRIPT_URL', 'https://js.hcaptcha.com/1/api.js'),
|
||||
'verify_url' => env('HCAPTCHA_VERIFY_URL', 'https://hcaptcha.com/siteverify'),
|
||||
'timeout' => (int) env('HCAPTCHA_TIMEOUT', 5),
|
||||
],
|
||||
|
||||
'turnstile' => [
|
||||
'site_key' => env('TURNSTILE_SITE_KEY'),
|
||||
'secret_key' => env('TURNSTILE_SECRET_KEY'),
|
||||
'script_url' => env('TURNSTILE_SCRIPT_URL', 'https://challenges.cloudflare.com/turnstile/v0/api.js'),
|
||||
'verify_url' => env('TURNSTILE_VERIFY_URL', 'https://challenges.cloudflare.com/turnstile/v0/siteverify'),
|
||||
'timeout' => (int) env('TURNSTILE_TIMEOUT', 5),
|
||||
],
|
||||
|
||||
132
config/skinbase_ai_moderation.php
Normal file
132
config/skinbase_ai_moderation.php
Normal file
@@ -0,0 +1,132 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'enabled' => env('SKINBASE_AI_MODERATION_ENABLED', true),
|
||||
|
||||
'provider' => env('SKINBASE_AI_MODERATION_PROVIDER', 'openai'),
|
||||
|
||||
'queue' => [
|
||||
'name' => env('SKINBASE_AI_MODERATION_QUEUE', 'forum-moderation'),
|
||||
],
|
||||
|
||||
'preflight' => [
|
||||
'run_ai_sync' => (bool) env('SKINBASE_AI_PREFLIGHT_SYNC', true),
|
||||
],
|
||||
|
||||
'thresholds' => [
|
||||
'safe' => 20,
|
||||
'low_quality' => 40,
|
||||
'suspicious' => 60,
|
||||
'block' => 80,
|
||||
],
|
||||
|
||||
'behavior' => [
|
||||
'new_account_days' => 7,
|
||||
'rapid_post_window_minutes' => 2,
|
||||
'rapid_post_threshold' => 5,
|
||||
'same_ip_window_days' => 7,
|
||||
'same_ip_accounts_threshold' => 2,
|
||||
'repeat_content_penalty' => 40,
|
||||
'new_account_with_links_penalty' => 30,
|
||||
'rapid_post_penalty' => 20,
|
||||
'same_ip_penalty' => 25,
|
||||
'high_link_frequency_penalty' => 10,
|
||||
'flagged_history_penalty' => 15,
|
||||
],
|
||||
|
||||
'links' => [
|
||||
'too_many_links_penalty' => 15,
|
||||
'suspicious_domain_penalty' => 40,
|
||||
'shortener_penalty' => 10,
|
||||
'suspicious_tld_penalty' => 15,
|
||||
'too_many_links_threshold' => 3,
|
||||
'shorteners' => [
|
||||
'bit.ly',
|
||||
'tinyurl.com',
|
||||
'goo.gl',
|
||||
't.co',
|
||||
'ow.ly',
|
||||
'cutt.ly',
|
||||
'rebrand.ly',
|
||||
],
|
||||
'suspicious_tlds' => [
|
||||
'xyz',
|
||||
'top',
|
||||
'click',
|
||||
'loan',
|
||||
'work',
|
||||
'gq',
|
||||
'ml',
|
||||
'tk',
|
||||
],
|
||||
],
|
||||
|
||||
'trust' => [
|
||||
'high' => 80,
|
||||
'medium' => 50,
|
||||
'high_modifier' => -15,
|
||||
'medium_modifier' => -8,
|
||||
'low_modifier' => 0,
|
||||
'flagged_ratio_penalty' => 10,
|
||||
],
|
||||
|
||||
'learning' => [
|
||||
'spam_penalty' => 40,
|
||||
'safe_modifier' => -12,
|
||||
'max_spam_penalty' => 60,
|
||||
'max_safe_modifier' => -20,
|
||||
],
|
||||
|
||||
'scan' => [
|
||||
'limit' => 200,
|
||||
'stale_after_minutes' => 10,
|
||||
],
|
||||
|
||||
'privacy' => [
|
||||
'redact_emails' => true,
|
||||
'redact_ip_addresses' => true,
|
||||
'redact_mentions' => false,
|
||||
],
|
||||
|
||||
'heuristics' => [
|
||||
'promotional_phrases' => [
|
||||
'buy now',
|
||||
'limited offer',
|
||||
'cheap seo',
|
||||
'guaranteed traffic',
|
||||
'visit my profile',
|
||||
'work from home',
|
||||
'crypto signal',
|
||||
'telegram me',
|
||||
'whatsapp me',
|
||||
'dm for service',
|
||||
],
|
||||
'toxic_phrases' => [
|
||||
'kill yourself',
|
||||
'you idiot',
|
||||
'piece of trash',
|
||||
'hate you',
|
||||
'worthless',
|
||||
],
|
||||
],
|
||||
|
||||
'providers' => [
|
||||
'openai' => [
|
||||
'api_key' => env('OPENAI_API_KEY'),
|
||||
'base_url' => env('OPENAI_BASE_URL', 'https://api.openai.com/v1'),
|
||||
'model' => env('SKINBASE_AI_OPENAI_MODEL', 'gpt-4.1-mini'),
|
||||
'timeout' => (int) env('SKINBASE_AI_OPENAI_TIMEOUT', 5),
|
||||
],
|
||||
'perspective_api' => [
|
||||
'api_key' => env('PERSPECTIVE_API_KEY'),
|
||||
'base_url' => env('PERSPECTIVE_API_BASE_URL', 'https://commentanalyzer.googleapis.com/v1alpha1/comments:analyze'),
|
||||
'timeout' => (int) env('SKINBASE_AI_PERSPECTIVE_TIMEOUT', 5),
|
||||
],
|
||||
'local_llm' => [
|
||||
'endpoint' => env('SKINBASE_AI_LOCAL_LLM_ENDPOINT'),
|
||||
'model' => env('SKINBASE_AI_LOCAL_LLM_MODEL', 'moderation'),
|
||||
'timeout' => (int) env('SKINBASE_AI_LOCAL_LLM_TIMEOUT', 5),
|
||||
'token' => env('SKINBASE_AI_LOCAL_LLM_TOKEN'),
|
||||
],
|
||||
],
|
||||
];
|
||||
Reference in New Issue
Block a user