Есть ли оболочка, которая проверяет, что код подписан?

19

На этой неделе я возился с PowerShell и обнаружил, что вы обязаны подписывать свои скрипты, чтобы их можно было запускать. Есть ли в Linux аналогичные безопасные функции, связанные с предотвращением запуска скриптов bash?

Единственная функциональность, похожая на эту, о которой я знаю, - это то, что SSH требует определенного ключа.

leeand00
источник
2
Это звучит как специальное решение для подписи пакетов для меня. Я не знаю, имеет ли Windows криптографический пакет, подписывающий то же, что и в Linux.
Wildcard
6
@ leeand00 Сценарий - это особый случай программного пакета, и я не вижу смысла выделять этот случай.
Жиль "ТАК ... перестать быть злым"
2
Механизм, который мне больше всего нравится, - это способ, которым ChromeOS делает это - размещение единственной файловой системы, не помеченной noexecв разделе, доступном только для чтения, на блочном устройстве со знаком dm-verity.
Чарльз Даффи
1
source.android.com/security/verifiedboot рассказывает о принятии Android этой функции (первоначально ChromeOS).
Чарльз Даффи
1
Вы можете рассматривать bash как набор команд, которые можно вводить вручную в интерфейсе командной строки. Какой смысл ограничивать скрипты, когда вы все равно можете вводить содержимое в командной строке?
Дин-Йи Чен

Ответы:

11

Если вы блокируете возможность пользователей запускать сценарии через, sudoвы можете использовать эту digestфункциональность.
Вы можете указать хеш скрипта / исполняемого файла, sudoersкоторый будет проверен sudoперед выполнением. Таким образом, хотя это не то же самое, что подпись, это дает вам основную гарантию того, что скрипт по крайней мере не был изменен без изменений sudoers.

Если к имени команды добавляется префикс Digest_Spec, команда будет успешно соответствовать, только если ее можно проверить с помощью указанного дайджеста SHA-2. Это может быть полезно в ситуациях, когда пользователь, вызывающий sudo, имеет доступ на запись к команде или ее родительскому каталогу. Поддерживаются следующие форматы дайджеста: sha224, sha256, sha384 и sha512. Строка может быть указана в формате hex или base64 (base64 более компактный). Существует несколько утилит, способных генерировать дайджесты SHA-2 в шестнадцатеричном формате, таких как openssl, shasum, sha224sum, sha256sum, sha384sum, sha512sum.

http://www.sudo.ws/man/1.8.13/sudoers.man.html

batfastad
источник
Это удержит меня, пока я не прочитаю о SE Linux и не сделаю все правильно
leeand00
13

Да и нет.

Распределение программного обеспечения Linux работает несколько иначе, чем распространение программного обеспечения Windows. В мире (не встроенного) Linux основным методом распространения программного обеспечения является дистрибутив (Ubuntu, Debian, RHEL, Fedora, Arch и т. Д.). Все основные дистрибутивы систематически подписывают свои пакеты уже около десяти лет.

Когда программное обеспечение распространяется независимо, поставщик должен решить, как он будет поставлять свое программное обеспечение. Хорошие поставщики предоставляют источники пакетов, которые совместимы с основными дистрибутивами (нет единого механизма распространения для всех Linux: распространение программного обеспечения является одной из основных точек различия между дистрибутивами) и которые подписаны ключом поставщика. Дистрибутивы Linux редко выступают в роли подписывающего органа для сторонних поставщиков (Canonical делает это с партнерами по Ubuntu, но охватывает очень мало поставщиков), и я думаю, что все основные дистрибутивы используют сеть доверия PGP, а не инфраструктуру открытых ключей TLS, поэтому пользователь должен выяснить, хотят ли они доверять ключу.

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

Я думаю, что Windows аннотирует файлы с их происхождением и требует подтверждения пользователя для запуска файла, источник которого «загружен», а не «локальный». У Linux действительно нет похожего механизма. Наиболее близким является разрешение на выполнение: загруженный файл не имеет разрешения на выполнение, пользователь должен явно включить его ( chmod +xв командной строке или аналогичное действие в файловом менеджере).

Жиль "ТАК - прекрати быть злым"
источник
2
FWIW, в дополнение к этому PowerShell можно настроить (с помощью параметров политики) на выполнение только подписанных сценариев, а эту политику можно настроить так, чтобы все сценарии были подписаны или только сценарии «удаленного происхождения», или не сценарии. Он лучше всего работает в среде AD с управлением ключами и централизованным управлением политиками. Это можно обойти :-)
Стивен Харрис
@StephenHarris Ну да, если вы установите его в обход ...
leeand00
@ leeand00 - по-видимому, кодирование base64 также работает как обход, но я не знаю, было ли это закрыто в более новых версиях PowerShell.
Стивен Харрис
1
@ leeand00 - см. darkoperator.com/blog/2013/3/5/… для забавы :-) В основном, передайте закодированный в base64 сценарий в качестве параметра в командной строке :-) Достаточно легко обернуть!
Стивен Харрис
2
SeLinux комментирует файлы с их происхождением. Это одно из основных его помещений.
loa_in_
10

Linux не предоставляет возможности ограничивать выполнение сценариев bash на основе цифровых подписей.

Существует некоторая работа по аутентификации бинарных исполняемых файлов. Смотрите https://lwn.net/Articles/488906/ для информации.

Квентин Феннесси
источник
Upvote для прямого ответа, не предлагая хоккейного обходного пути.
user394
8

Одним словом "нет".

Linux на самом деле не делает различий между исполняемыми файлами и скриптами; #!в начале это способ сообщить ядру , что программа для запуска , чтобы оценить вклад , но это не единственный способ , сценарий может быть выполнен.

Так, например, если у меня есть скрипт

$ cat x
#!/bin/sh 
echo hello

Тогда я могу запустить это с командой

$ ./x

Это заставит ядро ​​попытаться выполнить его, определить #!и затем эффективно запустить /bin/sh xвместо него.

Однако я мог бы также запустить любой из этих вариантов:

$ sh ./x
$ bash ./x
$ cat x | sh
$ cat x | bash
$ sh < x

или даже

. ./x

Таким образом, даже если ядро ​​попыталось навязать подпись на execуровне, мы можем обойти это, только запустив интерпретатор со сценарием в качестве параметра.

Это означает, что код подписи должен быть в самом интерпретаторе. И что помешает пользователю скомпилировать собственную копию оболочки без кода принудительного подписания?

Стандартным решением этого является не использование подписи, а использование обязательного контроля доступа (MAC), такого как SELinux. С системами MAC вы можете точно указать, что каждому пользователю разрешено запускать и переходить слои. Так, например, вы можете сказать, что «обычные пользователи могут запускать что угодно, но веб-сервер и процессы CGI могут получать доступ только к материалам из /var/httpdкаталога; все остальное отклоняется».

Стивен Харрис
источник
1
This means that signing code would have to be in the interpreter itself. And what would stop a user from compiling their own copy of a shell without the signing enforcement code?Запрет на выполнение любых неподписанных исполняемых файлов сделает это, если у пользователя нет ключа подписи. Для этого уже существуют различные проекты * nix.
Альзее
2

В дистрибутивах Linux обычно есть gnupg . Мне кажется, что все, что вам нужно, это простая оболочка bash, которая проверяет отдельную подпись gpg на скрипте аргументов и запускает скрипт только в случае успешной проверки:

#!/bin/sh
gpgv2 $1.asc && bash "$@"
PSkocik
источник
Единственное, чего здесь нет, - это запуск сценария, который кто-то только что сделал ... самостоятельно ...
leeand00
2

Встречный вопрос, который сразу приходит на ум: «Почему вы хотите запретить пользователям запускать программы, которые они написали? » Существует несколько возможностей:

  1. В буквальном смысле невозможно определить, кто является автором кода. Владельцем файла сценария является тот, кто действительно сохранил содержимое этого файла, независимо от того, откуда он взялся. Таким образом, принудительное выполнение подписи является сложной заменой диалоговому окну подтверждения: «Вы уверены, что хотите это сделать?» В Linux часть этой проблемы прозрачно решается с помощью подписанных пакетов и смягчается тем, что пользователи имеют ограниченный доступ по умолчанию. Пользователь также должен знать, что запуск чужого кода может быть опасным *.
  2. В том же духе подписание скрипта является гораздо более сложной операцией, чем сохранение файла. В лучшем случае это побуждает пользователя понять, что он выполняет действие, аналогичное подписанию документа, и должен проверить, что он говорит, прежде чем продолжить. Скорее всего, он просто обеспечивает минимальный уровень технических навыков пользователя, позволяющего запускать сценарий. В худшем случае это демонстрирует готовность прыгать через длинный ряд обручей, чтобы выполнить то, что они хотели. Техническое знание предполагается в Linux *.
  3. Более вероятно, что люди будут обнаруживать явно вредоносный код при вводе / вставке серии команд в их командную строку. Фрагменты открытого текста, предназначенные для копирования и вставки, обычно меньше, чем набор команд, необходимых для выполнения чего-то по-настоящему гнусного. Пользователь также может тщательно копировать и вставлять каждую строку отдельно, понимая, что происходит, как это происходит. С помощью сценария возможно, что пользователь вообще никогда не просматривал код. Это может быть полезным приложением подписанных сценариев, при очень распространенной цене самоуспокоения после того, как вы это сделаете в 12-й раз.

* Это, вероятно, становится все менее и менее верным, так как все больше людей начинают использовать Linux

l0b0
источник
1

Причина, по которой системы развиваются по-разному, заключается в том, что в Linux есть атрибут файла «exec», а Windows использует расширения файлов для определения исполняемости.

Таким образом, в Windows легко заставить пользователя загрузить файл с расширением «.exe», «.bat», «.scr», который по умолчанию будет скрыт . Двойной щелчок по этому файлу даст вам выполнение произвольного кода. Следовательно, большой механизм отслеживания происхождения и подписывания исполняемого файла / скрипта был создан для снижения этого риска.

В Linux вы можете получить файл для пользователя, но вы не можете легко заставить бит exec быть установленным. Кроме того, можно сделать целые файловые системы noexec.

В любом случае вы можете явно запустить скрипт, вызвав интерпретатор. Вы даже можете создавать сценарии оболочки во время выполнения и передавать их в «sh» или запускать «sh -c».

pjc50
источник
0

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

Дело в том, что то, что было описано в другом ответе, что отсутствие бита выполнения не мешает вам передавать такой скрипт напрямую bash. Хотя можно утверждать, что большинство таких сценариев являются bashсценариями, shebang может указывать любую программу в качестве интерпретатора. Это означает, что пользователь должен запустить соответствующий интерпретатор, если он решит игнорировать исполняемую семантику.

Хотя это не так много, это в значительной степени охватывает предотвращение запуска ненадежных исполняемых файлов на * nixes только с ядром и оболочкой .

Как я упоминал в одном из комментариев, существует еще один уровень защиты, SeLinuxкоторый отслеживает происхождение файлов на основе набора правил. Например, установка SeLinuxне позволит root запускать исполняемый файл с набором исполняемых битов, который был загружен из Интернета, даже если вы копируете и перемещаете файл. Можно добавить правило, что такие файлы можно запускать только через другой двоичный файл, который будет проверять подпись, в отличие от того, что вы упомянули в своем вопросе.

Итак, в конце концов, это вопрос настройки обычно предустановленных инструментов, и ответ - да .

loa_in_
источник
многие программы архивации не сохраняют бит выполнения для содержащихся файлов ... ну, это своего рода препятствие, когда вы действительно хотите использовать его для архивирования. К счастью tar , сохраняет бит выполнения.
pjc50
Вы должны использовать tar -p источник
loa_in_
-p, --preserve-permissions, --same-permissionsозначает извлекать информацию о правах доступа к файлам (по умолчанию для суперпользователя)
loa_in_
Нет, вам НЕ нужен -p. Я вижу, что говорит страница руководства, но это не то, что происходит. touch permtest; chmod +x permtest; tar cf permtest.tar.gz permtest; rm permtest; tar xf permtest.tar.gz; ls -l permtest- это исполняемый файл здесь, и я не root.
Домен
Я постараюсь улучшить свой ответ тогда.
loa_in_