Security Best Practices
Securing your InspireCMS installation is crucial to protect your content, user data, and site integrity. This guide outlines important security considerations and best practices for maintaining a secure InspireCMS website.
Core Security Features
InspireCMS includes several built-in security features:
- Secure authentication system
- Role-based access control
- CSRF protection
- XSS mitigation
- SQL injection prevention
- Input validation
- Secure password handling
- Session management
- Rate limiting
Environment Configuration
Secure .env File
Your .env file contains sensitive information and should be protected:
# Never commit .env to version control
echo ".env" >> .gitignore
# Use proper production values
APP_ENV=production
APP_DEBUG=false
APP_KEY=[64-character-random-string]
# Set proper permissions
chmod 600 .env
Production Settings
In production environments:
// config/app.php
'debug' => env('APP_DEBUG', false),
// config/logging.php
'default' => env('LOG_CHANNEL', 'daily'),
For better security and performance in production, cache your configuration and routes:
# Cache configuration files for faster loading
php artisan config:cache
# Cache routes for improved performance
php artisan route:cache
# Pre-compile views to minimize processing time
php artisan view:cache
# Clear all caches during updates (when making changes)
php artisan optimize:clear
These optimizations not only improve performance but also reduce security risks by minimizing file access operations.
Authentication Security
Password Policies
Implement strong password requirements:
// app/Providers/AuthServiceProvider.php
use Illuminate\Validation\Rules\Password;
public function boot()
{
// Configure password validation rules
Password::defaults(function () {
$rule = Password::min(12)
->letters()
->mixedCase()
->numbers()
->symbols();
return $rule;
});
}
Account Security
Configure account security settings:
// config/inspirecms.php
'auth' => [
// Number of failed attempts before lockout
'failed_login_attempts' => 5,
// Lockout duration in minutes
'lockout_duration' => 15,
// Force email verification
'skip_account_verification' => false,
],
Two-Factor Authentication
Enable two-factor authentication for admin users:
// Install Laravel Fortify
composer require laravel/fortify
// Enable 2FA in config/fortify.php
'features' => [
Features::twoFactorAuthentication([
'confirm' => true,
'confirmPassword' => true,
]),
// Other features...
],
File Upload Security
Secure File Uploads
Configure secure file upload handling:
// config/inspirecms.php
'media' => [
'media_library' => [
// Allowed file types
'allowed_mime_types' => [
'image/jpeg', 'image/png', 'image/gif', 'image/svg+xml',
'application/pdf', 'application/msword',
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
],
// Maximum file size in KB
'max_file_size' => 5 * 1024,
],
],
Content Delivery Security
Content Security Policy
Implement a Content Security Policy:
// app/Http/Middleware/ContentSecurityPolicy.php
namespace App\Http\Middleware;
use Closure;
class ContentSecurityPolicy
{
public function handle($request, Closure $next)
{
$response = $next($request);
$response->headers->set('Content-Security-Policy', "
default-src 'self';
script-src 'self' https://cdn.jsdelivr.net;
style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://fonts.googleapis.com;
img-src 'self' data: https://*.your-domain.com;
font-src 'self' https://fonts.gstatic.com;
connect-src 'self';
frame-src 'self';
object-src 'none';
base-uri 'self';
form-action 'self';
");
return $response;
}
}
Register the middleware in app/Http/Kernel.php:
protected $middlewareGroups = [
'web' => [
// Other middleware...
\App\Http\Middleware\ContentSecurityPolicy::class,
],
];
HTTPS Enforcement
Force HTTPS connections:
// app/Providers/AppServiceProvider.php
public function boot()
{
if (config('app.env') === 'production') {
\URL::forceScheme('https');
}
}
Add security headers:
// app/Http/Middleware/SecurityHeaders.php
namespace App\Http\Middleware;
use Closure;
class SecurityHeaders
{
public function handle($request, Closure $next)
{
$response = $next($request);
$response->headers->set('X-Frame-Options', 'SAMEORIGIN');
$response->headers->set('X-Content-Type-Options', 'nosniff');
$response->headers->set('X-XSS-Protection', '1; mode=block');
$response->headers->set('Referrer-Policy', 'strict-origin-when-cross-origin');
$response->headers->set('Permissions-Policy', 'camera=(), microphone=(), geolocation=()');
return $response;
}
}
Database Security
Database Connections
Secure database connections:
// .env
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=inspirecms
DB_USERNAME=inspirecms_user
DB_PASSWORD=strong_password_here
Query Protection
InspireCMS uses Laravel's query builder, which automatically protects against SQL injection. Always use parameter binding:
// GOOD: Uses parameter binding
$results = DB::table('cms_contents')
->where('id', $request->id)
->get();
// BAD: Never do this
$query = "SELECT * FROM cms_contents WHERE id = " . $request->id;
$results = DB::select($query);
Regular Updates
Keep Dependencies Updated
Regularly update InspireCMS and its dependencies:
# Check for outdated packages
composer outdated
# Update InspireCMS
composer update inspirecms/core
# Update all dependencies
composer update
Security Scanning
Implement security scanning in your workflow:
# Install security checker
composer require enlightn/security-checker --dev
# Scan for vulnerabilities
php artisan security:check
Server Hardening
File Permissions
Set proper file permissions:
# Set proper ownership
chown -R www-data:www-data /path/to/inspirecms
# Set directory permissions
find /path/to/inspirecms -type d -exec chmod 755 {} \;
# Set file permissions
find /path/to/inspirecms -type f -exec chmod 644 {} \;
# Set special permissions for storage and cache
chmod -R 775 /path/to/inspirecms/storage
chmod -R 775 /path/to/inspirecms/bootstrap/cache
Web Server Configuration
Configure your web server securely:
Nginx
# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# Disable server information
server_tokens off;
# Block access to sensitive files
location ~ \.(env|git|htaccess|log|yaml|json|lock|md|yml)$ {
deny all;
return 404;
}
# Protect system directories
location ~ ^/(storage|bootstrap|vendor|node_modules|tests)/ {
deny all;
return 404;
}
Apache
# Security headers
<IfModule mod_headers.c>
Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-Content-Type-Options "nosniff"
Header always set X-XSS-Protection "1; mode=block"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
</IfModule>
# Protect sensitive files
<FilesMatch "\.(env|git|htaccess|log|yaml|json|lock|md|yml)$">
Order allow,deny
Deny from all
</FilesMatch>
# Protect system directories
<DirectoryMatch "^/(storage|bootstrap|vendor|node_modules|tests)/">
Order allow,deny
Deny from all
</DirectoryMatch>
Monitoring and Logging
Security Monitoring
Configure proper security logging:
// config/logging.php
'channels' => [
'security' => [
'driver' => 'daily',
'path' => storage_path('logs/security.log'),
'level' => 'notice',
'days' => 14,
],
],
Log security events:
// Example security logging
\Log::channel('security')->notice('Failed login attempt', [
'user' => $request->email,
'ip' => $request->ip(),
'user_agent' => $request->userAgent(),
]);
Audit Logging
Track user actions for accountability:
// Install an audit package
composer require owen-it/laravel-auditing
// Make models auditable
use OwenIt\Auditing\Contracts\Auditable;
use OwenIt\Auditing\Auditable as AuditableTrait;
class Content extends Model implements Auditable
{
use AuditableTrait;
// ...
}
Backups and Disaster Recovery
Regular Backups
Configure automatic backups:
// Install backup package
composer require spatie/laravel-backup
// Create a backup command
php artisan backup:run
Schedule backups:
// app/Console/Kernel.php
protected function schedule(Schedule $schedule)
{
$schedule->command('backup:clean')->daily()->at('01:00');
$schedule->command('backup:run')->daily()->at('02:00');
}
Recovery Testing
Regularly test your backup restoration process:
# Test backup restoration in a separate environment
php artisan backup:restore-test
Security Checklist
Implement this checklist for your InspireCMS installation:
-
Application Security
- Run InspireCMS in production mode
- Keep InspireCMS and all dependencies updated
- Generate strong application key
- Disable debugging in production
- Configure proper error logging
- Cache configurations in production
-
Authentication & Authorization
- Implement strong password policies
- Configure account lockout settings
- Use two-factor authentication for admin accounts
- Review and limit admin accounts
- Implement principle of least privilege for user roles
- Set secure session configurations
- Implement proper CSRF protection
-
Content Security
- Validate and sanitize all content
- Implement Content Security Policy
- Configure proper CORS settings
- Use secure file upload handling
- Sanitize SVG files
- Set upload size and type restrictions
-
Server Security
- Force HTTPS connections
- Set proper file and directory permissions
- Protect sensitive files and directories
- Add security headers
- Disable server information disclosure
- Configure firewall rules
- Use secure database connections
- Implement rate limiting
-
Monitoring & Recovery
- Configure security monitoring
- Implement audit logging
- Set up intrusion detection
- Perform regular security scans
- Maintain regular backups
- Test backup restoration process
- Document security incident response plan