The safest ways to avoid running your PHP scripts directly are:
Hosting them outside the root of the website ( document root )
Your website should have a structure similar to this one:
/var/html/
├── html_publico/
│ ├── imagenes/
│ ├── css/
│ └── index.php
└── aplicacion/
├── script_php1.php
└── script_php2.php
It is the most recommended practice and is the one used by most frameworks (Slim, Symfony, etc.).
You can see an example on the documentation of Slim and another one on the Symfony documentation .
Using variable definition
When the previous solution can not be used (our accommodation does not allow us to access a higher level of our website) we can adopt this alternative solution, although it is less advisable and can lead to error by forgetting the check in a file.
If a PHP script can be accessed directly on its first line, a constant is defined using define()
:
define('ACCESO_PERMITIDO', true);
If you do not allow direct access to it, what you do is check that the constant has been defined through a permitted script using defined()
:
if (defined('ACCESO_PERMITIDO') === false) {
header('HTTP/1.0 403 Forbidden');
exit();
}
Denying access to the HTTP server
Another alternative that we could use is to configure the web server to refuse access to a directory where we store the protected PHP scripts.
It is a practice discouraged because when migrating from one server to another could change some parameter (such as Apache's AllowOverride
) that would allow access to the files that we thought were protected.
Apache makes use of access controls in a block <Directory>
or a file .htaccess
.
If we use the solution of the file .htaccess
our directory structure could be the following:
/var/html/
├── scripts/
│ ├── .htaccess
│ ├── script_php1.php
│ └── script_php2.php
├── imagenes/
├── css/
└── index.php
A content of .htaccess
that would prevent direct access to any file inside it would be:
Order Deny,Allow
Deny from All
We must remember that to use a file .htaccess
the directive AllowOverride
should allow the use of its content through the Limit
directive in the site settings web:
<Directory /var/html/scripts>
AllowOverride Limit
</Directory>
Since we are using the block <Directory>
in the configuration of the website this could be, without needing .htaccess
or allow Limit
with AllowOverride
:
<Directory /var/html/scripts>
Order Deny,Allow
Deny from All
</Directory>
And on an NGINX server, the website would be configured in the following way (using relative routes of the URL, not local directory routes):
location /scripts {
deny all;
return 403;
}