Sudo: запретить escapes shell'а по умолчанию

Есть ли причина иметь shebang, указывающий на /bin/sh, а не на /bin/bash?

Да. В отличном ответе @Marco это хорошо описано.

Что я должен использовать в моем shebang?

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

В моей системе (Centos 6.6), sh связан симлинком с bash:

$ ls -l /bin/sh 
lrwxrwxrwx 1 root root 4 Dec  2  2014 /bin/sh -> bash

Это означает, что я всегда использую #!/bin/bash в моем shebang, если я не проверил, что в моем скрипте нет bashims.

Устанавливая в shebang значение #!/bin/sh, вы обещаете, что скрипт будет работать со всеми реализациями sh.

Это гораздо большее обещание, чем сказать, что скрипт будет работать с bash.

Вот пример скрипта, который будет вести себя неправильно в зависимости от того, какую реализацию sh использует система:

#!/bin/sh
n=1
a=$((++n))
echo $n

При использовании bash скрипт будет печатать:

2

При использовании dash скрипт выведет:

1

Если я хочу использовать #!/bin/sh, что мне нужно сделать?

  • Проверьте скрипт с помощью checkbashisms - Обратите внимание, что он не найдет все bashims. Он не нашел башизм в моем скрипте выше
  • Проверьте скрипт, используя другую реализацию sh. Я обычно тестирую с dash, однако я ожидаю, что некоторые башизмы или дашимы все равно могут проскочить.

На странице DashAsBinSh в вики Ubuntu есть много интересной информации.

3
09.10.2018, 03:23
2 ответа

Не делай этого.

Вы даете sudo-userвозможность выполнять любые команды от имени любого пользователя. Это включает в себя возможность изменять/etc/sudoersс помощью любого инструмента, который не требует выполнения подпроцессов -. Вы можете подумать, что это исключает visudo, но, строго говоря, вам не нужно visudoдля редактирования /etc/sudoers.

Как, например:

sudo-user$ sudo sed --in-place -e '/^sudo-user/s/NOEXEC://' /etc/sudoers

...и пользователь только что снял ограничение NOEXEC:.

Ограничение, которое пользователь может снять по своему желанию, не является истинным ограничением.


Кроме того, NOEXEC:может вызвать проблемы. Это не только предотвращает выходы из оболочки :, но и предотвращает прямой запуск любой другой программы программой, выполняемой с помощью sudoиз . Это может иметь много последствий.

Например, если ваш sudo-userостанавливает, а затем перезапускает демон cron(, т.е. чтобы остановить запланированные задания на время некоторого обслуживания ), перезапущенный демон cronне сможет фактически выполнять какие-либо запланированные задания из-за ограничения NOEXEC:.

NOEXEC:существует для того, чтобы системный администратор мог применять его к тщательно отобранным программам, способным выполнять свои задачи без exec()включения каких-либо подпроцессов -. Слепое применение его ко всему ко всему вызовет проблемы.


Но если вам это абсолютно необходимо, вот как это сделать.

Из справочной страницы sudoers(5):

User specification
 User_Spec ::= User_List Host_List '=' Cmnd_Spec_List \
               (':' Host_List '=' Cmnd_Spec_List)*

 Cmnd_Spec_List ::= Cmnd_Spec |
                    Cmnd_Spec ',' Cmnd_Spec_List

 Cmnd_Spec ::= Runas_Spec? SELinux_Spec? Tag_Spec* Cmnd

 Runas_Spec ::= '(' Runas_List? (':' Runas_List)? ')'

 SELinux_Spec ::= ('ROLE=role' | 'TYPE=type')

 Tag_Spec ::= ('EXEC:' | 'NOEXEC:' | 'FOLLOW:' | 'NOFOLLOW' |
               'LOG_INPUT:' | 'NOLOG_INPUT:' | 'LOG_OUTPUT:' |
               'NOLOG_OUTPUT:' | 'MAIL:' | 'NOMAIL:' | 'PASSWD:' |
               'NOPASSWD:' | 'SETENV:' | 'NOSETENV:')

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

Давайте разберемся, используя ваш пример строки:

sudo-user ALL=(ALL) NOEXEC: NOPASSWD: ALL

Вся строка известна как пользовательская спецификация или User_Spec.

Он разбивается следующим образом:

  • User_Listв вашем примере есть только один пользователь:sudo-user
  • Host_Listимеет только одну запись,ALL
  • Cmnd_Spec_Listв вашем примере(ALL) NOEXEC: NOPASSWD: ALL
  • в этой строке больше нет : Host_List = Cmnd_Spec_Listединиц (звездочка после круглых скобок предполагает, что таких дополнительных единиц может быть ноль или больше.)

В вашем Cmnd_Spec_Listнет запятых, поэтому в нем только одна Cmnd_Spec.

Cmnd_Specраспадается на:

  • опциональноRunas_Spec:в вашем случае(ALL)
  • необязательный SELinux_Spec, которого нет в вашем примере
  • ноль или более Tag_Specs, это та часть, о которой вы хотите знать
  • Cmnd, команда, которая в вашем случае ALL.

А одинарное Tag_Spec— это просто одно из перечисленных ключевых слов с двоеточием в конце, без запятой, пробела или другого явно указанного разделителя. Строка Cmnd_Spec ::=говорит нам, где именно поставить пробелы в этой строке. Поскольку нет инструкций по размещению пробелов или любых других разделителей между тегами, не делайте этого.

Итак, просто поставьте теги один за другим , вот так:

sudo-user ALL=(ALL) NOEXEC:NOPASSWD: ALL
17
27.01.2020, 21:07

Объединяя два приведенных ответа, как насчет этого?:

Defaults noexec
root    ALL=(ALL)       ALL
%wheel  ALL=(ALL)       ALL
sudo-user ALL=(ALL)     EXEC:NOPASSWD:  ALL
fred ALL=(ALL)          NOPASSWD:  user_allowed_commands

На самом деле, я предлагаю предоставить неограниченный доступ пользователю sudo -. Кажется, это рекомендуемый метод (в Ubuntu и др., по крайней мере ), а не использование root. Я уже проверяю каталог /etc/sudoers, как это происходит. Это позволяет fred запускать список команд в «пользователь _разрешенные _команды» (, предполагая, что fork/exec не нужен, что кажется маловероятным, TBH -, или я неправильно понимаю, что делает noexec?)

Я хотел бы добавить это от @telcoM :Ограничение, которое пользователь может снять по своему желанию, не является истинным ограничением.

Во всех реализациях SELinux, которые я видел, он не является неизменным, поэтому любой пользователь может запустить setenforce permissive, и все ограничения будут сняты.

0
27.01.2020, 21:07

Теги

Похожие вопросы