Let’s get rid of default settings!


Let’s start with the configuration of the Indian who gained recognition on many servers on the web. The first setting we select is the one that prevents an attacker from recognizing the version of Apache. To do this, you can use two directives that have to be set to the following values:

ServerSignature Off
ServerTokens Prod

Separate user and group

The second step is to make sure that Apache runs under its own separate user and group. If the same user also manages something else, e.g. DBMS, an attacker who manages to compromise the web server can have access to the database as well.

Root directory

Then you need to make sure that the files located outside the root directory are not processed by the web server. If we assume that all the websites on the server are in the same directory (say, /web), the configuration has to look like this:

<Directory />
    Order Deny,Allow
    Deny from all
    Options None
    AllowOverride None
<Directory /web>
    Order Allow,Deny
    Allow from all

You can disable the view of the contents of directories inside the tag <Directory> with the use of Options-Indexes:

  • turn off the server side includes — Options -Includes;
  • disable CGI execution — Options -ExecCGI;
  • forbid Apache to open symbolic links — Options -FollowSymLinks.

The resources and DoS

To mitigate the effect of DoS-attacks, it is possible to reduce the timeout value to Timeout 45. Alternatively, you can also set a limit to the size of the body of the request, making it, for example, equal to 1 MB, — LimitRequestBody 1048576. In general, the reaction of the server to increased activity of the bots will also depend on the following parameters: RequestReadTimeout,KeepAliveTimeout, MaxRequestWorkers, as well as the policies that restrict the consumption of resources: LimitRequestFields, LimitRequestFieldSize, LimitRequestLine and LimitXMLRequestBody

Restricting access

If a resource located on a server resource is intended only for a specific subnet, you can restrict access to such resource:

Order Deny,Allow
Deny from all
Allow from

or for a separate IP-address: Allow from

Basic authentication in Apache

Protecting the settings

To protect the security-settings that you made in the configuration file and prevent users from changing them, disable htaccess-files:

<Directory />
    AllowOverride None

hiding Apache from prying eyes - ServerSignature Off


The next topic of our review is nginx web server. Firstly, it is possible, as is the case with Apache, to hide the type and version of the server, which is called “security through obscurity”; this will cause the attacker to spend extra time in the process. To do this, adjust the src/http/ngx_http_header_filter_module.c file by changing the following lines

static char ngx_http_server_string[] = "Server: nginx" CRLF;
static char ngx_http_server_full_string[] = "Server: " NGINX_VER CRLF;


static char ngx_http_server_string[] = "Server: ][akep Web Server" CRLF;
static char ngx_http_server_full_string[] = "Server: ][akep Web Server" CRLF;

Then compile the server. To hide the version of the server, you need to add the optionserver_tokens off to the configuration file nginx.conf. Now it is not so easy for an attacker to determine the type of the web server and its version. This is already a good result.

Limiting the buffers

Next, to ensure some protection from the attacks that act through buffer overflow, you can use the following settings:

client_body_buffer_size 1K;
client_header_buffer_size 1k;
client_max_body_size 1k;
large_client_header_buffers 2 1k;


  • client_body_buffer_size determines the size of the buffer for a client’s request;
  • client_header_buffer_size sets the buffer size for reading the header of the client request;
  • Client_max_body_size — the maximum size of the client request body;
  • Large_client_header_buffers sets the maximum number and size of buffers for reading the large header in the client’s request.

Filter user agents

The configuration file nginx.conf gives us an opportunity to set the web server just in the way we want it to operate. For example, you can restrict access to specific user-agents like bots, crawlers, and downloaders:

if ($http_user_agent ~* LWP::Simple|BBBike|wget|libwww-perl) {
    return 403;

Let’s do away with hotlinking

Another useful feature is the ban on hotlinking (a situation when a third-party resource refers to an image or some other resource on your server):

location /images/ {
    valid_referers none blocked www.xakep.ru xakep.ru;
    if ($invalid_referer) {
        return 403;

This also allows you to reduce the load on the server and the traffic costs, if your resource is already very popular. If it is not, then it is no problem if someone publishes a link to a picture on your website.

Restricting access

You can also allow or restrict access to the administrator control panel or some other resource directory for certain IP-addresses.

location /docs/ {
    ## block one workstation
    ## allow anyone in
    ## drop rest of the world
    deny all;

If you do not disable server_tokens, it becomes very easy to determine the version of nginx

Banning bots

To fight bots that scan the server for the presence of different domains you can allow requests only to the configured virtual domains, or reverse-proxy requests:

if ($host !~ ^(xakep.ru|www.xakep.ru|images.xakep.ru)$ ) {
    return 444;

Similarly, it is possible to limit the number of available HTTP-methods, leaving, for example, only GET, POST and HEAD:

if ($request_method !~ ^(GET|HEAD|POST)$ ) {
    return 444;

Referral spam

To combat referral spam, which may adversely affect your SEO-grade, you can use a configuration like this:

if ( $http_referer ~* (babes|forsale|girl|jewelry|love|nudit|organic|poker|porn|sex|teen) )
     return 403;

Geographic ban

If attacks at your resource always come from a particular country, or the content is not intended for some countries, you can limit access for users from such countries. First, in the configuration block http {} you have to specify the location of GeoIP database: geoip_country /etc/nginx/GeoIP.dat;, and then specify which countries you want to block in nginx:

if ($geoip_country_code ~ (CN|KR|UK) ) {
    return 403;

Ban on scripts execution

To provide some protection for your resource, you can also use one more method — prohibiting the execution of scripts from certain directories. Indeed, as it usually happens, the attacker places the web shell in one of the directories intended for files upload. To make sure that even if the attacker manages to bypass all the filters and put in a shell instead of an avatar, he will not be able to use it, do the following:

location ~* /(images|cache|media|logs|tmp)/.*.(php|pl|py|jsp|asp|sh|cgi)$ {
    return 403;
    error_page 403 /403_error.html;


Well, now it’s time to talk a bit about the safety of a popular DBMS. As you remember, its configuration file is called my.cnf. Typically, the first of the settings to check and change here is the bind-address, which determines which addresses are allowed to connect to the DBMS. As the database is usually physically located on the same server as the resource itself, this option is set as That is, the database will only accept local connections. By the way, as an option, you can also just forbid MySQL to open the network socket; this is done by adding skip-networking to the configuration file.

Ban on reading files

One of the most common vulnerabilities is the risk of SQL-injection. It enables the attacker not only to receive the data from the database, but also to read the local files. To avoid this, set the local-infile parameter to0.

Changing the Root

Another good step towards safety is to change the name and the password of the superuser. By default, this is usually the user called root. This is done with the following commands:

mysql> RENAME USER root TO new_user;
mysql> SET PASSWORD FOR 'new_user'@'%hostname' = PASSWORD('new_pass');

As we do not want to tempt any bad guys, we’d better delete test database, which was created during the installation, as well as all anonymous users with blank passwords.

Clean history

It is also useful to clean up the history, where a lot of valuable information is saved (e.g. passwords), and, what is more, where things are kept in the open form. This is done as follows:

cat /dev/null > ~/.mysql_history

MySQL history may include fascinating details...


There are a lot of materials on PHP security both on the web and in our magazine, so we are not going to discuss it here in detail. We’ll only go over the most important parameters that have to be taken into consideration first.
PHP version disclosure

Hazardous functions

First, you can block calls from potentially dangerous functions by using disable_functions = phpinfo, system, mail, exec. Then you can limit the use of the resources, i.e. the maximum time of script execution (max_execution_time), the time of query input (max_input_time), the size of the memory consumed with each script (memory_limit), the maximum size of data transmitted by POST request, etc.

Errors and logs

Then you can disable the display of errors to users: display_errors = Off, and enable logging:



Disable expose_php in order not to show that PHP is present on the server. However, this trick will help only if NPC is used. Otherwise, the URL will disclose everything.

Still, you can disable the option of opening remote files by setting allow_url_fopen in the configuration file security.ini as Off.

Force redirect

To prevent any attempts of direct calls to PHP at the address of http://my.host/cgi-bin/php/secretdir/script.php type, you can use cgi.force_redirect = 0 directive. In this case, PHP will process the request only if it was redirected by the web server.

And of course, you can enable the safe_modeand disable register_globals.


Today’s projects are becoming more complex and have increasingly larger scale, and the growing number of visitors create increased load on the server. To overcome the problem of the increasing workload, people start to use caching. The most popular solution is memcached. People very often deploy it without paying enough attention to security issues. As a result, the potential holes can go undetected for years until one day somebody finds it and decides to take advantage of it. Administrators often forget about the settings of the connection to the memcached daemon. On habrahabr.ru, there is [a story] (bit.ly/1Bhfgez) about how this bug was found on phpclub.ru.

Overcoming this problem is quite simple: if the caching service is located on the same machine as the project, it is enough to restrict access to it from local host. To do this, change the line OPTIONS="" in the memcached configuration file to OPTIONS ="-l" and restart memcached. If the caching daemon is located on a separate server, the access to it has to be restricted by a firewall.

To sum up

Actually, the safe settings for each of the products mentioned above can be a subject of a lengthy discussion. The things we looked at today are well-known truths, so we just reviewed the parameters you need to focus on when setting up your server so that it cannot become an easy target for attackers. Once again, we see that not all advice given online is worth following. I hope this article motivates you to double-check your configurations and make sure that they are the right ones.

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>