How to Harden the Apache Web Server on CentOS 7

NOTE: https://www.feistyduck.com/library/apache%2dsecurity/online/

Introduction

Apache is one of the most widely-used and popular web servers. It is also one of the most secure web servers available. In this article, I will explain some tips and tricks that will secure your Apache server.

Requirements

  • A server running CentOS v. 7 with Apache installed
  • A static IP address for your server
  • Firefox browser with the Firebug add-on installed (for testing)

Hide the Apache version

Visit your web server in Firefox. Activate Firebug by clicking the Firebug icon on the top right side.

If you check the HTTP response headers in Firebug, it will show the Apache version along with your operating system name and version, as shown in this screenshot:

To hide this information from browsers, you will need to make some changes in Apache’s main configuration file.

You can do this by editing the httpd.conf file:

sudo nano /etc/httpd/conf/httpd.conf

Add the following line at the end of file:

ServerSignature Off
ServerTokens Prod

Save the file and restart the Apache service to reflect these changes:

sudo apachectl restart

Now, open Firefox and access your web server. Check the HTTP response headers in Firebug, You can see that setting ServerSignature to Off has removed the version information from Server.

Turn off directory listing

Directory listing in the absence of an index file is enabled by default in Apache. Directory listing displays all the files from the Apache web root directory. If this is enabled, then a hacker can easily view any file, analyze it, and obtain sensitive information about an application of your Apache server.

You can turn off this setting by using the Options directive in the Apache configuration file for a specific web directory.

sudo nano /etc/httpd/conf/httpd.conf

Find the section that begins with Directory /var/www/html and add -Indexes in the Options directive:

<Directory /var/www/html/>
    Options -Indexes
    AllowOverride None
    Require all granted
</Directory>

Save the file and restart Apache service to reflect these changes.

sudo apachectl restart

Next, try to visit your website in a browser. You will get a “Forbidden” error.

Disable unnecessary modules

By default Apache comes with lots of unnecessary installed modules. It is a good policy to disable any unnecessary modules that are not in use.

You can list all enabled modules on your server using the following command:

sudo grep LoadModule /etc/httpd/conf.modules.d/00-base.conf

From the enabled modules in 00-base.conf file, some modules like mod_info, mod_userdir, mod_autoindex are enabled but not needed.

You can disable this modules by editing the 00-base.conf file:

sudo nano /etc/httpd/conf.modules.d/00-base.conf

Insert a # at the beginning of the following lines to disable the modules:

#LoadModule info_module modules/mod_info.so
#LoadModule userdir_module modules/mod_userdir.so</code></pre>

Save the file and restart Apache service to reflect these changes.

sudo apachectl restart

By default Apache follows symbolic links (symlinks). Turning this off is recommended for security.

To do this, you need to edit httpd.conf file:

sudo nano /etc/httpd/conf/httpd.conf

Find the section that begins with Directory /var/www/html. Add -FollowSymLinks in option directive:

<Directory /var/www/html/>
    Options -Indexes -FollowSymLinks
    AllowOverride None
    Require all granted
</Directory>

Now restart Apache to reflect changes.

sudo apachectl restart

Turn off server-side includes (SSI) and CGI execution

Server-side includes (SSI) are directives present on Web applications that are placed in HTML pages. An SSI attack allows a web application to be exploited by remotely executing arbitrary codes. The attacker can access sensitive information like password files, and execute shell commands. It is recommended that you disable server side includes and CGI execution if they are not needed.

To do this, edit the main Apache config file:

 sudo nano /etc/httpd/conf/httpd.conf</code></pre>

Find the section that begins with Directory /var/www/html, Add -ExecCGI and -Includes in option directive:

<Directory /var/www/html/>
    Options -Indexes -FollowSymLinks -ExecCGI -Includes
    AllowOverride None
    Require all granted
</Directory>

Now restart Apache to reflect the changes.

sudo apachectl restart

You can also do this for specific web directories. For example, to turn off Includes and CGI file executions for /var/www/html/www.vhost1.com directory:

sudo nano /etc/httpd/conf/httpd.conf

Add the following line:

<Directory /var/www/html/www.vhost1.com/>
    Options -Includes -ExecCGI
</Directory>

Save the file and restart Apache.

sudo apachectl restart

Limit request size

By default Apache has no limit on the size of the HTTP request. This can allow hackers to send large number of data.

You can limit the requests size by using the Apache directive LimitRequestBody in combination with the Directory tag. This can help protect your web server from a denial of service (DOS) attack.

Suppose you have a site (www.example.com), where you allow uploads, and you want to limit the upload size on this site.

You can set value from 0 (unlimited) to 2147483647 (2GB) in the main Apache config file.

For example, to limit the request size for the /var/www/html/www.example.com directory to 200K:

sudo nano /etc/httpd/conf/httpd.conf

Add the following line:

<Directory /var/www/html/www.example.com>
    LimitRequestBody 204800
</Directory>

Save the file and restart Apache.

sudo apachectl restart

Disallow browsing outside the document root

Unless you have a specific need, it is recommended to restrict Apache to being only able to access the document root.

You can secure the root directory / with Allow and Deny options in the httpd.conf file.

sudo nano /etc/httpd/conf/httpd.conf

Add/edit the following line:

<Directory />
    Options None
    Order deny,allow
    Deny from all
</Directory>

Save the file and restart Apache:

sudo apachectl restart
  • Options None : This will turn off all options
  • Order deny,allow : The order in which the allow and deny commands are applied
  • Deny from all : This will deny request from all to the root directory

Keep Apache up to date

The Apache Server has a good record for security. New Apache updates will contain patches that will reduce vulnerability of your Apache server. You should always be using the most recent version of Apache server.

You can update your Apache to the most recent version by running the following command:

sudo yum update httpd

Secure Apache from clickjacking attacks

Clickjacking, also known as “User Interface redress attack,” is a malicious technique to collect an infected user’s clicks. Clickjacking tricks the victim (visitor) into clicking on an infected site.

To avoid this, you need to use X-FRAME-OPTIONS to prevent your website from being used by clickjackers.

You can do this by editing the httpd.conf file:

sudo nano /etc/httpd/conf/httpd.conf

Add the following line:

Header append X-FRAME-OPTIONS "SAMEORIGIN"

Save the file and restart Apache:

sudo apachectl restart

Now, open Firefox and visit your website. When you check the HTTP response headers in Firebug, you should see X-Frame-Options

Disable ETag

ETags (entity tags) are a well-known point of vulnerability in Apache web server. ETag is an HTTP response header that allows remote users to obtain sensitive information like inode number, child process ids, and multipart MIME boundary. ETag is enabled in Apache by default.

To prevent this vulnerability, disabling ETag is recommended.

You can do this by editing httpd.conf file:

sudo nano /etc/httpd/conf/httpd.conf

Add the following line:

FileETag None

Save the file and restart Apache:

sudo apachectl restart

Now, open Firefox and visit your website. When you check the HTTP response headers in Firebug, you should not see Etag listed.

HTTP request methods

Apache support the OPTIONS, GET, HEAD, POST, CONNECT, PUT, DELETE, and TRACE method in HTTP 1.1 protocol. Some of these may not be required, and may pose a potential security risk. It is a good idea to only enable HEAD, POST, and GET for web applications.

You can do this by editing the httpd.conf file:

sudo nano /etc/httpd/conf/httpd.conf

Find the section that begins with Directory /var/www/html. Add the following lines under this section:

<LimitExcept GET POST HEAD>
    deny from all
</LimitExcept>

Save the file and restart Apache:

sudo apachectl restart

Secure Apache from XSS attacks

Cross-site scripting (XSS) is one of the most common application-layer vulnerabilities in Apache server. XSS enables attackers to inject client-side script into web pages viewed by other users. Enabling XSS protection is recommended.

You can do this by editing the httpd.conf file:

sudo nano /etc/httpd/conf/httpd.conf

Add the following line:

<IfModule mod_headers.c>
    Header set X-XSS-Protection "1; mode=block"
</IfModule>

Save the file and restart Apache to reflect changes.

sudo apachectl restart

Now, open Firefox and visit your website. When you check HTTP response headers in Firebug, you should see that XSS Protection is enabled and mode is blocked.

Protect cookies with HTTPOnly flag

You can protect your Apache server from most of the common Cross Site Scripting attacks using the HttpOnly and Secure flags for cookies.

You can do this by editing the httpd.conf file:

sudo nano /etc/httpd/conf/httpd.conf

Add the following line:

<IfModule mod_headers.c>
    Header edit Set-Cookie ^(.*)$ $1;HttpOnly;Secure
</IfModule>

Save the file and restart Apache to reflect changes.

sudo apachectl restart

Let’s Encrypt automatic renewal problem!

I ran into a problem with one of my domain name about a week ago! The problem was related to the automatic renewal of Let’s Encrypt SSL Key. There is a easy fix out there, on this server I am using .htaccess to forward all traffic to https:// the fix is to remove or rename the .htaccess until the SSL key is renewed.

As per today 5-19-2017 Let’s Encrypt gateway make a time-out!


Source : https://statusgator.com/services/lets-encrypt

Cheers

Update :

A new certificate was successfully requested from Let’s Encrypt, and installed for easy-admin.ca, www.easy-admin.ca.

🙂

You lost your Webmin password? No problem!

How to reset Webmin root password?

At times we often forget the webmin password for a given user, say root, or after repeated failed login attempts webmin locks the account and no one cannot login anymore. In this case you need to wait for couple, three minutes and you will be able to try to login again. However, if you’ve forgotten your password and need to change it, then login to the server via ssh and run the following command:

For RHEL/CentOS:

/usr/libexec/webmin/changepass.pl /etc/webmin root NEWPASSWORD

The package could not be installed.

PCLZIP_ERR_MISSING_FILE (-4) : Missing archive file

If WP detects that it cannot write files to your /tmp/…. directory, then you get the error message like “The package could not be installed. PCLZIP_ERR_MISSING_FILE (-4) : Missing archive file”

Solution:

You can work around this by specifying a new temp directory on your server with a place that you know WordPress is allowed to write files to. You can do this by adding this line of code into the wp-config.php file.

1. Find the links blow
if ( !defined(‘ABSPATH’) )
define(‘ABSPATH’, dirname(__FILE__) . ‘/’);

2. Add lines below
/** Specify wordpress temp dir */
define(‘WP_TEMP_DIR’, ABSPATH . ‘wp-content/temp‘);

3. Open wp-content folder,
and create a new folder on your CENTOS Server named temp and make sure you set the right CHOWN for your new created directory!

Try again, you will see it works like a charm.

Easy Fix here!

How to change OpenCart Timezone

OpenCart used globally and operated from different timezone based on site owner place. In most case, OpenCart site run in UTC timezone. This affecting all aspect depend on the time configuration, from product comment, special price to order history.

This is not issue if you can accept the time difference; but of course it’s not logical for the site owner confused either an order is placed today or yesterday because the OpenCart site time is different from their local.

This tutorial covering not just change PHP timezone but also synchronize it with database. Lets start the tutorial with most case assumption that the OpenCart site is run on UTC timezone. To visualize this we use the free extension System Information as on image below.

For this tutorial, I use OpenCart v2.2.x that might be different from your OpenCart version. In order to use this tutorial for your site, you need to do adjustment where the code should change.

Change PHP Timezone

There is two method to change PHP timezone, through php.ini or set them at PHP file directly. To change timezone in php.ini you can ask your hosting provider, because one host to another have different approach.

To use the second method, we will change system/startup.php with PHP supported timezone.

// if (!ini_get('date.timezone')) {     
//   date_default_timezone_set('UTC');      
// }
date_default_timezone_set('Australia/Sydney');

On code above I commented the OpenCart code because I have date.timezone configured in php.ini. This change will give us result:

Most tutorial on change OpenCart timezone finish at this stage. But this is actually wrong. I purposely set the timezone to Australia/Sydney because I know the time different when write this tutorial will be one day with database time that still use UTC.

If you add product review now, which is added to database with sql query now() the date added is 20/03/2016, even though PHP time is March 21, 2016. This will make you think the review is maded yesterday, even though it’s just 5 minute ago.

OpenCart 2.2 have 275+ sql query that use now() and this mean the same thing will happen to Product Special Price, Coupon Code, Voucher, Order, Return and more. If you change PHP timezone, make sure to synchronize with database.

Synchronize PHP and Database Timezone

Synchronize php and database timezone is done by set the database connection timezone. We can try to set global database timezone but that need super privillage user which is not available on shared hosting. Query we use to set database timezone:

SET time_zone='offset';

We use offset and not named timezone because, quoted from MySQL: “Named time zones can be used only if the time zone information tables in the mysql database have been created and populated”. There is no guarantee all hosting have timezone information table in their database instances.

To change OpenCart database connection timezone, we will change system/library/db/mysqli.php and add code below after $this->connection->query(“SET SQL_MODE = ””);

$dt = new \DateTime();
$this->connection->query("SET time_zone='" . $dt->format('P') . "';");

In OpenCart 2.0.x and 2.1.x change $this->connection to $this->link.Since System Information use OcMod to get Database info, it’s important to refresh modification at Extensions > Modification before check the result. This change will give us result:

You can see on image above that date time on PHP and Database is now synchronized.

7 Days to Die is a survival horde crafting game for PC ;-)

With over 1.5 million copies sold on PC (digital download), 7 Days to Die has redefined the survival genre, with unrivaled crafting and world-building content. Set in a brutally unforgiving post-apocalyptic world overrun by the undead, 7 Days to Die is an open-world game that is a unique combination of first person shooter, survival horror, tower defense, and role-playing games. It presents combat, crafting, looting, mining, exploration, and character growth, in a way that has seen a rapturous response from fans worldwide. Play the definitive zombie survival sandbox RPG that came first. Navezgane awaits!

7DaysToDie.com

R.I.P  ~  T H E   R O B  !
1973 – 2017

The “unhide” command used by rkhunter!

The unhide command for RKHUNTER in CentOS 7 must be installed with the following “Yum” command:

yum install unhide unhide-tcp

I have detected that rkhunter need this file to be able to unhide stuff!

Info: Starting test name ‘malware’
Performing malware checks
Info: Test ‘deleted_files’ disabled at users request.
Info: Starting test name ‘running_procs’
Checking running processes for suspicious files [ None found ]
Info: Starting test name ‘hidden_procs’
Info: Unable to find the ‘unhide’ command
Info: Unable to find the ‘unhide-linux’ command
Checking for hidden processes
[ Skipped ]

rkhunter command line

rkhunter help

Have Phun!

YUM Commands

YUM Commands

Package manager used by RPM based systems, you can pull some usefull information about installed packages and or install additional tools.

COMMANDDESCRIPTION
yum updateUpdate all RPM packages with YUM, also shows whats out of date.
yum update httpdUpdate individual packages, in this example HTTPD (Apache).
yum install packageInstall a package using YUM.
yum --exclude=package kernel* updateExclude a package from being updates with YUM.
yum remove packageRemove package with YUM.
yum erase packageRemove package with YUM.
yum list packageLists info about yum package.
yum provides httpdWhat a packages does, e.g Apache HTTPD Server.
yum info httpdShows package info, architecture, version etc.
yum localinstall blah.rpmUse YUM to install local RPM, settles deps from repo.
yum deplist packageShows deps for a package.
yum list installed | moreList all installed packages.
yum grouplist | moreShow all YUM groups.
yum groupinstall 'Development Tools'Install YUM group.

CentOS 7 System Information Commands

System Information Commands

Useful for local enumeration.

COMMANDDESCRIPTION
whoamiShows currently logged in user on Linux.
idShows currently logged in user and groups for the user.
lastShows last logged in users.
mountShow mounted drives.
df -hShows disk usage in human readable output.
echo "user:passwd" | chpasswdReset password in one line.
getent passwdList users on Linux.
strings /usr/local/bin/blahShows contents of none text files, e.g. whats in a binary.
uname -arShows running kernel version.
PATH=$PATH:/my/new-pathAdd a new PATH, handy for local FS manipulation.
historyShow bash history, commands the user has entered previously.

Sysctl Security

#nano /etc/sysctl.conf

net.ipv4.ip_forward = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.tcp_max_syn_backlog = 1280
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.secure_redirects = 0
net.ipv4.conf.all.log_martians = 1
net.ipv4.conf.default.accept_source_route = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.default.secure_redirects = 0
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.icmp_ignore_bogus_error_responses = 1
net.ipv4.tcp_syncookies = 1
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
net.ipv4.tcp_timestamps = 0