Laravel Security: Restricting uploads of PHP files to your Laravel public directory

Posted by

–

You’re on the right track thinking about restricting uploads of PHP files to your Laravel public directory—this is one of the most effective defenses against webshells, backdoors, and PHP-based malware. The public folder should only have files you intend to be web-accessible, and usually only index.php (plus assets like CSS, JS, images).

Below is a step-by-step, professional-grade hardening guide for your situation.


1. Never Allow File Uploads Directly to public/

  • Change your app logic so any file uploads go to storage/ or a dedicated, non-web-accessible folder.
  • Use Laravel’s storage system and serve user-uploaded files via a controller if needed, not direct public links.

2. Block Access to PHP Files Except index.php (in .htaccess)

Add this to your public/.htaccess, after the existing rules:

# BLOCK direct access to ALL PHP files except index.php
<FilesMatch "^(?!index\.php$).+\.php$">
    Order allow,deny
    Deny from all
</FilesMatch>

Or, using mod_rewrite (for hosts where FilesMatch isn’t allowed):

RewriteCond %{REQUEST_URI} !/index\.php$
RewriteRule \.php$ - [F]

This means:

  • Only index.php is web-accessible.
  • Any attempt to run another PHP file (even if uploaded by a hacker) will be blocked with a 403 Forbidden.

3. Forbid PHP Execution in Upload Folders (Even If They’re Public!)

If you must make a subfolder in public/ writeable (not recommended!), add an .htaccess inside that folder:

# /public/uploads/.htaccess
php_flag engine off
RemoveHandler .php .phtml .php3 .php4 .php5 .php7 .phps
<FilesMatch "\.(php|php[3457]?|phtml|phps)$">
    Order allow,deny
    Deny from all
</FilesMatch>
  • This disables the PHP engine for that folder, even if a PHP file is uploaded.

4. Disable Dangerous PHP Functions

In your php.ini:

disable_functions = exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source
  • This makes it harder for webshells to function, even if uploaded.

5. Permissions: Never Allow PHP to Write Into public/

  • On your server: chown -R www-data:www-data /var/www/html/yourproject chmod -R 755 /var/www/html/yourproject chmod 644 /var/www/html/yourproject/public/*.php chmod -R 555 /var/www/html/yourproject/public
  • Only grant write permissions to folders Laravel actually needs (typically storage/ and bootstrap/cache/).

6. General Tips

  • Always keep Laravel, Composer, PHP, and all libraries up-to-date.
  • Install a Web Application Firewall (WAF) if possible (e.g., ModSecurity).
  • Use fail2ban or similar tools to block brute-force attackers.
  • Restrict SSH access to only trusted IPs and use key authentication.

Example: Secure .htaccess for Laravel public/

<IfModule mod_negotiation.c>
    Options -MultiViews -Indexes
</IfModule>

<IfModule mod_rewrite.c>
    RewriteEngine On

    # HTTPS and www redirects (add yours here)

    # Block direct access to PHP files except index.php
    RewriteCond %{REQUEST_URI} !/index\.php$
    RewriteRule \.php$ - [F]

    # Usual Laravel front controller rules...
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ index.php [L]
</IfModule>

Summary Table

ProtectionHow-To
Block PHP except index.php.htaccess FilesMatch or RewriteCond
No uploads to publicApp logic, Laravel storage
PHP execution off in uploads.htaccess in upload folder
Permissions: no write to publicchmod, chown as above
Disable dangerous PHP functionsphp.ini settings

Final Advice

  • Blocking all PHP except index.php is a good approach and should be used in combination with other security steps.
  • Never allow uploads directly to public/ or any web-accessible folder.
  • Audit permissions, keep everything updated, and use defense in depth.

Leave a Reply