Protecting a web server on Linux

Original author: David Clinton
  • Transfer
Hi, Habr!

We haven't had any new books on Linux for beginners for a long time - and now we take on the translation of a novelty of just such a plan. The book " Linux in Action " by David Clinton was published by Manning and tells not only about the internal structure of Linux , but also about the most common problems, and how to eliminate them.


The author has published on the Hackernoon website an excerpt from the ninth chapter, which we invite you to evaluate.

Assembling a LAMP server, how to configure it, ensure reliable data processing, set up a subject area and attend to a TLS certificate is only half the journey to victory. You also need to make sure your infrastructure is protected from the many daunting threats of the Internet.

In this article, we explore the security of a website, learning how to work with system groups, ensure process isolation and regular audit of system resources. Of course, this story is not complete (other topics are discussed in the Linux book, for example, installing TLS certificates and working with SELinux), but this will be quite enough for a start.

System groups and the principle of minimum privileges


Developers whose support you are engaged in (finally) are beginning to realize that it is necessary to limit the general access to data and configuration files located on the application server, but at the same time, leave such access open to various programming and other IT commands.

The first part of the solution is the groups . A group is an object in the system (approximately as a user) with the proviso that no user will ever log in as a group. The power of groups lies in the fact that they, like users, can be “assigned” to files or directories, allowing each member of the group to use the powers provided for it. This is illustrated below.

Developers who are part of the Developers group can access a specific directory, and for users who are not in this group, the directory will be closed.
Try it yourself: create a new file in a text editor. Write a simple text in it, for example, “Hello World”, so that you can immediately see when the file was successfully accessed. Then edit the permissions using chmod 770, so that the owner of the file and the members of the group to which he belongs have full rights to work with the file, while others cannot read it.

$ nano datafile.txt
$ chmod 770 datafile.txt

If there are no other user accounts other than your own in your system, create such an account either with the help of adduser - this is done in Debian / Ubuntu - or with the help useradd, as is customary in CentOS. The team useraddwill work in Ubuntu.

The command useradd, unlike adduserin Debian, requires that a user password be generated separately:

# useradd otheruser# passwd otheruser
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully

With the help of the command suswitch to the new user. After we enter his password, all of the following commands will be executed on behalf of this user. You will work on behalf of this particular user; no more, no less. If you try to read the data file datafile.txt(with help cat), then nothing will come of it anymore; as you remember, only group members have read permissions. When done, enter exitto exit the shell of the new user, and return to your original shell.

$ su otheruser
Password:
$ cat /home/ubuntu/datafile.txt
cat: /home/ubuntu/datafile.txt: Permission denied
$ exit

All this is expected and quite understandable. As you can see, when you can not read a file belonging to another user - this is sometimes a problem. Let's see what can be done by associating a file with a group, and then properly configuring file permissions.

Create a new group with which we can manage the data of our application, and then edit the properties of our data file with the command chown. The ubuntu: app-data-group argument leaves the Ubuntu user the right to own the file, but its group is changed to a new one: app-data-group.

# groupadd app-data-group# chown ubuntu:app-data-group datafile.txt

Run ls to get a “expanded” output of this file and view its new access rights and status. Note: as expected, the file ubuntubelongs to the user belonging to the group app-data-group.

$ ls -l | grep datafile.txt
-rwxrwx — — 1 ubuntu app-data-group6 Aug 922:43 datafile.txt

You can apply usermodto add your user to app-data-group, and then the command suto switch to the shell in which the other user’s account is deployed. Now, even though the file permissions close it from all “others” - and you are definitely a “different” user at the moment - you should read this file freely, as you belong to the right group.

# usermod -aG app-data-group otheruser
$ su otheruser
$ cat datafile.txt
Hello World

With the help of the command suswitch between user accounts. They are recorded in my file datafile.txt. Such an organization is the right and effective way to eliminate various complex problems with access rights that may arise in a multi-user system.

In fact, it is used not only to provide the necessary access rights to individual users - many system processes would also not be able to carry out their tasks if they were not assigned to belong to the right groups. You can view the / etc / group file diagonally - notice how many system processes belong to their own groups ...

Abbreviated listing of the contents of / etc / group file:

$ cat /etc/group
root:x:0:
daemon:x:1:
bin:x:2:
sys:x:3:
adm:x:4:syslog
tty:x:5:
disk:x:6:
lp:x:7:
mail:x:8:
news:x:9:
uucp:x:10:
man:x:12:
proxy:x:13:
[]

Isolation of processes in containers


Perhaps you are worried that many services running on one server for you will be at risk if at least one of these services is hacked? One option to mitigate such damage that careless or malicious users can cause is to isolate system resources and processes. Thus, even if someone wishes to expand his authority beyond the established limits, he will not receive physical access to the data.

Previously, this problem was decided to solve as follows: for each service, they allocated their own physical machine. However, thanks to virtualization, it becomes much easier and cheaper to build a “mesh” architecture. Today, such an architecture is often referred to as microservice.and allows you to run multiple containers at once, in one of which can work, for example, a database, in the other - Apache, and in the third - media files that can be embedded in your web pages. Microservice architecture allows not only to significantly increase performance and efficiency, but also significantly reduces the risk of hacking of each individual component.

The “containers” I’m talking about do not have to be convincing LXC. Other container technologies, such as Docker, are becoming much more popular today.

Check for dangerous user ID values


Of course, any user with administrator rights can temporarily provide a root-access command sudo, but only the admin is a genuine admin. As you already know, it is not safe to perform regular functions under root access. However, it may happen - either purely by chance or due to malicious falsification of data - that a regular user will have administrative rights without any interruptions.

In this case, it is good that it is easy to identify such impostors: their user and / or group ID, like the admin, will have a “0”. Take a look at the passwd file in the / etc / directory. This file contains an entry for each regular and system user account that already exists in the system. The first field contains the account name (in this case, root and ubuntu), and the second field can contain x instead of the password (if the password exists, it will be in the encrypted form in the / etc / shadow file). But the following two fields contain a user and group ID. In the case of ubuntuin this example, both IDs are 1000. And the administrator, as you can see, has zeros here.

$ cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
[…]
ubuntu:x:1000:1000::/home/ubuntu:/bin/bash

If you ever meet a regular user with a user or group ID = 0, then you can be sure that this is unclean, and the situation needs to be rectified. A quick and easy way to detect such a problem is to check the file with a passwdcommand awkthat displays all the lines in the third field of which there is nothing except 0. In my case (you can breathe out) there was only one such line - the root. You can run it again, replacing $ 4 with $ 3 - so you check the group ID field.

$ awk -F: ‘($3 == “0”) {print}’ /etc/passwd
root:x:0:0:root:/root:/bin/bash

System Resource Audit


The more all sorts of things you have in the system, the higher the likelihood that something in it will break. Therefore, it is reasonable to keep track of what works. Speech in this case is about network ports (if the port is “open”, then by definition there should be an input), services (if the service is active, then it should be possible to use it) and about installed programs (if the program is installed, then it should be the ability to perform it).

For an audit to be beneficial, it must be more or less regular. Since we are all forgetful, it is much better to write the audit tools in a special script that will not only run regularly but also ideally parse the results so that they become more readable.

Here, however, I will introduce you to three key audit tools that will help you view open ports, active services, and unnecessary software packages. Your task is to automate all this.

Port scan


A port is considered “open” if a process is running on the host that listens for requests on that port. Watching over your open ports, you will better understand what is happening on your server.

You already know that HTTP (80) and SSH (22) ports should probably be open on a regular web server, so they won't surprise you. But it is much more important to pay attention to other, unexpected results. The netstat command displays all open ports, as well as a wealth of information about exactly how they are used.

In this example, we check a completely typical multi-purpose server, and the team -norders netstatto include all numeric ports and addresses. -lincludes only listening sockets, and-padds the process ID of the listener. Naturally, if you see something - act.

# netstat -nplActive Internet connections (only servers)
Proto Local Address Foreign Address State PID/Program name
tcp 127.0.0.1:33060.0.0.0:* LISTEN 403/mysqld
tcp 0.0.0.0:1390.0.0.0:* LISTEN 270/smbd
tcp 0.0.0.0:220.0.0.0:* LISTEN 333/sshd 
tcp 0.0.0.0:4450.0.0.0:* LISTEN 270/smbd
tcp6 :::80 :::* LISTEN 417/apache2 
[…]

In recent years, instead of netstatincreasingly used ss. Just to be on the safe side: if ever you find yourself in the company, and someone asks you about ss, then this example (which lists all the established SSH connections) should be informative enough so that you can’t lose face.

$ ss -o state established ‘( dport = :sshor sport = :ssh )’
Netid Recv-Q Send-Q Local Address:Port Peer Address:Port 
tcp 0010.0.3.1:3987410.0.3.96:sshtimer:(keepalive,18min,0)

We check active services


If you take a quick, instant snapshot of the services that are managed systemand currently active on your computer, the machine will help identify any unwanted activity. The team systemctlcan list all existing services, and then their list can be narrowed down to those in the description of which is contained enabled. Only active services will be returned this way.

# systemctl list-unit-files — type=service — state=enabled
autovt@.service                       enabled 
bind9.service                         enabled 
cron.service                          enabled 
dbus-org.freedesktop.thermald.service enabled 
docker.service                        enabled 
getty@.service                        enabled 
haveged.service                       enabled 
mysql.service                         enabled 
networking.service                    enabled 
resolvconf.service                    enabled 
rsyslog.service                       enabled 
ssh.service                           enabled 
sshd.service                          enabled
syslog.service                        enabled 
systemd-timesyncd.service             enabled 
thermald.service                      enabled 
unattended-upgrades.service           enabled 
ureadahead.service                    enabled

If you find something that is clearly not the place, you can use the command systemctlto stop the service and to make sure that it does not restart on the next boot.

# systemctl stop haveged# systemctl disable haveged

In fact, there is nothing dark and gloomy in the service havegedthat I stop in this example: these are the tools that I often run to create random background system activity when I create encryption keys.
Search for installed programs

Could someone install programs in the system without your knowledge? Well, to find out - you need to look. The command yum list installedor, in the case of Debian / Ubuntu, dpkg — list will give you a detailed summary, and the remove command should remove all the packages that we do not need.

# yum list installed# yum remove packageName

Here's how the same thing is done in Ubuntu:

# dpkg --list# apt-get remove packageName

It is also useful to keep track of the changes that are made to your system configuration files — we'll talk about this in Chapter 11.

Also popular now: