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

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 Comment