Почему мы не можем выполнить список команд как другой пользователь без sudo?

Acronis True Image является возможным решением.

Но Если Вы хотите, можно также использовать командную строку:

На стороне получателя: netcat ...>yourdisk.dat.gz

На стороне отправителя: dd if=/dev/sda bs=1M|gzip -|netcat ...

8
15.08.2013, 10:27
4 ответа

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

bash не имеет условия для изменения пользователей, но zsh делает.

В zsh, Вы изменяете пользователей путем присвоения значений тем переменным:

  • $EUID: измените эффективный идентификатор пользователя (и ничто иное). Обычно, можно изменить euid между реальным идентификатором пользователя и сохраненным идентификатором пользователя аппарата (если названо от setuid исполняемого файла) или изменяться на что-либо, если euid 0.
  • $UID: измените эффективный идентификатор пользователя, идентификатор реального пользователя и сохраненный идентификатор пользователя аппарата к новому значению. Если то новое значение не 0, нет никакого возвращения, как, после того как все 3 были установлены на то же значение, нет никакого способа изменить его на что-либо еще.
  • $EGID и $GID: то же самое, но для идентификаторов группы.
  • $USERNAME. Это похоже на использование sudo или su. Это устанавливает Ваш euid, ruid, ssuid к uid того пользователя. Это также устанавливает egid, rgid и ssgid и дополнительные группы на основе составов группы, как определено в пользовательской базе данных. Как для $UID, если Вы не устанавливаете $USERNAME кому: root, нет никакого возвращения, но как для $UID, можно изменить пользователя только для подоболочки.

Если Вы запускаете эти скрипты как "корень":

#! /bin/zsh -
UID=0 # make sure all our uids are 0

id -u # run a command as root

EUID=1000

id -u # run a command as uid 1000 (but the real user id is still 0
      # so that command would be able to change its euid to that.
      # As for the gids, we only have those we had initially, so 
      # if started as "sudo the-script", only the groups root is a
      # member of.

EUID=0 # we're allowed to do that because our ruid is 0. We need to do
       # that because as a non-priviledged user, we can't set our euid
       # to anything else.

EUID=1001 # now we can change our euid since we're superuser again.

id -u # same as above

Теперь, для изменения пользователя как в sudo или su, мы можем только сделать это при помощи подоболочек, иначе мы могли только сделать это однажды:

#! /bin/zsh -

id -u # run as root

(
  USERNAME=rag
  # that's a subshell running as "rag"

  id # see all relevant group memberships are applied
)
# now back to the parent shell process running as root

(
  USERNAME=stephane
  # another subshell this time running as "stephane"

  id
)
4
27.01.2020, 20:10

Предложения ядра man 2 setuid и друзья.

Теперь, это работает над обработкой вызовов. Что еще более важно, Вы не можете поднять свои полномочия. Вот почему su и sudo имейте набор битов SETUID, таким образом, они всегда работают с самыми высокими полномочиями (root) и опуститесь до требуемого пользователя соответственно.

Та комбинация означает, что Вы не можете изменить оболочку UID путем запущения некоторой другой программы, чтобы сделать это (вот почему, Вы не можете ожидать sudo или любая другая программа, чтобы сделать это) и Вы не можете (как оболочка), делают это сами, если Вы не готовы работать как корень или тот же пользователь, Вы желаете переключиться, к которому не имеет смысла. Кроме того, после того как Вы отбрасываете полномочия, назад нет никакого пути.

8
27.01.2020, 20:10

"sudo-u врезаются, sh" команда может использоваться для изменения на пользователя "поршня" путем выполнения команды оболочки или "sh". Команда "выхода" вернет Вас исходному пользователю.

-2
27.01.2020, 20:10

Ну, Вы могли всегда делать:

#! /bin/bash -
{ shopt -s expand_aliases;SWITCH_TO_USER(){ { _u=$*;_x="$(declare;alias
shopt -p;set +o);"'set -- "${_a[@]}";unset _x _a';set +x;} 2>/dev/null
exec sudo -u "$1" env "_x=$_x" bash -c 'eval "$_x" 2> /dev/null;. "$0"
' "$0";};alias skip=":||:<<'SWITCH_TO_USER $_u'"
alias SWITCH_TO_USER="{ eval '"'_a=("$@")'"';} 2>/dev/null;SWITCH_TO_USER"
${_u+:} alias skip=:;} 2>/dev/null
skip

echo test
a=foo
set a b

SWITCH_TO_USER root

echo "$a and $1 as $(id -un)"
set -x
foo() { echo "bar as $(id -un)"; }

SWITCH_TO_USER rag

foo
set +x

SWITCH_TO_USER root again

echo "hi again from $(id -un)"

(ʘ‿ʘ)

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

Как Miroslav сказал, если бы мы не принимаем во внимание возможности стиля Linux (который действительно не помог бы здесь ни одному так или иначе), единственный путь к непривилегированному процессу для изменения uid путем выполнения setuid исполняемого файла.

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

Например:

$ sudo cp /usr/bin/env .
$ sudo chmod 4755 ./env

Теперь я имею env команда, которая позволяет мне выполнять любую команду с эффективным идентификатором пользователя и сохраненным идентификатором пользователя аппарата 0 (мой идентификатор реального пользователя, все еще являющийся 1000):

$ ./env id -u
0
$ ./env id -ru
1000
$ ./env -u PATH =perl -e '$>=1; system("id -u"); $>=0;$>=2; system("id -u");
   $>=0; $>=$<=3; system("id -ru; id -u"); $>=0;$<=$>=4; system("id -ru; id -u")'
1
2
3
3
4
4

perl имеет обертки к setuid/seteuid (они $> и $< переменные).

Делает zsh:

$ sudo zsh -c 'EUID=1; id -u; EUID=0; EUID=2; id -u'
1
2

Хотя выше тех id команды называют с идентификатором реального пользователя и сохранили идентификатор пользователя набора 0 (хотя, если я использовал мой ./env вместо sudo это только было бы сохраненным идентификатором пользователя набора, в то время как идентификатор реального пользователя останется 1000), что означает, что, если бы они были недоверяемыми командами, они могли бы все еще нанести некоторый ущерб, таким образом, Вы хотели бы записать это вместо этого как:

$ sudo zsh -c 'UID=1 id -u; UID=2 id -u'

(который установлен весь uids (эффективный, реальный, и сохранил набор), только для выполнения тех команд.

bash не имеет никакого подобного способа изменить идентификаторы пользователей. Таким образом, даже если у Вас был setuid исполняемый файл, с которым можно назвать Ваш bash сценарий, который не помог бы.

С bash, Вас оставляют с выполнением setuid исполняемого файла каждый раз, когда Вы хотите изменить uid.

Идея в сценарии выше на вызов к SWITCH_TO_USER, для выполнения нового экземпляра удара для выполнения оставления от сценария.

SWITCH_TO_USER someuser более или менее функция, которая выполняет сценарий снова как другого пользователя (использование sudo) но пропущение запуска сценария до SWITCH_TO_USER someuser.

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

Давайте сломаем его:

{ shopt -s expand_aliases;

Нам будут нужны псевдонимы. Один из приемов в этом сценарии должен пропустить часть сценария до SWITCH_TO_USER someuser, с чем-то как:

:||: << 'SWITCH_TO_USER someuser'
part to skip
SWITCH_TO_USER

Та форма подобна #if 0 используемый в C, который является путем к completly, комментируют некоторый код.

: не, который возвращает true. Таким образом в : || :, второе : никогда не выполняется. Однако это анализируется. И << 'xxx' форма здесь-документа где (потому что xxx заключается в кавычки), никакое расширение или интерпретация не сделаны.

Мы, возможно, сделали:

: << 'SWITCH_TO_USER someuser'
part to skip
SWITCH_TO_USER

Но это означало бы, что здесь-документ должен был быть записан и передан как stdin :. :||: избегает этого.

Теперь, где это добирается, hacky - то, что мы используем факт это bash разворачивает псевдонимы очень рано в его процессе парсинга. Иметь skip будучи псевдонимом к :||: << 'SWITCH_TO_USER someuther' часть конструкции комментария.

Давайте продолжим:

SWITCH_TO_USER(){ { _u=$*;_x="$(declare;alias
shopt -p;set +o);"'set -- "${_a[@]}";unset _x _a';set +x;} 2>/dev/null
exec sudo -u "$1" env "_x=$_x" bash -c 'eval "$_x" 2> /dev/null;. "$0"
' "$0";}

Вот определение функции SWITCH_TO_USER. Мы будем видеть ниже того SWITCH_TO_USER, в конечном счете будет псевдоним, перенес ту функцию.

Та функция делает объем перевыполнения сценария. В конце мы видим, что он повторно выполняется (в том же процессе из-за exec) bash с _x переменная в он - среда (мы используем env здесь, потому что sudo обычно санирует его среду и не позволяет передавать произвольный огибающий Вар через). Это bash оценивает содержание этого $_x переменная как код удара и источники сам сценарий.

_x определяется ранее как:

_x="$(declare;alias;shopt -p;set +o);"'set -- "${_a[@]}";unset _x _a'

Весь из declare, alias, shopt -p set +o вывод составляет дамп внутреннего состояния оболочки. Таким образом, они выводят определение всех переменных, функций, псевдонимов и опций как код оболочки, готовый быть оцененным. Вдобавок ко всему, мы добавляем установку позиционных параметров ($1, $2...) на основе значения $_a массив (см. ниже), и некоторая уборка так, чтобы огромное $_x переменная не остается в environemnt для оставления от сценария.

Вы заметите что первая часть до set +x перенесен в оперативную группу штаба, stderr которой перенаправляется к /dev/null ({...} 2> /dev/null). Поэтому, если в какой-то момент в сценарии set -x (или set -o xtrace) выполняется, мы не хотим, чтобы та преамбула генерировала трассировки, как мы хотим сделать ее как можно меньше навязчивой. Таким образом, мы выполняем a set +x (после того, как удостоверился, что вывел опцию (включая xtrace) настройки заранее), куда трассировки отправляются в/dev/null.

eval "$_X" stderr также перенаправляется к/dev/null по подобным причинам, но также и избегать ошибок о записи попытки к специальным переменным только для чтения.

Давайте продолжим со сценарием:

alias skip=":||:<<'SWITCH_TO_USER $_u'"

Это - наш прием, описанный выше. На начальном вызове сценария это будет отменено (см. ниже).

alias SWITCH_TO_USER="{ eval '"'_a=("$@")'"';} 2>/dev/null;SWITCH_TO_USER"

Теперь обертка псевдонима вокруг SWITCH_TO_USER. Главная причина состоит в том, чтобы смочь передать позиционные параметры ($1, $2...) к новому bash это интерпретирует остальную часть сценария. Мы не могли выполнить в нем SWITCH_TO_USER функционируйте потому что в функции, "$@" аргументы функциям, не те из сценариев. stderr перенаправление к/dev/null должно снова скрыть xtraces, и eval должен работать вокруг ошибки в bash. Затем мы звоним SWITCH_TO_USER функция.

${_u+:} alias skip=:

Та часть отменяет skip псевдоним (заменяет его : никакая-op команда), если $_u переменная установлена.

skip

Это - наш skip псевдоним. На первом вызове это просто будет : (не). На перевызовах подпоследовательности это будет что-то как: :||: << 'SWITCH_TO_USER root'.

echo test
a=foo
set a b

SWITCH_TO_USER root

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

То, что это означает, - то, что это должно быть записано точно как статистика, с SWITCH_TO_USER в начале строки и точно с одним пространством между аргументами.

Большая часть состояния, stdin, stdout и stderr будут сохранены, но не другие дескрипторы файлов потому что sudo обычно закрывает их, если explicitely не настроил не к. Так, например:

exec 3> some-file
SWITCH_TO_USER bob
echo test >&3

не будет обычно работать.

Также обратите внимание на это, если Вы делаете:

SWITCH_TO_USER alice
SWITCH_TO_USER bob
SWITCH_TO_USER root

Тот единственные работы, если Вы имеете право на sudo как alice и alice имеет право на sudo как bob, и bob как root.

Так, на практике это не действительно полезно. Используя su вместо sudo (или a sudo конфигурация, где sudo проходит проверку подлинности целевой пользователь вместо вызывающей стороны) мог бы иметь немного больше смысла, но это будет все еще означать, что необходимо было бы знать пароли всех тех парней.

6
27.01.2020, 20:10
  • 1
    можно ли объяснить, что делает сценарий? –  rag 16.08.2013, 10:26
  • 2
    @rag, Вы попросили его... –  Stéphane Chazelas 17.08.2013, 01:38
  • 3
    Та Ваша запись для ioshcc? Необходимо было войти во всего одну строку tho. –  ott-- 17.08.2013, 23:52

Теги

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