Securing PHP using a gateway that consults a whitelist My site was recently infected and running malicious scripts. Once I discovered this, I cleared everything, the hosting company re-initialized the VPS and I setup my site anew. This is how I run my PHP scripts currently. I have two objectives:


To keep my scripts from being directly accessible from the web
To never run a script that I do not approve of


First I moved the PHP files out of the public folder except for one gateway file

scripts/
   prepend.php
   a.php
   b.php
   ...
public_html/
   gateway.php
   html, css, js, image files


I use .htaccess to redirect all requests for my PHP scripts to gateway.php.  This is the file that actually executes the PHP script requested.  To reach a.php, the browser requests /php/a...

RewriteEngine On
RewriteBase /    
RewriteRule ^php/(.*)   gateway.php?file=$1.php   [END,QSA,NC]


In php.ini, I set auto_prepend_file to point to scripts/prepend.php. This file is run before all PHP scripts, so I can use it to do some configuration. In part, it has a list of allowed PHP scripts.

prepend.php

//the only scripts that will be allowed to run
Const SAFE_SCRIPTS = '"path/to/gateway.php","/path/to/a.php","/path/to/b.php"';
Const SCRIPTS_PATH = __DIR__;   

//ensure that the requested script is allowed. The check here is to prevent
//a maliciously uploaded PHP file from executing.
$file = $_SERVER['SCRIPT_FILENAME'];//typically /path/to/gateway.php
if(strpos(SAFE_SCRIPTS,"\"$file\"")===false) die("$file is not allowed");


After prepend.php, gateway.php runs; it's in charge of making sure the requested PHP file is on the allowed list and for forwarding the request to the right file

//get the file requested. Comes from the htaccess rule
$file = SCRIPTS_PATH.'/'.$_GET['file'];

//if file is not in the allowed list, abort. The check here is to prevent
//gateway from loading any file it wasn't designed to load
if(strpos(SAFE_SCRIPTS,"\"$file\"")===false) die("$file is not allowed");

//load the file that actually handles the http request
require $file;


Looking for feedback on what's the weakest link and/or how to improve.
Remove the additional information you are providing in your die statements. Just simply die quietly without revealing any information. It's similar to putting a zero byte index.html file in directories that you don't want people browsing.

Edit: Going away quietly without providing any information gives less information about your site to someone who may be trying to attack it. Any clues that you give them, like file not found for example, lets them know that they need to change their attack vector. The less information you can give them the better.