Позвольте с setuid на скриптах оболочки

В улучшить бит разрешение говорит Linux запускать программу с эффективным идентификатором пользователя владельца вместо исполнителя:

> cat setuid-test.c

#include <stdio.h>
#include <unistd.h>

int main(int argc, char** argv) {
    printf("%d", geteuid());
    return 0;
}

> gcc -o setuid-test setuid-test.c
> ./setuid-test

1000

> sudo chown nobody ./setuid-test; sudo chmod +s ./setuid-test
> ./setuid-test

65534

Однако, это касается только исполняемые файлы; скрипты игнорировать бит setuid:

> cat setuid-test2

#!/bin/bash
id -u

> ./setuid-test2

1000

> sudo chown nobody ./setuid-test2; sudo chmod +s ./setuid-test2
> ./setuid-test2

1000

Википедия говорит:

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

Если предположить, что я'м готов принять эти риски, есть ли способ, чтобы сообщить Linux лечить бит setuid же на скриптах, как это делает на исполняемые файлы?

Если нет, есть ли общее решение для этой проблемы? Мое текущее решение, чтобы добавить запись пользователям использовать sudo? чтобы все, чтобы запустить данный скрипт как пользователь я хочу, чтобы запустить его как, с NOPASSWD, чтобы избежать ввода пароля. Основные минусы в том, что это необходимо для записи, а пользователям использовать sudo?каждый раз, когда я хочу сделать это, а также необходимость для абонентасудо некоторые-сценарийвместо простокакой-сценария`

Linux игнорирует права доступа к файлу¹ бит по всем интерпретировать исполняемые файлы (т. е. исполняемые файлы, начинающиеся с #! линии). На сост.в Unix.часто задаваемые вопросы объясняет проблемы безопасности с setuid для сценариев оболочки. Эти проблемы бывают двух видов: стерильные и раковины, а я пойду в более подробно ниже. Если вы Don'т заботятся о безопасности и хотите разрешить setuid для скриптов под Linux, вы'll необходимо пропатчить ядро. По состоянию на 3.х ядер, я думаю, вы должны добавить вызов [install_exec_creds](http://lxr.linux.no/linux+В3.18/ДФ/ОТВ.в C#L1187) в [load_script](http://lxr.linux.no/linux+В3.18/ДФ/binfmt_script.функции C#л90), перед вызовом `open_exec, но я не'т тестирование.

Дополнительное притон

Есть состязания, присущие слову притон (#!) обычно реализуется:

  1. Ядро открывает исполняемый файл, и считает, что она начинается с #!.
  2. Ядра закрывает и открывает исполняемый вместо переводчика.
  3. Ядро вставляет путь к скрипту в списке аргументов (как и argv1`), и выполняет переводчик. Если установлен бит setuid скрипты разрешены благодаря этому злоумышленник может вызвать произвольный сценарий, создав символическую ссылку на существующую улучшить скрипт, выполнить его, и договорилась о смене ссылке после ядра выполнили Шаг 1 и до переводчика к открытию своего первого аргумента. По этой причине, большинство юниксов игнорировать бит setuid когда они обнаруживают притон. Одним из способов защиты эта реализация будет для ядра, чтобы заблокировать файл сценария до того, как переводчик открыл его (обратите внимание, что это должно предотвратить не только для удаления или перезаписи файла, а также переименование каталогов в пути). Но Unix-системы, как правило, уклоняются от обязательной блокировки и символические ссылки внесет необходимую функцию блокировки особо сложных и инвазивных. Я не'т думаю, что кто-то делает это таким образом. Несколько UNIX-систем (главным образом в OpenBSD, NetBSD и МАК оС х, каждый из которых требует параметр ядра должна быть включена) осуществлять обеспечить дополнительное притон, используя дополнительную функцию: путь в <код> В каталоге/dev/ФД/в<их>П</ЭМ></код> ссылается на файл уже открыт файл дескриптора Н (т. открытие в <код> В каталоге/dev/ФД/в<их>П</ЭМ></код> эквивалентна примерно в <код>ДУП (в<их>П</ЭМ и GT;)</код и GT;). Многие системы Unix (включая Linux) есть устройство/dev/ФД, но не улучшить скрипты.
  4. Ядро открывает исполняемый файл, и считает, что она начинается с #!. Позвольте'ы сказать дескриптор файла для исполняемого файла 3.
  5. Ядро открывает переводчика.
  6. Ядра вставками в/dev/ФД/3 списке аргументов (как и argv1`), и выполняет переводчик. Свен Mascheck'ы подробно страница содержит много информации на притон по юниксов, в том числе [setuid для поддержки](http://www.in-ulm.de/~mascheck/различных/притон/#с setuid).

    Setuid для переводчиков

    Позвольте'ы предполагаем, что вы'ве удалось сделать вашу программу запускать от имени root, либо потому, что ваша ОС поддерживает функцию setuid притон или потому, что вы'вэ используется бинарная оболочка (например, судо). Ты открыл дыру в безопасности? Возможно. Речь здесь идет не о интерпретировано против скомпилированных программ. Вопрос, Является ли ваш системы спокойно ведет себя, если она выполняется с привилегиями.

  • Какие динамически связаны родной двоичный исполняемый файл таким образом интерпретироваться динамический загрузчик (например, /Либ/ЛД.так), который загружает динамических библиотек, необходимых для работы программы. На многих Unix-подобных системах, вы можете настроить путь поиска для динамических библиотек с помощью окружения (переменная LD_LIBRARY_PATH - это общее название для переменной окружения), и даже загружать дополнительные библиотеки В всех запускаемых программах (LD_PRELOAD). Призывателя программы может выполнить произвольный код в программу'ы контекста, поместив специально созданный файл libc.так в $переменная LD_LIBRARY_PATH (среди других тактик). Всех вменяемых системах игнорировать переменные `LD_* в режиме setuid программы.
  • В ракушки, таких как Sh, csh и производных, переменные окружения автоматически становятся параметры оболочки. Через такие параметры как путь, если, и многое другое, у Invoker скрипт имеет много возможностей, чтобы выполнить произвольный код в shell-скрипты'ы контексте. Некоторые снаряды набор этих переменных в значения по умолчанию, если они обнаруживают, что скрипт был вызван с правами, но я не'т знаю, что существует какой-либо конкретной реализации, что я бы доверил.
  • Большинство сред выполнения (то ли родной, то байт-код или интерпретируемый) имеют схожие особенности. Мало принять особые меры предосторожности в setuid для исполняемых файлов, хотя те, которые выполнить машинный код часто не'т сделать что-нибудь более динамическое связывание (которое не принять меры предосторожности).
  • Перл является заметным исключением. Это явно поддерживает функцию setuid скрипты в защищенном режиме. На самом деле, ваш скрипт может запускать setuid даже если ваша ОС игнорируется бит setuid на скриптах. Это происходит потому, что корабли на Perl с установленным битом setuid корень помощником, который выполняет необходимые проверки и reinvokes переводчик на нужные скрипты с нужными привилегиями. Это объясняется в perlsec руководство. Раньше считалось, что setuid для Perl-скриптов нужен #!/УСР/бин/suidperl -мас вместо #!/usr/Бен/Perl с -МАС, но на большинстве современных систем,#!/usr/Бен/на Perl -мас является достаточным. Обратите внимание, что использование бинарная фантик не в себе, чтобы предотвратить эти проблемы. На самом деле, это может сделать ситуацию хуже, потому что это может помешать вашей среды выполнения обнаруживать, что он вызывается с правами и в обход его выполнения конфигурирования. Родной бинарных обертке можете сделать скрипт просмотра, если фантик санирует окружающей среды. Скрипт должен заботиться, чтобы не сделать слишком много допущений (например, о текущем каталоге), но к этому идет. Вы можете использовать sudo для этого при условии, что она's была создана для очистки окружающей среды. Переменные черных списков может привести к ошибкам, поэтому всегда белый. С sudo, убедитесь, что опция env_reset включен, что setenv, и что env_file и `env_keep содержат только безобидные переменных.

    ТЛ ДР:

  • Дополнительное хижина неуверенно, но, как правило, игнорируется.
  • Если запустить программу с правами (либо через sudo или setuid), написать собственный код или Perl, или запустить программу с оболочкой, которая очищает окружающую среду (например, sudo с опцией env_reset). ¹ <суб>это обсуждение относится в равной степени, если заменить “функцию setgid” за “дополнительное”; они оба игнорировали ядра Linux на Скрипты</суб>
Комментарии (15)

Одним из способов решения этой проблемы является вызов скрипта из программы, которые могут использовать setuid-бит. его что-то вроде sudo. Например, вот как вы бы сделать это в программе c:

#include 
#include 
#include 
#include 

int main()
{
    setuid( 0 );   // you can set it at run time also
    system( "/home/pubuntu/setuid-test2.sh" );
    return 0;
 }

Сохраните его как дополнительное-test2 на.С. компиляции Теперь с setuid на этой бинарной программе:

su - nobody   
[enter password]  
chown nobody:nobody a.out  
chmod 4755 a.out  

Теперь, вы должны быть в состоянии запустить его, и вы'll увидеть ваш скрипт выполняется с никто разрешения. Но здесь также нужно закодировать путь к скрипту или сдать его в командной строке аргументов выше exe-файла.

Комментарии (12)

Я префикса несколько скриптов, которые находятся в этой лодке таким образом:

#!/bin/sh
[ "root" != "$USER" ] && exec sudo $0 "$@"

Обратите внимание, что это не использовать улучшить, а просто выполняет текущий файл с судо.

Комментарии (1)

Если вы хотите избежать вызова судо some_script вы можете просто сделать:

  #!/ust/bin/env sh

  sudo /usr/local/scripts/your_script

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

  • Снаряды большой части программ, которые сильно взаимодействуют с пользователем. Это почти невозможно вменяемость проверить все, тем более что большая часть кода не предназначен для работы в таком режиме.
  • Скрипты в основном быстрая'Н'грязный раствор и, как правило, не готовились с такой тщательностью, что они позволили бы улучшить. У них много потенциально опасных объектов.
  • Они сильно зависят от других программ. Это не достаточно, что снаряд был проверен. СЭД, неужели, и т. д. должны быть проверены также

Обратите внимание, что судо предоставляет некоторые вменяемость-проверки, но это вовсе'т достаточно — проверить каждую строку в свой код.

Как последнее примечание: рекомендуется использовать возможности. Они позволяют придать процессу в качестве особой привилегии пользователей, которые обычно требуют привилегий суперпользователя. Однако, например, в то время как "пинг" должен манипулировать сети, для этого не нужно иметь доступ к файлам. Я'м не уверен, однако если они передаются по наследству.

Комментарии (1)

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

Но если вы Don'т ум ужасные угрозы безопасности, использовать setuid для раковины в качестве переводчика для сценария. Дон'т знаете ли, что'll будет работать для вас, но я предполагаю, что это может.

Позвольте мне заявить, что я советую на самом деле делаете это, хотя. Я'м просто упомянуть его в образовательных целях ;-)

Комментарии (2)

супер [ -Р reqpath] команда [ аргументы ]

Супер позволяет определенным пользователям выполнять скрипты (или других команд), как если бы они были корень; или он может определить UID, GID и/или дополнительных групп на командной основе перед выполнением команды. Он предназначен для надежной альтернативой, чтобы сделать скрипты с setuid корень. Супер также позволяет обычным пользователям подачей команд для исполнения другим; они выполняются с UID, GID и групп пользователей, предлагающих команды.

Супер консультирует `супер.вкладка'' файл, чтобы увидеть, если пользователь может выполнить запрашиваемую команду. Если разрешение предоставлено, супер будет старпома ПГМ [ аргументы ], где ПГМ-это программа, которая связана с этой командой. (Корень допускается исполнение по умолчанию, но все равно может быть отказано, если правило исключает корень. Обычные пользователи могут запретить выполнение по умолчанию.)

Если команда является символической ссылкой (или жесткая ссылка, тоже) к программе супер, затем введите команду % аргументы вместо того, чтобы вводить % супер команду параметры (команды не должны быть супер, или супер не признать, что она'ы, вызываемого по ссылке.)

http://www.ucolick.org/ - с/РУП/супер/ридми

http://manpages.ubuntu.com/manpages/utopic/en/man1/super.1.html

Комментарии (2)

Если по каким-то причинам судо недоступна, вы можете писать тонким скрипт-обертку на C:

#include 
int main() {
    setuid(0);
    execle("/bin/bash","bash","/full/path/to/script",(char*) NULL,(char*) NULL);
}

И после компиляции установить его как дополнительное с командой chmod 4511 wrapper_script.

Это похоже на очередную запостил ответ, но запускает скрипт с чистой экологией и явно использует /Бен/Баш вместо раковины называютсистемы (), а так закрывает некоторые потенциальные дыры в безопасности.

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

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

Комментарии (0)

Я сначала нашел этот вопрос, убежден на все ответы, здесь намного лучше, что также позволяет полностью скрыть ваш bash-скрипт, если вы так склонны!

Она должна быть самодостаточной.

#include 
#include 

template 
T &replace (
          T &str, 
    const U &from, 
    const U &to)
{
    size_t pos;
    size_t offset = 0;
    const size_t increment = to.size();

    while ((pos = str.find(from, offset)) != T::npos)
    {
        str.replace(pos, from.size(), to);
        offset = pos + increment;
    }

    return str;
}

int main(int argc, char* argv[])
{
    // Set UUID to root
    setuid(0);

    std::string script = 
R"(#!/bin/bash
whoami
echo $1
)";

    // Escape single quotes.
    replace(script, std::string("'"), std::string("'\"'\"'"));

    std::string command;
    command = command + "bash -c '" + script + "'"; 

    // Append the command line arguments.
    for (int a = 0; a < argc; ++a)
    {
        command = command + " " + argv[a];
    }

    return system(command.c_str());
}

Затем вы бежите

g++ embedded.cpp -o embedded
sudo chown root embedded
sudo chmod u+s embedded
Комментарии (2)