================================================================================ Security Hardening Guide ================================================================================ This guide provides security best practices and hardening steps for your Laravel application on CloudPanel. Follow these guidelines to protect your application from common vulnerabilities. ================================================================================ Essential Security Checklist ================================================================================ ☐ Set APP_DEBUG=false in production ☐ Set DISABLE_INSTALLER=true after installation ☐ Use HTTPS/SSL for all traffic ☐ Set strong APP_KEY (auto-generated) ☐ Use environment variables for secrets (.env) ☐ Configure proper file permissions ☐ Enable security headers in NGINX ☐ Keep Laravel and dependencies updated ☐ Use strong database credentials ☐ Configure CORS properly ☐ Enable rate limiting ☐ Regular security updates ☐ Implement backup strategy ☐ Monitor logs for suspicious activity ================================================================================ Application Security ================================================================================ 1. Debug Mode (CRITICAL): In .env: APP_DEBUG=false APP_ENV=production Why: Debug mode exposes sensitive information (database credentials, file paths, environment variables) in error messages. Verify: Visit a non-existent page, should show generic error, not stack trace 2. Application Key: Generate strong key: php artisan key:generate --show Set in .env: APP_KEY=base64:generated_key_here Why: Used for encryption, session security, CSRF tokens Never: Commit to version control or share publicly 3. Disable Installer: After installation, in .env: DISABLE_INSTALLER=true Or delete installer files: rm -rf app/Http/Controllers/Installer rm -rf app/Services/Installer rm -rf resources/views/installer Why: Prevents unauthorized reinstallation/reconfiguration 4. Environment File Protection: The .env file contains sensitive credentials: - Never commit to Git - Never make web-accessible - Restrict read permissions: chmod 600 .env - Keep backup in secure location NGINX blocks access by default, verify in deployment/nginx/laravel.conf 5. CSRF Protection: Laravel includes CSRF protection by default. In forms, always include: @csrf For AJAX requests: X-CSRF-TOKEN header from meta tag Don't disable: App\Http\Middleware\VerifyCsrfToken 6. SQL Injection Protection: Always use Eloquent ORM or Query Builder: SAFE: User::where('email', $email)->first(); DB::table('users')->where('email', $email)->get(); UNSAFE: DB::select("SELECT * FROM users WHERE email = '$email'"); Use parameter binding if raw SQL needed: DB::select("SELECT * FROM users WHERE email = ?", [$email]); 7. XSS Protection: Blade templates escape output by default: SAFE (escaped): {{ $user->name }} UNSAFE (raw HTML): {!! $user->bio !!} // Only if you trust the source For user input, use htmlspecialchars() or strip_tags() 8. Mass Assignment Protection: In models, define fillable or guarded: protected $fillable = ['name', 'email']; // OR protected $guarded = ['id', 'is_admin']; Why: Prevents users from modifying unintended fields ================================================================================ HTTPS/SSL Configuration ================================================================================ 1. Enable SSL in CloudPanel: - Go to Sites > Your Site > SSL/TLS - Click "New Certificate" - Choose "Let's Encrypt" (free) - Enter email for expiry notifications - Click "Create" 2. Force HTTPS: After SSL is active: - Enable "Force HTTPS" in CloudPanel In .env: APP_URL=https://yourdomain.com In NGINX config, uncomment HTTP to HTTPS redirect: server { listen 80; return 301 https://$server_name$request_uri; } 3. HTTP Strict Transport Security (HSTS): In NGINX config (after testing HTTPS): add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; This forces browsers to always use HTTPS 4. SSL Best Practices: - Use TLS 1.2 or higher (disable SSLv3, TLS 1.0, TLS 1.1) - Use strong cipher suites - Renew certificates before expiry - Test with SSL Labs: https://www.ssllabs.com/ssltest/ ================================================================================ Web Server Security ================================================================================ 1. Security Headers (NGINX): Already configured in deployment/nginx/laravel.conf: # Prevent clickjacking add_header X-Frame-Options "SAMEORIGIN" always; # Prevent MIME type sniffing add_header X-Content-Type-Options "nosniff" always; # XSS protection add_header X-XSS-Protection "1; mode=block" always; # Referrer policy add_header Referrer-Policy "no-referrer-when-downgrade" always; # Content Security Policy (customize as needed) add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline';" always; 2. Hide Server Information: In NGINX config: server_tokens off; In PHP-FPM: fastcgi_hide_header X-Powered-By; Prevents attackers from knowing server software versions 3. Deny Access to Sensitive Files: Already configured in NGINX: # Block access to .env, .git, etc. location ~* /(\.env|\.git|composer\.(json|lock)|vendor/|storage/) { deny all; } # Block PHP execution in uploads location ~* ^/storage/.*\.php$ { deny all; } 4. Rate Limiting: Add to NGINX http block: limit_req_zone $binary_remote_addr zone=login:10m rate=5r/m; Apply to login routes: location ~ ^/(login|api/login) { limit_req zone=login burst=5 nodelay; # ... rest of config } 5. Upload Size Limits: In NGINX: client_max_body_size 50M; In PHP (php.ini): upload_max_filesize = 50M post_max_size = 50M Set based on your needs, prevents DoS via large uploads ================================================================================ File & Directory Permissions ================================================================================ Correct Permissions: # Application files (read-only) find . -type f -exec chmod 644 {} \; find . -type d -exec chmod 755 {} \; # Executable scripts chmod +x artisan chmod +x scripts/*.sh # Writable directories chmod -R 775 storage chmod -R 775 bootstrap/cache # Environment file (read-only for web server only) chmod 600 .env # Set ownership chown -R www-data:www-data storage bootstrap/cache chown www-data:www-data .env Permission Principles: - Files: 644 (rw-r--r--) - Directories: 755 (rwxr-xr-x) - Writable by web server: 775 (rwxrwxr-x) - Secrets: 600 (rw-------) - Never use 777 (security risk!) Verify No World-Writable Files: find . -type f -perm 0777 # Should return nothing ================================================================================ Database Security ================================================================================ 1. Strong Credentials: - Use strong, unique passwords - Minimum 16 characters - Mix of uppercase, lowercase, numbers, symbols - Never use: root, admin, password, 123456 Generate secure password: openssl rand -base64 32 2. Least Privilege: Create dedicated database user with minimal permissions: CREATE USER 'appuser'@'localhost' IDENTIFIED BY 'strong_password'; GRANT SELECT, INSERT, UPDATE, DELETE ON appdb.* TO 'appuser'@'localhost'; FLUSH PRIVILEGES; Don't grant: DROP, CREATE, ALTER unless needed 3. Remote Access: If database on separate server: - Use SSL/TLS for connections - Whitelist specific IPs only - Use SSH tunnel when possible 4. Backup Encryption: Encrypt database backups: mysqldump -u user -p database | gzip | openssl enc -aes-256-cbc -salt -out backup.sql.gz.enc 5. SQL Injection Prevention: - Always use parameterized queries - Never concatenate user input in SQL - Validate and sanitize all input ================================================================================ Authentication & Authorization ================================================================================ 1. Password Security: Laravel uses bcrypt by default (good!) Enforce strong passwords: - Minimum 8-12 characters - Require mix of character types - Check against common passwords Use validation rule: 'password' => 'required|min:12|regex:/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).*$/' 2. Password Reset: - Use signed, expiring tokens - Rate limit reset requests - Require email verification - Invalidate old tokens after use 3. Session Security: In config/session.php: 'secure' => env('SESSION_SECURE_COOKIE', true), // HTTPS only 'http_only' => true, // Prevent JavaScript access 'same_site' => 'lax', // CSRF protection Session timeout: 'lifetime' => 120, // 2 hours 4. Two-Factor Authentication: Consider adding 2FA: composer require pragmarx/google2fa-laravel Especially for: - Admin accounts - Accounts with sensitive data - Financial applications 5. API Authentication: Using Laravel Sanctum: - Use HTTPS only - Expire tokens after inactivity - Implement rate limiting - Validate API keys on every request ================================================================================ Input Validation ================================================================================ 1. Server-Side Validation: ALWAYS validate on server, even if validated on client: $request->validate([ 'email' => 'required|email|max:255', 'age' => 'required|integer|min:18|max:120', 'website' => 'nullable|url|max:255', ]); 2. Sanitization: Strip unwanted characters: $clean = strip_tags($input); $clean = htmlspecialchars($input); For specific formats: $phone = preg_replace('/[^0-9]/', '', $input); 3. File Upload Validation: $request->validate([ 'avatar' => 'required|image|mimes:jpeg,png,jpg|max:2048', 'document' => 'required|mimes:pdf,doc,docx|max:10240', ]); Additional checks: - Verify MIME type - Scan for malware (ClamAV) - Rename uploaded files - Store outside web root 4. Content Type Validation: Verify request Content-Type: if (!$request->isJson()) { abort(415, 'Unsupported Media Type'); } ================================================================================ Dependency Security ================================================================================ 1. Keep Dependencies Updated: Check for updates: composer outdated Update with caution: composer update --with-all-dependencies Always test in staging first! 2. Security Audits: Check for known vulnerabilities: composer audit Install security checker: composer require --dev roave/security-advisories:dev-latest 3. Use Composer Lock: Commit composer.lock to ensure consistent versions In production: composer install --no-dev --optimize-autoloader 4. Remove Dev Dependencies: Never deploy dev dependencies to production: composer install --no-dev ================================================================================ Logging & Monitoring ================================================================================ 1. Security Event Logging: Log important events: - Failed login attempts - Password changes - Admin actions - API access - File uploads Example: Log::warning('Failed login attempt', ['email' => $email, 'ip' => $ip]); 2. Monitor Logs: Regularly review: tail -f storage/logs/laravel.log Look for: - Repeated failed logins - Unusual access patterns - SQL errors (possible injection attempts) - 403/404 errors (possible probing) 3. Alerting: Set up alerts for: - Multiple failed logins from same IP - Access from unusual locations - Suspicious file uploads - Error spikes Tools: Sentry, Bugsnag, Rollbar 4. Audit Trail: For sensitive operations, maintain audit log: - Who did what, when - IP addresses - Changes made - Before/after values ================================================================================ Backup & Disaster Recovery ================================================================================ 1. Regular Backups: Daily: - Database dump - User uploads Weekly: - Full application files - Configuration files See OPERATIONS.txt for backup procedures 2. Backup Security: - Encrypt backups (especially database) - Store off-site (different server/location) - Test restore procedures monthly - Limit access to backups 3. Incident Response Plan: If compromised: 1. Enable maintenance mode 2. Change all credentials 3. Review logs for attack vector 4. Restore from clean backup 5. Apply security patches 6. Re-deploy 7. Monitor closely ================================================================================ CORS Configuration ================================================================================ For API applications: In config/cors.php: 'allowed_origins' => [ 'https://yourdomain.com', 'https://app.yourdomain.com', ], 'allowed_methods' => ['GET', 'POST', 'PUT', 'DELETE'], 'allowed_headers' => ['Content-Type', 'Authorization'], 'exposed_headers' => [], 'max_age' => 3600, 'supports_credentials' => true, Never use '*' in production! ================================================================================ Security Testing ================================================================================ 1. Automated Scanning: OWASP ZAP: https://www.zaproxy.org/ - Automated security scanner - Finds common vulnerabilities Run regularly in staging environment 2. Manual Testing: Test for: - SQL Injection - XSS (Cross-Site Scripting) - CSRF (Cross-Site Request Forgery) - Authentication bypass - Directory traversal - File inclusion 3. Penetration Testing: For production applications: - Hire professional penetration testers - Annual or bi-annual testing - After major changes 4. Security Headers Check: Test headers: https://securityheaders.com/ Should get A or A+ rating ================================================================================ Compliance & Best Practices ================================================================================ 1. Data Privacy: If handling personal data: - Implement GDPR compliance (if EU users) - CCPA compliance (if California users) - Provide data export/deletion - Clear privacy policy 2. Password Storage: - Never store plain text passwords - Use Laravel's Hash::make() (bcrypt) - Never email passwords - Provide secure reset mechanism 3. Session Fixation Prevention: Regenerate session ID on login: $request->session()->regenerate(); 4. Timing Attack Prevention: For password/token comparison: hash_equals($known, $user) // Constant time comparison 5. Regular Security Audits: Monthly: - Review access logs - Check failed login attempts - Update dependencies Quarterly: - Full security review - Penetration testing - Update security policies ================================================================================ Quick Security Commands ================================================================================ # Check for world-writable files find . -type f -perm 0777 # Find files owned by wrong user find . ! -user www-data -type f # Check for .env exposure curl -I https://yourdomain.com/.env # Should return 404 or 403 # Verify HTTPS redirect curl -I http://yourdomain.com # Should return 301 to HTTPS # Test security headers curl -I https://yourdomain.com # Search for potential SQL injection grep -r "DB::raw" app/ grep -r "DB::select" app/ # Find potential XSS vulnerabilities grep -r "{!!" resources/views/ ================================================================================ Security Resources ================================================================================ Laravel Security: - https://laravel.com/docs/security - https://github.com/Checkmarx/laravel-security-checklist OWASP Resources: - https://owasp.org/www-project-top-ten/ - https://cheatsheetseries.owasp.org/ Security Tools: - OWASP ZAP (vulnerability scanner) - Snyk (dependency vulnerability checker) - SonarQube (code quality & security) Stay Informed: - Laravel Security Advisories - PHP Security Advisories - Subscribe to security mailing lists ================================================================================ Remember: Security is an ongoing process, not a one-time setup! For configuration details, see CONFIGURATION.txt For operational procedures, see OPERATIONS.txt For issue resolution, see TROUBLESHOOTING.txt