Skip to content

Instantly share code, notes, and snippets.

@nadyshalaby
Last active February 19, 2025 07:36
Show Gist options
  • Save nadyshalaby/6427d2b16892a57147747061c7d72b47 to your computer and use it in GitHub Desktop.
Save nadyshalaby/6427d2b16892a57147747061c7d72b47 to your computer and use it in GitHub Desktop.
The process of securing your Laravel application.

Laravel Project Security Hardening Guide

A comprehensive guide to secure your Laravel application against common attacks and vulnerabilities.

Table of Contents

  1. Nginx Configuration
  2. File Permissions
  3. Laravel Security Settings
  4. Server Hardening
  5. Monitoring & Maintenance
  6. Security Checklist

Nginx Configuration

1. Main Nginx Configuration

Edit /etc/nginx/nginx.conf:

http {
    # ... existing settings ...

    # Rate limiting
    limit_req_zone $binary_remote_addr zone=mylimit:10m rate=5r/s;
    
    # Security settings
    server_tokens off;
    client_max_body_size 10M;
    client_body_buffer_size 128k;
    
    # ... rest of settings ...
}

Test and reload Nginx to apply the changes:

# test the configuration first
sudo nginx -t

# Reload nginx
sudo systemctl reload nginx
  1. Site Configuration Create /etc/nginx/sites-available/your-site.conf:
server {
    listen 443 ssl http2;
    server_name your-domain.com;
    root /var/www/your-domain.com/public;
    index index.php index.html;

    # SSL Configuration
    ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
    
    # Please make sure that the following rules are not duplicated
    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:50m;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;

    # Security Headers
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-XSS-Protection "1; mode=block" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header Referrer-Policy "no-referrer-when-downgrade" always;
    add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always;
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

    # Logs
    access_log /var/log/nginx/your-domain.com-access.log;
    error_log /var/log/nginx/your-domain.com-error.log;
    
    # Rate Limiting
    location / {
        limit_req zone=mylimit burst=10 nodelay;
        try_files $uri $uri/ /index.php?$query_string;
    }

    # Block Sensitive Files
    location ~ /\. { deny all; }
    location ~ ^/(app|bootstrap|config|database|resources|routes|storage|tests|vendor)/ { deny all; }
    location ~ \.(env|log|lock|json|yml|yaml|config|bak|git|svn|txt|md|sql)$ { deny all; }

    # Protect Upload Directories
    location ~ ^/uploads/.*\.php$ { deny all; }

    # PHP-FPM Configuration
    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/var/run/php/php-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
        fastcgi_intercept_errors on;
        fastcgi_buffer_size 16k;
        fastcgi_buffers 4 16k;
    }
    
    # Static Files Cache
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
        expires 30d;
        add_header Cache-Control "public, no-transform";
    }
}

# HTTP to HTTPS Redirect
server {
    listen 80;
    server_name your-domain.com www.your-domain.com;
    return 301 https://$server_name$request_uri;
}

File Permissions

  1. Set Ownership
# Set proper ownership
sudo chown -R www-data:www-data /var/www/your-domain.com

# Set proper permissions
find /var/www/your-domain.com -type f -exec chmod 644 {} \;
find /var/www/your-domain.com -type d -exec chmod 755 {} \;

# Set specific permissions for sensitive directories
chmod 750 storage
chmod -R 750 storage/framework
chmod -R 750 storage/logs
chmod -R 750 bootstrap/cache

Laravel Security Settings

  1. Environment File
APP_ENV=production
APP_DEBUG=false
APP_URL=https://your-domain.com

SESSION_SECURE_COOKIE=true
SESSION_COOKIE_HTTPONLY=true
SESSION_DOMAIN=your-domain.com

SANCTUM_STATEFUL_DOMAINS=your-domain.com
  1. Security Middleware Add to app/Http/Kernel.php:
protected $middlewareGroups = [
    'web' => [
        \App\Http\Middleware\VerifyCsrfToken::class,
        \App\Http\Middleware\EncryptCookies::class,
        \App\Http\Middleware\TrustProxies::class,
        \Illuminate\Http\Middleware\HandleCors::class,
    ],
];
  1. Config Updates
// config/session.php
'secure' => true,
'http_only' => true,
'same_site' => 'lax',

// config/hashing.php
'driver' => 'bcrypt',
'rounds' => 12,

Server Hardening

  1. Install Security Tools
# Install security packages
sudo apt update
sudo apt install fail2ban ufw mod-security

# Configure UFW
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow ssh
sudo ufw allow 'Nginx Full'
sudo ufw enable
  1. Create Security Scan Script
#!/bin/bash
# /root/security_scan.sh

# Scan for recently modified files
find /var/www/your-domain.com -type f -mtime -1 -ls > /root/modified_files.log

# Check for files with wrong permissions
find /var/www/your-domain.com -type f -perm /o+w -ls > /root/wrong_permissions.log

# Check for PHP files in upload directories
find /var/www/your-domain.com/public/uploads -name "*.php" -ls > /root/suspicious_uploads.log

# Check for large files that might indicate malware
find /var/www/your-domain.com -type f -size +10M -ls > /root/large_files.log

Add to crontab:

# Make it executable and add to crontab:
chmod +x /root/security_scan.sh

(crontab -l 2>/dev/null; echo "0 */6 * * * /root/security_scan.sh") | crontab -

Monitoring & Maintenance

  1. Regular Updates
# Update system packages
sudo apt update
sudo apt upgrade

# Update Composer dependencies
composer update --no-dev
  1. Log Monitoring
# Monitor Laravel logs
tail -f storage/logs/laravel.log

# Monitor Nginx access logs
tail -f /var/log/nginx/access.log

# Monitor Nginx error logs
tail -f /var/log/nginx/error.log

Create cleanup script

#!/bin/bash

echo "Starting security cleanup..."

# Directory containing suspicious files
PROJECT_ROOT="/var/www/yourdomain.com"
cd $PROJECT_ROOT

# 1. Remove suspicious PHP files in various locations
echo "Removing suspicious PHP files..."
suspicious_files=(
    "public/.well-known/pki-validation/_manager/Support/ChunkInterface.php"
    "public/.well-known/pki-validation/_manager/Support/SOURCE/-/php.ini"
    "public/.well-known/pki-validation/_manager/Support/SOURCE/-/source.php"
    "public/admin-bar.php"
    "public/apply/assets/cc.php"
    "public/assets/global/excel/gecko.php"
    "public/assets/site/images/en.jpg.php"
    "public/php.ini"
    "public/storage/index.php"
    "public/storage/sitme.xml"
    "public/vendor/datatables/ALFA_DATA"
    "public/vendor/datatables/server_data.php"
    "public/vendor/datatables/style.php"
    "public/video/index.php"
    "public/video/sitme.xml"
    "public/video/wgjc.txt"
    "public/workshops/assets/.DS.Prokon.php"
    "public/workshops/assets/images/ALFA_DATA"
    "public/workshops/assets/images/base.php"
    "public/workshops/assets/images/rigen.php"
    "public/workshops/assets/vendor/bootstrap/Backup_fil.php"
    "bootstrap/app.php.bk"
)

for file in "${suspicious_files[@]}"; do
    if [ -e "$file" ]; then
        rm -rf "$file"
        echo "Removed: $file"
    fi
done

# 2. Remove ALFA shell backdoors (common malware)
echo "Removing ALFA shell backdoors..."
find . -type f -name "*.alfa" -delete
find . -type f -name "bash.alfa" -delete
find . -type f -name "perl.alfa" -delete
find . -type f -name "py.alfa" -delete

# 3. Clean uploads directory of PHP files
echo "Cleaning uploads directory..."
find ./public/assets/uploads -type f -name "*.php" -delete

# 4. Remove any hidden PHP files
echo "Removing hidden PHP files..."
find . -type f -name ".*.php" -delete

# 5. Verify and fix permissions
echo "Fixing permissions..."
find . -type d -exec chmod 755 {} \;
find . -type f -exec chmod 644 {} \;
chmod -R 750 storage
chmod -R 750 bootstrap/cache

# 6. Clean git cache
echo "Cleaning git cache..."
git rm -r --cached .
git add .
git commit -m "security: remove malicious files and fix permissions"

echo "Cleanup complete. Please review the following security measures:"

# Output security recommendations
echo "
IMPORTANT NEXT STEPS:
1. Change all passwords immediately
2. Review all database tables for unauthorized changes
3. Check for unauthorized users/admin accounts
4. Update all dependencies
5. Run: composer update --no-dev
6. Check for unauthorized cron jobs: crontab -l
7. Monitor access logs for suspicious activity
8. Consider fresh installation of core files
9. Update Laravel framework
10. Enable file integrity monitoring
"

# Scan for remaining PHP files in suspicious locations
echo "Scanning for remaining suspicious files..."
find ./public -type f -name "*.php" ! -path "./public/index.php" -ls

echo "Please review any remaining PHP files listed above."

Save this as cleanup.sh and run it:

sudo chmod +x cleanup.sh
sudo ./cleanup.sh

After running the cleanup script:

  1. Change all passwords:
    • Database passwords
    • Admin user passwords
    • API keys
    • SSH keys
  2. Add these rules to your nginx configuration to prevent future uploads:
# Add inside your server block
location ~ /\.well-known/.*\.php$ {
    deny all;
}

location ~ /vendor/.*\.php$ {
    deny all;
}

location ~ /workshops/.*\.php$ {
    deny all;
}
  1. Monitor your files:

First, create the monitoring script:

sudo nano /root/monitor_files.sh

Add this content:

#!/bin/bash
/usr/bin/inotifywait -m -r /var/www/freeziana.com -e create,modify,delete,move |
while read path action file; do
    echo "$(date): $path$file $action" >> /var/log/file_changes.log
    if [[ "$file" =~ .*\.php$ ]]; then
        echo "PHP file $action: $path$file" | mail -s "Security Alert: PHP File Change" [email protected]
    fi
done

Make it executable:

sudo chmod +x /root/monitor_files.sh

Add it to crontab properly:

# Open crontab editor
sudo crontab -e

Add this line to the crontab:

@reboot /root/monitor_files.sh

For immediate monitoring (without waiting for reboot), you can start it as a service:

sudo nano /etc/systemd/system/file-monitor.service

Add this content:

[Unit]
Description=File Monitoring Service
After=network.target

[Service]
Type=simple
ExecStart=/root/monitor_files.sh
Restart=always

[Install]
WantedBy=multi-user.target

Start and enable the service:

sudo systemctl daemon-reload
sudo systemctl enable file-monitor
sudo systemctl start file-monitor

Check the service status:

sudo systemctl status file-monitor

This setup will:

  • Monitor your files continuously
  • Log changes to /var/log/file_changes.log
  • Send email alerts for PHP file changes
  • Start automatically on reboot
  • Restart if it crashes

Security Checklist:

  • ✅ SSL certificate installed and renewed automatically
  • ✅ Rate limiting configured in Nginx
  • ✅ File permissions properly set
  • ✅ Security headers configured
  • ✅ Upload directory protected
  • ✅ Sensitive files blocked
  • ✅ Debug mode disabled
  • ✅ Security scan script installed
  • ✅ Fail2ban configured
  • ✅ UFW firewall enabled
  • ✅ Regular updates scheduled
  • ✅ Log monitoring in place
  • ✅ CSRF protection enabled
  • ✅ Session security configured
  • ✅ Database credentials secured
  • ✅ API endpoints protected
  • ✅ Input validation implemented
  • ✅ XSS protection enabled
  • ✅ SQL injection prevention configured
  • ✅ File upload validation implemented

Additional Recommendations

  • Use Laravel Sanctum for API authentication
  • Implement two-factor authentication
  • Use prepared statements for all database queries
  • Implement rate limiting on API routes
  • Regular security audits
  • Keep backups in secure, off-site location
  • Use Laravel's built-in XSS protection
  • Implement proper password hashing
  • Use HTTPS for all requests
  • Regular penetration testing
  • Emergency Response
  • If your site is compromised:

Take the site offline

  • Backup all files and logs
  • Check file modification timestamps
  • Review all PHP files for malicious code
  • Check database for unauthorized changes
  • Reset all passwords and API keys
  • Update all software and dependencies
  • Review and strengthen security measures
  • Report the incident if required by regulations
  • Document the incident and improve security
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment