<\/span><\/h2>\nThere is not much on the topic of securing your MySQL database and in fact, the best way to secure it is to make sure that it is not accessible from anywhere except the host itself. After installing MySQL, the package comes with a great deployment script which can be invoked using mysql_secure_installation<\/code> on your server. The script is great because it will make sure that there are no loose ends. It will prompt you to setup a MySQL root password as well as it will disable the remote logins and will remove the test database.<\/p>\nFor those of you that already have functioning servers and do not wish to start the script, the best place to check is \/etc\/my.cnf<\/code> and make sure that you have the bind-address = 127.0.0.1<\/code> value set and it is not commented out.<\/p>\nAnother also highly secure mechanism is to use one (read at least one) user\/database per site. A lot of websites out there make use of the root mysql user for connecting the website with the database. The root user by default has access to every other database. This means any discovered vulnerability on one site, can potentially be exploited for an attacker to gain access to all of your databases.<\/p>\n
Bottom line is, if you have three websites on your server, then there should be at least three database users accessing their own database.<\/p>\n
<\/span>Securing PHP<\/strong><\/span><\/h2>\nPHP itself provides a relatively large attack surface, especially because most PHP implementations by default have fairly liberal configurations so that the developers can write their code without too much hassle. The subtopics mentioned here, are\u00a0general considerations for sysadmins. These, however, have to be additionally tweaked as per the developer’s needs. Securing the PHP interpreter is always a place\u00a0of argument and debate between the sysadmins and the developers, and can only be done properly if they all work together.<\/p>\n
Always a place\u00a0of argument and debate between the sysadmins and the developers, thus can only be done properly if both work together.<\/p>\n
<\/span>Types of PHP Attacks<\/span><\/h2>\nSQL Injection<\/h3>\n
This is a vulnerability of the application itself, usually poorly coded PHP apps almost always have this vulnerability. The more popular CMS systems are always secured against this type of attack. There is not much to be said about this type of attack except that the best way to prevent it is with good\u00a0education for the developers.<\/p>\n
XSS – Cross Site Scripting<\/h3>\n
These types of vulnerabilities are difficult to defend against. Again, the developers of the commonly used CMS platforms like WordPress, Joomla, Drupal etc. are very cautious and make sure that their code is properly written and regularly patched. Most of the security measures against these and any other types of attacks can be implemented via the main PHP configuration file. More on this later.<\/p>\n
Cross-site request forgeries \u2013 CSRF<\/h3>\n
Type of attack which forces the end user to execute unwanted actions on the web application where he is currently authenticated. If the user is an administrator account, the entire website could be compromised.\u00a0Banking and e-commerce sites are particularly targeted with these types of attacks\u00a0especially because the attackers are interested in stealing their account information to gain access to their funds.<\/p>\n
<\/span>PHP.INI Tweaks<\/span><\/h2>\nStop PHP processing if the file is not found<\/h3>\n
Make sure that\u00a0cgi.fix_pathinfo=0 \u00a0is in fact set to 0 in php.ini. This causes the PHP interpreter to only try the literal path given and to stop processing if the file is not found. Do you recall the examples from Forwarding\u00a0uncontrolled requests to PHP<\/strong> of the Securing NGINX part? This is the final piece of the NGINX\/PHP-FPM puzzle.<\/p>\nDisabling PHP Dangerous functions<\/strong><\/h3>\nThe flexibility of PHP includes many functions by default which can be used or misused depending on what one wishes to accomplish. For example, for more advanced configurations, PHP allows for remote file executions where the files can be remotely executed from another server. Although this may sound fun, it is also a security vulnerability where an attacker can open and execute any file on the remote server. This may allow them to also upload malicious files. Remote file execution should be disabled from the PHP configuration file.<\/p>\n
disable_functions =exec,eval,phpinfo,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source<\/pre>\nRestricting file uploads<\/strong><\/h3>\nWe’ve seen that through the NGINX configuration we can restrict the file uploads only to certain directories on our site. However, if your site doesn’t use file uploading features at all, they can and should be completely disabled.<\/p>\n
file_uploads=Off<\/pre>\nOf course, if your application is using the file uploads feature,\u00a0then it can be reasonably enabled by restricting the upload size limit. In the below example, one can upload files up to 1 megabyte.<\/p>\n
file_uploads=On\r\nupload_max_filesize=1M<\/pre>\nSet the POST size to a reasonable value<\/h3>\n
The POST method is used whenever a user needs to send some data to your server\/web application, and as such can potentially be exploited for malicious use, like DoS attack for example. This also includes sending large files to your server. However this method is also an integral part of any web application, so the best way to protect yourself is to limit its value and set it to something more reasonable. If you don’t use file uploads, then its value can be set to something like 4 KB or less.<\/p>\n
post_max_size=1K<\/pre>\nIf you do use the uploading files feature, then it should be set to a value that is larger than the\u00a0upload_max_filesize<\/code> value on your server.<\/p>\nRestrict PHP Information Leakage<\/h3>\n
By setting the \u00a0expose_php = Off<\/code>, one can simply hide the information that PHP is installed on the server. This will, in fact, hide the signature that PHP is leaving on the Web server header. The PHP documentation states that leaving this value to ON is not a vulnerability. However, no one can deny the fact\u00a0that the less information you present to the external world, the more secure your server will be.<\/p>\nRestricting the PHP script maximum execution time<\/h3>\n
Set the following values in your php.ini<\/code> file. They can later be tailored according to a more specific needs.<\/p>\n# set in seconds\r\nmax_execution_time = 30\r\nmax_input_time = 30\r\nmemory_limit = 40M\r\n<\/pre>\nNot only that setting these limits are a great DoS attack prevention, but they can also protect your server by careless programming and infinite loop cycles. What this basically does, is the following:<\/p>\n
\n- Sets the maximum time to 30 seconds that a script is allowed to run before it is terminated by the parser (PHP).<\/li>\n
- Sets the maximum time to 30 seconds that a script is allowed to parse input data, like POST and GET.<\/li>\n
- Sets the maximum amount of memory to 40 MB, a value that a script is allowed to allocate.<\/li>\n<\/ol>\n
In many PHP configurations, the\u00a0memory_limit value is set to -1, which is fine in development, but otherwise a bad choice.<\/p>\n
Disable unused PHP modules<\/h3>\n
PHP modules are great since they allow and enable certain functionalities to your web application. The most common example for this is the PHP pdo_mysql module which allows PHP to access MySQL databases. All of these modules, however, can potentially bring their own flaws and vulnerabilities with them and if they are not used, they can be disabled or removed. By using the command php -m<\/code> one can see all of the installed PHP modules. Disabling unused modules lowers the PHP attack surface. Ideally, PHP should be reinstalled and recompiled using only the needed modules. However, if you feel that redoing all of that is too much, then you can simply disable these by just uncommenting their line in php.ini or renaming their configuration file in \/etc\/php.d\/module_name.ini<\/code> to something like\u00a0\/etc\/php.d\/module_name.ini.disabled<\/code>.<\/p>\n