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/
andbootstrap/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
Protection | How-To |
---|---|
Block PHP except index.php | .htaccess FilesMatch or RewriteCond |
No uploads to public | App logic, Laravel storage |
PHP execution off in uploads | .htaccess in upload folder |
Permissions: no write to public | chmod , chown as above |
Disable dangerous PHP functions | php.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.