Local Security
By the end of this section, you should know:
- The purpose of a
chroot
environment and how it enhances local security by restricting users to a defined directory. - How to create a basic
chroot
directory and structure it to mimic a limited root file system. - How to set up and test the
chroot
environment to ensure users are confined to their pseudo-root directory. - The process for identifying and copying necessary binaries and their dependencies into a
chroot
. - Basic troubleshooting techniques for common issues that may arise when setting up or entering a
chroot
. - The limitations of
chroot
for security and how it serves as a foundational concept for containerization technologies like Docker. - How to configure SSH to restrict specific user groups to a
chroot
environment for added security.
Getting Started
Security challenges predominantly emanate from network interactions;
however, safeguarding a system from potential internal threats is equally critical.
This can be achieved by enforcing stringent file permissions and ensuring that users lack certain types of access, such as sudo
privileges.
Take, for instance, the program /usr/bin/gcc
.
gcc
serves as the GNU C and C++ compiler, translating C or C++ source code into executable programs (like exe
programs on Windows computers).
Unrestricted access to this compiler could potentially allow users to create programs capable of compromising the system
(I know, based on personal experience).
In the following section, we will shift focus to external threats and learn about setting up a firewall.
In this section, we focus on internal threats and learn how to create a chroot environment.
This is a specialized environment that restricts user operations or processes to a defined directory, thereby bolstering system security.
By delving into the setup of a chroot
environment, we will unveil an effective strategy that can mitigate risks stemming from within the system.
chroot
As we all know, the Linux file system has a root directory /, and under this directory are other directories like /home, /bin, and so forth.
A chroot
(change root) environment is a way to create a fake root directory at some specific location in the directory tree, and
then build an environment in that pseudo root directory that offers some applications.
Once that environment is setup, we can confine a user account(s) to that pseudo directory, and when they login to the server,
they will only be able to see (e.g., with the cd
command) what's in that pseudo root directory and only be able to use the applications that
we've made available in that chroot.
Thus, a chroot
is a technology used to change the "apparent root / directory for a user or a process" and
confine that user to that location on the system.
A user or process that is confined to the chroot
cannot easily see or access the rest of the file system and
will have limited access to the binaries (executables/apps/utilities) on the system.
From its man
page:
chroot (8) - run command or interactive shell with special root directory
Although it is not security proof, it does have some useful security use cases.
Some use chroot
to contain DNS or web servers, for example.
chroot
is also the conceptual basis for some kinds of virtualization technologies that are common today, like Docker.
Creating a chroot
In this tutorial, we are going to create a chroot
.
-
First, we create a new directory for our chroot. That directory will be located at
/mustafar
(but it could be elsewhere). Note that the normal root directory is/
, but for the chroot, the root directory will be/mustafar
even though it will appear as/
in thechroot
.Depending on where we create the chroot, we want to check the permissions of the new directory and make sure it's owned by root. If not, use
chown root:root /mustafar
to set it.Create directory:
sudo mkdir /mustafar
Check user and group ownership:
ls -ld /mustafar
-
We want to make the
bash
shell available in the chroot. To do that, we create a/bin
directory in/mustafar
, and copybash
to that directory.which bash sudo mkdir /mustafar/bin sudo cp /usr/bin/bash /mustafar/bin/
ALTERNATIVELY: use command substitution to copy
bash
:sudo mkdir /mustafar/bin sudo cp $(which bash) /mustafar/bin
-
Large software applications have dependencies, aka libraries. We need to copy those libraries to our chroot directory so applications,like
bash
, can run.To identify libraries needed by
bash
, we use theldd
command:ldd /usr/bin/bash
Do not copy!! Output (output may vary depending on your system):
linux-vdso.so.1 (0x00007fff2ab95000) libtinfo.so.6 => /lib/x86_64-linux-gnu/libtinfo.so.6 (0x00007fbec99f6000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fbec97ce000) /lib64/ld-linux-x86-64.so.2 (0x00007fbec9ba4000)
Ignore the first item in the output (
linux-vdso.so.1
). But we will need the libraries in the last three lines. -
Next we create directories for these libraries in
/mustafar
that match or mirror the directories they reside in. For example, in the aboveldd
output, two directory paths are highlighted:/lib/x86_64-linux-gnu
and/lib64
. Therefore, we need to create directories with those names in/mustafar
.To do that, use the
mkdir
command to create a/mustafar/lib/x86_64-linux-gnu/
directory and a/mustafar/lib64
for the libraries. We need to name the library directories after the originals to stay consistent with the main environment.sudo mkdir -p /mustafar/lib/x86_64-linux-gnu
And then:
sudo mkdir /mustafar/lib64
Then we proceed to copy (not move!) the libraries to their respective directories in the /mustafar directory:
cd /mustafar/lib/x86_64-linux-gnu/ sudo cp /lib/x86_64-linux-gnu/libtinfo.so.6 . sudo cp /lib/x86_64-linux-gnu/libc.so.6 cd /mustafar/lib64/ sudo cp /lib64/ld-linux-x86-64.so.2 .
-
Finally, we can test the
chroot
:sudo chroot /mustafar
If successful, you should see a new prompt like below:
bash-5.1#
If you try running some commands, that are not part of Bash itself, you'll encounter some errors.
We do have access to some commands, like
help
,dirs
,pwd
,cd
, and more because these are builtin tobash
. Utilities not builtin tobash
are not yet available. These includels
,cat
,cp
, and more. The following is a brief example of interacting in a limited chroot environment with no outside utilities available:bash-5.1# ls bash: ls: command not found bash-5.1# help bash-5.1# dirs bash-5.1# pwd bash-5.1# cd bin/ bash-5.1# dirs bash-5.1# cd ../lib64/ bash-5.1# dirs bash-5.1# cd .. bash-5.1# for i in {1..4} ; do echo "$i" ; done
To exit the
chroot
environment, simply typeexit
:bash-5.1# exit
Exercise
Use the ldd
command, to add additional binaries.
Make the following utilities/binaries available in the /mustafar
chroot directory:
ls
cat
Troubleshooting Common chroot Setup Errors
When setting up a chroot
environment, you may encounter an error like:
chroot: failed to run command '/bin/bash': No such file or directory
This error often occurs if the chroot
environment is missing critical files or directories, such as the bash
executable or its required libraries. Here are some steps to resolve this:
-
Check for the Bash Binary: Ensure that the
bash
executable has been correctly copied to/mustafar/bin/
:sudo ls /mustafar/bin/bash
If this file isn't there, go back to the step where you copy
bash
to thechroot
directory. -
Verify Library Dependencies: The
bash
binary requires certain libraries to run. Use theldd
command to list these dependencies and confirm they are copied to/mustafar
:ldd /usr/bin/bash
Ensure each library listed is copied to the matching directory within
/mustafar
, such as/mustafar/lib/x86_64-linux-gnu/
and/mustafar/lib64/
. -
Correct File Structure: Confirm that your
chroot
directory structure mirrors the actual root structure. The paths within/mustafar
should match the paths of the dependencies found usingldd
.
After confirming these items, try running chroot
again:
sudo chroot /mustafar
If these checks don't resolve the issue, double-check permissions on the chroot
directory to ensure root ownership:
sudo chown root:root /mustafar
Conclusion
Systems need to be secure from the inside and out. In order to secure from the inside, system users should be given access and permissions as needed.
In this section, we covered how to create a chroot environment.
The chroot confines users and processes to this pseudo root location.
It provides them limited access to the overall file system and to the software on the system.
We can use this chroot to confine users and processes, like apache2 or human users.
Any user listed in /etc/passwd
can be chrooted, and most users listed in that file are services.
Restricting a human user to a chrooted environment may not be necessary.
On a multi-user system, proper education and training about the policies and uses of the system may be all that's needed.
Alternatively, when creating user accounts, we could make their default shell rbash
, or restricted bash.
rbash
limits access to a lot of Bash's main functions, and for added security, it can be used in conjunction with chroot
.
See man rbash
for more details.
In summary, if a stricter environment is needed, you know how to create a basic chroot
environment.
Additional Sources:
- How to automatically chroot jail selected ssh user logins.
- BasicChroot
- How to Use chroot for Testing on Ubuntu
- How To Setup Linux Chroot Jails
Appendix A: Non-Google Cloud Systems
Our user accounts and connections to our Google Cloud virtual instances are managed on the Google Cloud console,
and we reach these instances using the gcloud compute ssh
command.
The gcloud
command is special software that we installed on our personal systems and authentication happens via our Google accounts.
However, on traditional remote systems, we use ssh
with its standard syntax, which is: ssh user@domain.com
or ssh user@<ip_address>
,
where user
is the account name managed directly on the server and domain.com
is the host name of the server.
On those traditional types of systems, we can take advantage of chroot
to isolate user accounts to a chrooted environment.
There are a number of ways to do this, but below I demonstrate how to isolate users to a chrooted environment based on their group membership.
-
Let's create a new user. After we create the new user, we will
chroot
that user going forward.sudo adduser vader
-
Create a new group called
mustafar
. We can add users to this group that we want to jail in a chrooted environment.sudo groupadd mustafar sudo usermod -a -G mustafar vader groups vader
-
Edit
/etc/ssh/sshd_config
to direct users in thechrootjail
group to thechroot
directory. Add the following line at the end of the file. Then restart ssh server.sudo nano /etc/ssh/sshd_config
Then add:
Match group mustafar ChrootDirectory /mustafar
Exit
nano
, and restartssh
:systemctl restart sshd
-
Test the
ssh
connection for thevader
user. Here I usessh
on the local system to connect to the local system, simply to test it.ssh vader@localhost -bash-5.1$ ls -bash: ls: command not found exit
That works as expected. The user
vader
is now restricted to a special directory and has limited access to the system or to any utilities on that system.
Appendix B: Additional Tools for Securing Multi-User Shell Systems
In addition to chroot
and rbash
, other Linux tools can help secure multi-user, shell-accessible systems.
These tools can be used to restrict file modifications, monitor system changes, and limit user actions.
Together they provide an extra layer of control and protection.
-
chattr
(Change File Attributes)The
chattr
command changes file attributes on Linux filesystems. By setting certain attributes on files, you can restrict users—even with superuser permissions—from modifying critical files. This is particularly useful for preventing accidental or malicious deletion or alteration of configuration files and other sensitive data.- Common Usage: The most frequently used option is the
+i
(immutable) attribute, which prevents modification or deletion.
sudo chattr +i /path/to/important/file
Once this attribute is set, the file cannot be modified, renamed, or deleted until the attribute is removed with
chattr -i
.- Other Options: There are additional flags to explore, such as
+a
, which allows only appending to a file, which is useful for log files that should not be altered.
- Common Usage: The most frequently used option is the
-
lsattr
(List File Attributes)The
lsattr
command is used to view the attributes set bychattr
. This command shows you which files are immutable or otherwise restricted. It allows administrators to verify that critical files have the appropriate protections.- Common Usage:
lsattr /path/to/important/file
This command outputs a list of attributes and helps administrators quickly identify files that are protected or have special restrictions.
-
sudo
andsudoers
ConfigurationThe
sudo
command grants specific users permission to execute commands as superuser, but thesudoers
file can also be configured to limit which commands a user may execute withsudo
. By restrictingsudo
permissions, you can allow users access to only the commands they need to perform their roles.- Common Usage: Open the
sudoers
file withvisudo
to edit user permissions. For example, to allow a user only to usels
andcat
withsudo
, add:
username ALL=(ALL) /bin/ls, /bin/cat
- Common Usage: Open the
-
ulimit
(User Limits)The
ulimit
command sets resource limits for user sessions, such as maximum file sizes, number of open files, and CPU time. This is essential in preventing users from consuming excessive resources, which could slow down or crash the system.- Common Usage: To set a file size limit of 100MB for a session, use:
ulimit -f 100000
You can make these limits permanent for specific users by adding them to the user’s shell configuration file (e.g.,
~/.bashrc
) or to the/etc/security/limits.conf
file for global settings. If you add them to a user's~/.bashrc
file, you can use thechattr
command to prevent the user from editing that file. -
faillock
and Account Lockout Policiesfaillock
helps protect against brute-force attacks by locking user accounts after a specified number of failed login attempts. This can prevent unauthorized access to user accounts.- Common Usage: To set a policy that locks an account for 10 minutes after three failed login attempts, edit
/etc/security/faillock.conf
:
deny = 3 unlock_time = 600
Then, restart your authentication services to apply the changes.
- Common Usage: To set a policy that locks an account for 10 minutes after three failed login attempts, edit
-
iptables
for Access ControlWhile traditionally used for network security,
iptables
can also be configured to control user access to certain resources or services. For example, you can restrict SSH access to specific IP addresses, reducing the attack surface on multi-user systems.- Common Usage: To limit SSH access to users coming from a specific IP address:
sudo iptables -A INPUT -p tcp --dport 22 -s <allowed_ip> -j ACCEPT sudo iptables -A INPUT -p tcp --dport 22 -j DROP
On Debian-based systems, including Ubuntu, you can use the
ufw
command (Uncomplicated Firewall) instead ofiptables
:To permit SSH access (port 22) only from a specific IP address, use:
sudo ufw allow from <allowed_ip> to any port 22
To block SSH access from all other IPs, use:
sudo ufw deny 22
For example, to block SSH traffic from
192.168.1.100
, you would write:sudo ufw allow from 192.168.1.100` to any port 22 sudo ufw deny 22
Make sure
ufw
is active and running with these commands:sudo ufw enable sudo ufw status
Combined with chroot
and rbash
, these create a layered approach to security for multi-user shell systems.
Each tool has specific use cases, but together they help administrators establish a secure and controlled environment.