Вы хотите использовать Экран GNU. Это является супер потрясающим!
ssh me@myserver.com
screen #start a screen session
run-a-long-process
CTRL+a, d для отсоединений от экранной сессии
exit #disconnect from the server, while run-a-long-process continues
Когда Вы возвращаетесь к своему ноутбуку:
ssh me@myserver.com
screen -r #resume the screen session
Затем проверьте прогресс своего продолжительного процесса!
screen
очень всесторонний инструмент и может сделать намного больше, чем, что я описал. В то время как на экранной сессии, попробуйте ctrl+a? изучить несколько общих команд. Вероятно, наиболее распространенные:
screen -d -r
гарантировать, что, если другая оболочка присоединена к моей экранной сессии, это будет отсоединено, прежде чем я возобновлю его на своей существующей системе.Linux игнорирует setuid ¹, обдумал все интерпретируемые исполняемые файлы (т.е. исполняемые файлы, запускающиеся с a #!
строка). comp.unix.questions FAQ объясняет проблемы безопасности с setuid сценариями оболочки. Этими проблемами являются два вида: связанный с хижиной и связанный с оболочкой; я вдаюсь в большее количество подробностей ниже.
Если Вы не будете заботиться о безопасности и хотеть позволить setuid сценарии, в соответствии с Linux, то необходимо будет исправить ядро. С 3.x ядра, я думаю, что необходимо добавить вызов к install_exec_creds
в load_script
функция, перед вызовом к open_exec
, но я не протестировал.
Существует состояние состязания, свойственное к пути хижина (#!
) обычно реализуется:
#!
.argv[1]
), и выполняет интерпретатор.Если setuid сценарии позволяются с этой реализацией, взломщик может вызвать произвольный сценарий, создав символьную ссылку на существующий setuid сценарий, выполнив ее и расположив изменить ссылку после того, как ядро выполнило шаг 1 и прежде чем интерпретатор найдет время для открытия его первого аргумента. Поэтому большинство нельдов игнорирует бит setuid, когда они обнаруживают хижину.
Один способ защитить эту реализацию состоял бы в том, чтобы ядро заблокировало файл сценария, пока интерпретатор не открылся, это (обратите внимание, что это должно предотвратить не только удаление связи или перезапись файла, но также и переименование любого каталога в пути). Но системы Unix имеют тенденцию уклоняться от обязательных блокировок, и символьные ссылки сделали бы корректную функцию блокировки особенно трудной и агрессивной. Я не думаю, что любой делает это этот путь.
Несколько систем Unix (главным образом OpenBSD, NetBSD и Mac OS X, все из которых требуют, чтобы установка ядра была включена) реализация защищают setuid хижину, использующую дополнительную функцию: путь /dev/fd/N
относится к файлу, уже открытому на дескрипторе файла N (настолько вводный /dev/fd/N
примерно эквивалентно dup(N)
). Много систем Unix (включая Linux) имеют /dev/fd
но не setuid сценарии.
#!
. Скажем, дескриптор файла для исполняемого файла равняется 3./dev/fd/3
список аргументов (как argv[1]
), и выполняет интерпретатор.Страница хижины Sven Mascheck имеет большую информацию о хижине через нельды, включая поддержку setuid.
Давайте предположим, что Вам удалось сделать Ваш прогон программы как корень, или потому что Ваша ОС поддерживает setuid хижину или потому что Вы использовали собственную двоичную обертку (такой как sudo
). Вы открыли дыру в системе безопасности? Возможно. Проблема здесь не об интерпретируемом по сравнению со скомпилированными программами. Проблема - ведет ли Ваша система во время выполнения себя безопасно, если выполняется с полномочиями.
Любой динамично связанный собственный двоичный исполняемый файл способом интерпретируется динамическим загрузчиком (например. /lib/ld.so
), который загружает динамические библиотеки, требуемые программой. На многих нельдах можно настроить путь поиска для динамических библиотек через среду (LD_LIBRARY_PATH
общее название для переменной среды), и равномерная нагрузка дополнительные библиотеки во все выполняемые двоичные файлы (LD_PRELOAD
). invoker программы может выполнить произвольный код в контексте той программы путем размещения особенно обработанного libc.so
в $LD_LIBRARY_PATH
(среди другой тактики). Все нормальные системы игнорируют LD_*
переменные в setuid исполняемых файлах.
В оболочках, таких как sh, csh и производные, переменные среды автоматически становятся параметрами оболочки. Через параметры такой как PATH
, IFS
, и намного больше, invoker сценария имеет много возможностей выполнить произвольный код в контексте сценариев оболочки. Некоторые оболочки устанавливают эти переменные на нормальные значения по умолчанию, если они обнаруживают, что сценарий был вызван с полномочиями, но я не знаю, что существует какая-то конкретная реализация, которой я доверял бы.
Большинство сред выполнения (ли собственный компонент, байт-код или интерпретируемый) имеет подобные функции. Немногие принимают специальные меры предосторожности в setuid исполняемых файлах, хотя те, что выполненный собственный код часто не делает ничего более необычного, чем динамическое подключение (который действительно принимает меры предосторожности).
Perl является существенным исключением. Это явно поддерживает setuid сценарии безопасным способом. На самом деле Ваш сценарий может выполнить setuid, даже если Ваша ОС проигнорировала setuid, обдумал сценарии. Это вызвано тем, что жемчуг поставлется с корневым помощником setuid, который выполняет необходимые проверки и повторно вызывает интерпретатор на желаемые сценарии с желаемыми полномочиями. Это объяснено в perlsec руководстве. Это раньше было, что для setuid сценариев жемчуга было нужно #!/usr/bin/suidperl -wT
вместо #!/usr/bin/perl -wT
, но в большинстве современных систем, #!/usr/bin/perl -wT
достаточно.
Обратите внимание, что использование собственной двоичной обертки не делает ничего сам по себе для предотвращения этих проблем. На самом деле это может сделать ситуацию хуже, потому что это могло бы препятствовать тому, чтобы Ваша среда выполнения обнаружила, что это вызывается с полномочиями и обходом ее конфигурируемости во время выполнения.
Собственная двоичная обертка может сделать сценарий оболочки безопасным, если обертка санирует среду. Сценарий должен заботиться для не создания слишком многих предположений (например, о текущем каталоге), но это идет. Можно использовать sudo для этого при условии, что он настраивается для очистки среды. Помещение в черный список переменных подвержено ошибкам, поэтому всегда добавляйте в белый список. С sudo удостоверьтесь что env_reset
опция включена, это setenv
выключено, и это env_file
и env_keep
только содержите безвредные переменные.
TL, DR:
env_reset
опция).¹ Это обсуждение применяется одинаково, если Вы заменяете “setgid” “setuid”; они оба проигнорированы ядром Linux на сценариях
Один способ решить эту проблему состоит в том, чтобы назвать сценарий оболочки из программы, которая может использовать бит setuid.
что-то как sudo. Например, вот то, как Вы выполнили бы это в программе C:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
setuid( 0 ); // you can set it at run time also
system( "/home/pubuntu/setuid-test2.sh" );
return 0;
}
Сохраните его как setuid-test2.c.
скомпилировать
Теперь сделайте setuid на этом двоичном файле программы:
su - nobody
[enter password]
chown nobody:nobody a.out
chmod 4755 a.out
Теперь, необходимо смочь выполнить его, и Вы будете видеть, что Ваш сценарий не выполняется ни с кем полномочия.
Но здесь также или Вы нуждаетесь к hardcode в пути сценария или передаете его как аргумент командной строки к вышеупомянутому exe.
PATH
и LD_LIBRARY_PATH
очевидные векторы. Некоторые оболочки выполняются $ENV
или $BASHENV
или ~/.zshenv
даже, прежде чем они начинают выполнять надлежащий сценарий, таким образом, Вы не можете защитить от них вообще из сценария. Единственный безопасный способ вызвать сценарий оболочки с полномочиями состоит в том, чтобы очистить среду. Sudo знает, как сделать это безопасно. Не пишите свою собственную обертку, используйте sudo.
– Gilles 'SO- stop being evil'
08.10.2010, 23:26
LD_LIBRARY_PATH
среди прочего, когда это встречается, setuid укусил.
– user1686
15.02.2012, 17:31
system
, можно найти это более простым (и более эффективный) для использования одного из exec
семейство - скорее всего, execve
. Тем путем Вы не создаете новый процесс или запускаете оболочку, и можно передать аргументы (предполагающий, что привилегированный сценарий может безопасно обработать аргументы).
– Toby Speight
23.07.2015, 21:52
Я снабжаю префиксом несколько сценариев, которые находятся в этой лодке таким образом:
#!/bin/sh
[ "root" != "$USER" ] && exec sudo $0 "$@"
Обратите внимание, что это не использует setuid
но просто выполняет текущий файл с sudo
.
Если Вы не хотите звонить sudo some_script
можно просто сделать:
#!/ust/bin/env sh
sudo /usr/local/scripts/your_script
Программы SETUID должны быть разработаны с большой осторожностью, когда они работают с полномочиями пользователя root, и пользователи имеют большой контроль над ними. Им нужно к проверке работоспособности все. Вы не можете сделать этого со сценариями потому что:
sed
, awk
, и т.д. должен был бы быть проверен такжеОбратите внимание на то, что sudo
обеспечивает некоторую проверку исправности, но это не достаточно — проверяют каждую строку в Ваш собственный код.
Как последнее примечание: рассмотрите использование возможностей. Они позволяют Вам давать процесс, работающий как пользователя специальные полномочия, которые обычно требовали бы полномочий пользователя root. Однако, например, в то время как ping
потребности управлять сетью, это не должно иметь доступа к файлам. Я не уверен однако, если они наследованы.
Можно создать псевдоним для sudo + название сценария. Конечно, это - еще больше работы для установки, так как затем необходимо установить псевдоним также, но она сохраняет Вас от необходимости ввести sudo.
Но если Вы не возражаете против ужасных угроз безопасности, используйте оболочку setuid в качестве интерпретатора для сценария оболочки. Не знайте, будет ли это работать на Вас, но я предполагаю, что это могло бы.
Позвольте мне заявить, что я советую против фактического выполнения этого, все же. Я просто упоминаю это в образовательных целях ;-)
rm -rf /
(и другие команды от серии DO не ДЕЛАЮТ IT ДОМА).
– Maciej Piechotka
17.08.2010, 13:52
Команда Super [-R Reqpath] Super [args]
Super позволяет указывать пользователей выполнять скрипты (или другие команды), как если бы они были root; Или он может установить UID, GID и / или дополнительные группы на основе в соответствии с командой, прежде чем выполнять команду. Предназначен, чтобы быть безопасной альтернативой для создания скриптов SETUID ROOT. Super также позволяет обычным пользователям поставлять команды для выполнения других; Они выполняют с помощью UID, GID и групп пользователей, предлагающих команду.
Super Обратитесь к файлу «Super.tab», чтобы увидеть, разрешено ли пользователю выполнить запрошенную команду. Если предоставляется разрешение, супер будет работать PGM [args], где PGM - это программа, связанная с этой командой. (Root разрешено выполнением по умолчанию, но все еще может быть отказано, если правило исключает корня. Обычные пользователи по умолчанию запрещают выполнение.)
Если команда также является символической ссылкой (или жесткой ссылкой) в супер программу, Затем набрав% command args эквивалентно набрать% Super Command args (команда не должна быть супер, или супер не распознает, что это вызывается по ссылке.)
http://www.ucolick.org/~will /Rue/super/Readme
Http://manpages.ubuntu.com/manpages/utopic/en/man1/super.1.html
Я впервые нашел этот вопрос, меня не убедили все ответы. Вот гораздо лучший вопрос, который также позволяет полностью запутать ваш сценарий bash, если вы так склонны!
Это должно быть самоочевидным.
#include <string>
#include <unistd.h>
template <typename T, typename U>
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
Если по какой-то причине sudo
недоступен, можно написать тонкий скрипт-оболочку на C:
#include <unistd.h>
int main() {
setuid(0);
execle("/bin/bash","bash","/full/path/to/script",(char*) NULL,(char*) NULL);
}
И как только вы скомпилируете его, установите его как setuid
с chmod 4511 wrapper_script
.
Это похоже на другой опубликованный ответ, но сценарий запускается в чистой среде и явно использует /bin/bash
вместо оболочки, вызываемой system()
, и таким образом закрывает некоторые потенциальные дыры в безопасности.
Обратите внимание, что при этом среда полностью отбрасывается. Если вы хотите использовать некоторые переменные среды, не открывая уязвимостей, вам просто нужно использовать sudo
.
Очевидно, вы хотите убедиться, что сам сценарий доступен для записи только пользователю root.
Во-первых, отказ от ответственности :ОП сказал: «Предполагая, что я готов принять на себя эти риски…». Я оказался в похожей ситуации, когда у меня было одно -нерабочее задание, где я не беспокоился о рисках безопасности, потому что это была краткосрочная -ситуация... Прежде чем вы, ненавистники, понизите голосование, это то, что хотел ОП....
Таким образом, все мое решение является расширением того, что Хемант придумал выше . Единственным отличием от его решения является небольшая автоматизация, так что вы можете как жестко -кодировать конкретный исполняемый файл, который хотите запустить, так и с помощью одного -лайнера, что-то вроде комбинации ln
и setuid
(. ] напримерchmod 6755
).
Кто-то скажет, что это излишество для чего-то, что вы «не должны делать в первую очередь» --, но опять же, это то, чего хотел ОП... Около половины кода можно было бы удалить, если вы не заботитесь об отладке. опции; Я хотел возможность включения xtrace
,и некоторые из функций отладки были просто для того, чтобы помочь мне в его разработке...
И повторяю, если это уже было неясно :просто sudo
является лучшим вариантом почти во всех случаях, за исключением явного обмена -между ленью и скоростью... (I согласен с большинством других постов)
Вот код:
cat > makeSetUIDExecutable <<\ENDSCRIPT
#!/bin/bash
usage() { echo "Usage: $0 -c <command> -o <output> [-u <user>] [-v (verbose)] [-x (xtrace)] [-X (xtrace inherit)]" 1>&2; exit 1; }
PrintArray() {
local -n arr=$1
echo -n "$1: "
for elem in "${!arr[@]}"; do
echo -n "[${elem@Q}]=${arr[$elem]@Q}, "
done | sed 's/, $//'; echo
}
PrintVariable() {
echo "$1: ${!1}"
}
unset makeSetUIDExecutableOpts quotedCommand
declare -A makeSetUIDExecutableOpts
OPTIND=1
while getopts ":c:o:u:vxX" makeSetUIDExecutableOpt; do
# echo -e "\nProcessing argument...\nmakeSetUIDExecutableOpt = ${makeSetUIDExecutableOpt}\nOPTARG = ${OPTARG}"
[[ "${makeSetUIDExecutableOpt}" == ":" ]] && usage
makeSetUIDExecutableOpts["${makeSetUIDExecutableOpt}"]="${OPTARG}"
done
[[ -z "${makeSetUIDExecutableOpts[c]}" ]] || [[ -z "${makeSetUIDExecutableOpts[o]}" ]] && usage
[[ "${makeSetUIDExecutableOpts[x]+-}" ]] && {
set -x
trap "set +x" EXIT
}
makeSetUIDExecutableOpts[u]="${makeSetUIDExecutableOpts[u]:-root}"
userID=$(id -u "${makeSetUIDExecutableOpts[u]}")
[[ "${makeSetUIDExecutableOpts[X]+-}" ]] && quotedCommand="set -x; "
quotedCommand+="${makeSetUIDExecutableOpts[c]//\\\"/\\\\\"}"
quotedCommand="\"${quotedCommand//\"/\\\"}\""
[[ "${makeSetUIDExecutableOpts[v]+-}" ]] && {
echo -e "\nSummary -- Arguments provided:\n"
PrintArray makeSetUIDExecutableOpts
echo
PrintVariable quotedCommand
echo
}
cat > "${makeSetUIDExecutableOpts[o]}.c" <<ENDSUBSCRIPT
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
int main()
{
if( setuid( ${userID} ) ) {
printf("setuid failed, errno = %i\n", errno);
}
system( ${quotedCommand} );
return 0;
}
ENDSUBSCRIPT
cc "${makeSetUIDExecutableOpts[o]}.c" -o "${makeSetUIDExecutableOpts[o]}"
sudo chown "${makeSetUIDExecutableOpts[u]}" "${makeSetUIDExecutableOpts[o]}"
sudo chmod 6755 "${makeSetUIDExecutableOpts[o]}"
ENDSCRIPT
Пример использования -довольно большой команды, чтобы доказать тремя -способами, что вся пользовательская информация соответствует -ожидаемому... Ваша команда может состоять из одного слова или десяти строк...:
printUidGidInfo='set -- $(cat /proc/self/status | grep -P -o "(?<=Uid:|Gid:).*$"); unset outputString; i=1; while [ ${i} -le 4 ]; do outputString=${outputString}"\n"$(id -nu ${1}); shift; i=$(( i + 1 )); done; while [ ${i} -le 8 ]; do temp=$(getent group ${1}); outputString=${outputString}"\n"${temp%%:*}; shift; i=$(( i + 1 )); done; printf "\nReal UID: %s\nEffective UID: %s\nSaved set UID: %s\nFilesystem UID: %s\nReal GID: %s\nEffective GID: %s\nSaved set GID: %s\nFilesystem UID: %s\n\n" ${outputString}'
./makeSetUIDExecutable -c 'echo; echo "id -u -n:"; id -u -n; echo; echo stat -c "User: %U, Group: %G" /proc/$$/; stat -c "User: %U, Group: %G" /proc/$$/; echo; echo "/proc/self/status"; '"${printUidGidInfo}" -o proveUserInfo -v
./proveUserInfo
Выход:
id -u -n:
root
stat -c User: %U, Group: %G /proc/10977/
User: root, Group: users
/proc/self/status
Real UID: root
Effective UID: root
Saved set UID: root
Filesystem UID: root
Real GID: users
Effective GID: users
Saved set GID: users
Filesystem UID: users
ПРИМЕЧАНИЕ.:задача, описанная в исходном вопросе, может быть решена безопасным способом с использованием конфигураций sudo
и sudoers
. Этот ответ останется для людей, которые все еще привержены запуску сценариев с setuid, даже после того, как их предупредили о последствиях для безопасности. Описанный метод также заложил основу для написания более надежной обработки среды, подобной той, что была описана в sudo
. Предложения приветствуются в чате .
Приведенный ниже сценарий оболочки создаст собственную оболочку с setuid и встроенным заданным сценарием.
ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ :ВНИМАТЕЛЬНО ПРОЧТИТЕ
Для безопасного использования следующего фрагмента необходимы некоторые допущения.:
PATH
доступных каталогах уже заменены вредоносными версиями. Если вы не можете гарантировать соблюдение вышеуказанных условий или не принимаете риски безопасности, связанные с возможностью запуска доверенных или -недоверенных сценариев с setuid, прекратите чтение. Кроме того, родная оболочка, вероятно, неполна для смягчения некоторых распространенных атак манипулирования средой, поэтому используйте ее на свой страх и риск. Предложения по улучшению кода приветствуются.
Если вы прочитали приведенное выше предупреждение,и вы думаете, что сможете гарантировать вышеуказанные условия, или вы можете обеспечить безопасность вашей системы другими способами, создайте файл create-setuid-wrapper.sh
следующим образом:
#!/usr/bin/env bash
set -e
if [[ `id -u` != 0 ]]; then
echo "Execute this command with super user credentials"
exit 1
fi
if [[ $# -ne 1 || ! -f $1 ]]; then
echo "A file argument is necessary"
exit 1
fi
INPUT=$1
TEMPFOLDER=/tmp/tmpsuidwrapper
TEMPINPUT=$TEMPFOLDER/input.data
TEMPINPUTOBJ=$TEMPFOLDER/input.o
WRAPPERSRC=$TEMPFOLDER/wrapper.c
OUTFILE=$(basename -- "$INPUT")
OUTFILE="${OUTFILE%.*}.bin"
# Create temporary directory and copy the input
mkdir -p $TEMPFOLDER
cp $INPUT $TEMPINPUT
# Write wrapper source
cat > $WRAPPERSRC <<- EOF
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <err.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/wait.h>
extern const char _binary_input_data_start[];
extern void* _binary_input_data_size;
int main (int argc, char *argv[])
{
int rc = setuid(0);
if (rc == -1)
{
perror("setuid failed");
return -1;
}
int fd = memfd_create("script", 0);
if (fd == -1)
{
perror("memfd_create failed");
return -1;
}
size_t size = (size_t)&_binary_input_data_size;
rc = write(fd, _binary_input_data_start, size);
if (rc == -1)
{
perror("write failed");
return -1;
}
// Clean the environment to protect from some common
// environment manipulation attacks
// CHECK-ME: Check if some variables unset is actually needed
// and if more variables should be unset, sanitize
unsetenv("LD_LIBRARY_PATH");
unsetenv("LD_PRELOAD");
unsetenv("BASHENV");
unsetenv("ENV");
setenv("PATH", "${PATH}", 1);
pid_t pid = fork();
if (pid == 0)
{
// Child process, execute the script
{
const char * const argv[] = { "script", NULL };
const char * const envp[] = { NULL };
int rc = fexecve(fd, (char * const *) argv, (char * const *) envp);
if (rc == -1)
{
perror("fexecve failed");
return -1;
}
}
}
if (pid == -1)
{
perror("fork failed");
return -1;
}
// Parent process
wait(NULL);
return 0;
}
EOF
# NOTE: Crappy 'ld' syntax apparenty doesn't allow to
# specify a name for the symbol being created, so it will
# use path as the name. We move the input to temp folder
# to keep the symbol name short
CWD=`pwd`
cd $TEMPFOLDER
# Create a linkable object with the data to be embedded
ld -r -b binary -o input.o input.data
cd $CWD
# Compile the program and set setuid
cc -fPIC -no-pie -o $OUTFILE $WRAPPERSRC $TEMPINPUTOBJ
chmod 4755 $OUTFILE
# Cleanup
rm -fr $TEMPFOLDER
Затем подготовьте, например, test.py
скрипт, подобный следующему:
#!/usr/bin/env python3
import getpass
print(getpass.getuser())
Позвоните create_setuid_wrapper.sh
по указанному выше test.py
. Сценарий создаст исполняемый файл test.bin
. Убедитесь, что ваша система разрешает выполнение произвольных исполняемых файлов с setuid (. Системы с поддержкой SELinux не будут ). Выполнение напечатает root
или имя вашего суперпользователя.
EDIT1:Удалена копия во временный файл исполняемого файла setuid. Теперь встроенный скрипт просто выполняется непосредственно из памяти с помощью fork
и fexecve
.
EDIT2:Попытка очистить среду от некоторых распространенных атак манипулирования средой. Оно может быть неправильным и/или недостаточным.
suidperl
материал был удержан от использования и отмечен для удаления в течение многих лет (но сохраняется неменьше), – jmtd 12.05.2011, 17:32suidperl
был удален с жемчуга 5.11 (5,12 стабильных): perl5110delta:> "suidperl" был удален. Это раньше обеспечивало механизм для эмуляции setuid битов полномочий в системах, которые не поддерживают его правильно. perl5120delta:> "suidperl" больше не является частью Perl. Это раньше обеспечивало механизм для эмуляции setuid битов полномочий в системах, которые не поддерживают его правильно. – Randy Stauner 14.07.2011, 20:40