In this article I will show you how to slightly increase application security, by exploiting the fact that Yii implements the Front Controller Pattern.
Introduction ¶
While surfing the web, I noticed that most of the tutorials about configuring Nginx+PHP, propose the following pattern of invoking PHP:
location ~ \.php$ {
...
}
That very line is used even in the official recommended configuration of Yii2.
The above directive instructs Nginx to pass every request, whose URL end with ".php" to the PHP interpreter. It works very well and is a nearly universal solution. But in fact, if you use Yii it is excessive.
The Only Entry Point ¶
If you are somewhat familiar with Yii, you might already know that application lifecycle starts in
the so called "entry script", usually named index.php
. This is where the web application instance
is created and request processing started.
The truth is that among all of the PHP files that an application consists of, only the entry script really should be invokable with PHP interpreter from the web! So the relevant part of Nginx config should resemble the following:
location = /index.php {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name;
fastcgi_pass 127.0.0.1:9000;
#fastcgi_pass unix:/var/run/php5-fpm.sock;
try_files $uri =404;
}
location ~ \.php$ {
# prevent exposure of any other .php files!!!
return 404;
}
Security ¶
One may ask how this rather subtle configuration change affects security. Here is a little example.
Imagine you have written and application, which among other things allows users to upload some files.
Now, if you "forgot" to implement strict validation rules, malicious user could potentially
upload (exploiting e.g. some NUL char vulnerability) file shell.php
into the
server's uploads
folder.
Now the malicious user opens the URL: http://yourapp.net/uploads/shell.php
- If the common configuration snippet was used, the request will be passed to the PHP - WIN for the hacker.
- With the config from this article, the 404 Not Found will be shown - FAIL for the hacker :)
Limitations ¶
The described approach is not always applicable. If you use some third party tools (e.g. KCFinder),
which has its own scripts meant for web access (e.g. browser.php
, upload.php
etc), you will need to allow PHP for
these scripts as well. Or better, write a Yii-compatible wrapper script, which will then pass
request parameters from the entry script to a corresponding third party handler.
Good advice
Really, this article must be upvoted thousand times. It's a really simple change, but dramatically reduces the attack surface. Most MVC frameworks could be using this approach, I wonder why the authors don't advocate it.
As a side note, you can omit that 404 rule and simply return other
.php
files as text, so they are simply rendered in browser, instead of being interpreted on the server.If you have any questions, please ask in the forum instead.
Signup or Login in order to comment.