루트 쉘 중첩을 방지하는 방법은 무엇입니까? (POSIX)

루트 쉘 중첩을 방지하는 방법은 무엇입니까? (POSIX)

다음 Bash 별칭을 생각해 보세요. 금방 생각났지만 더 깊이 파고들 시간이 없었습니다.

alias su='sudo -s'

저는 Bash를 실행하고 있지만 언젠가 공유하기 위해 GitHub에 게시할 수 있으므로 이 솔루션을 이식 가능하게 만들고 싶습니다.

사람들이 겪을 수 있는 문제는 이미 루팅된 상태에서 해당 프로그램(이 별칭)을 실행하는 것입니다.

데모:

$ su
[sudo] password for vlastimil:                
# su
# su
# 
exit
# 
exit
# 
exit
$ 

중첩된 쉘 세션을 방지하는 방법이 있습니까?

중요: 저는 별도의 파일이 아닌 사용자와 루트에 동일한 별칭 파일을 사용합니다. 솔루션은 이식 가능해야 합니다(POSIX).

답변1

suAPI, 의미 체계, 동작이 서로 다른 명령 이므로 sudo -s명령 중 하나를 다른 명령에 별칭으로 지정해서는 안 됩니다.

여기서는 로그인 쉘을 시작하는 명령을 원하는 것처럼 보이지만 root권한이 없는 쉘에서 호출될 때만 가능하므로 다음과 같은 스크립트를 작성하겠습니다.rootsudorootshell

#! /bin/sh -

die() {
  printf >&2 '%s\n' "$@"
  exit 1
}

[ "$#" -eq 0 ] || die "Usage: $0

Starts a root shell, no argument accepted."

[ "$(id -u)" -eq 0 ] && die "You're already superuser!"

exec sudo -s

시스템 구성의 기본 대상 사용자 가 아닌 경우 명령(또는 시스템의 uid 0 사용자 이름) -u root에 추가합니다 .sudosudo

또는 스크립트를 생성하지 않으려면 rootshell() (<that-code>)코드를 쉘 rc 파일에 추가하여 코드를 래핑하여 쉘 함수로 만듭니다( $0모든 쉘이 함수 이름을 에 입력하는 것은 아니므로 함수 이름으로 변경 $0).

답변2

간단한 솔루션, 쉘 별칭

alias su='[ $(id -u) -ne 0 ] && sudo -s || echo Already root...'

  • POSIX 호환, 즉 복사하여 붙여넣거나 dash다른 쉘 지원 별칭을 거의 추측하면 동일한 동작이 발생해야 함을 의미합니다.

  • 이것이 바로 EUID제가 직접적인 가치 비교를 완전히 피하는 이유입니다.


데모:

$ su
[sudo] password for vlastimil:                
# su
Already root...
# su
Already root...
# 
exit
$ 

을 사용하는 것을 고려하여 sudo -s첨부합니다.sudo -s다른 변형과의 비교.


고급 솔루션, 쉘 스크립트(POSIX)

나는 위의 의사 솔루션(별명)을 오랫동안(수년) 사용해 왔기 때문에 그 단점도 알고 있습니다. 그렇기 때문에 방금 코드 검토에 스크립트를 게시했습니다.스티븐 차제라스, 이것질문그리고 각각의답변거기에서 찾을 수 있습니다. 지금부터 사용할 스크립트를 여기에 배치했습니다.

#!/bin/sh

set -o nounset -o errexit

error()
{
    printf >&2 '%s\n' "$@"
    exit 1
}

is_root()
{
    [ "$(id -u)" -eq 0 ]
}

start_root_shell()
{
    exec sudo -s
}

if [ "$#" -gt 0 ]
then
    error "Usage of $(basename "$0") script:" \
    '' \
    'Starts a root shell, no argument accepted.'
fi

if is_root
then
    error 'You are already superuser!'
fi

start_root_shell

감사해요스티븐 차제라스나에게 올바른 방향을 알려줬어요!

답변3

이 답변은 파일 편집에 의존하는 두 부분으로 나뉩니다 sudoers. (귀하의 예제에는 POSIX가 없거나 사용되지 sudo않았기 때문에 POSIX 준수와 관련하여 이 질문에 어떻게 대답해야 할지 잘 모르겠습니다 bash. 그러나 솔루션은 이러한 도구를 사용하는 시스템 간에 이식 가능해야 합니다.)

  1. 파일에 부울 변수를 설정하면 사용법을 단순화 sudo하고 별칭 사용을 피할 수 있습니다. 이제 를 사용하여 루트 셸에 액세스할 수 있습니다.shell_noargs/etc/sudoerssudosudo -s

  2. 예를 들어 일부 셸에서는 bash변수(예:)를 통해 셸 수준을 추적할 수 있습니다 $SHLVL. 이는 sudo전화를 걸거나 간단히 입력하여 추적 할 수 있습니다 bash. 이것을 쉘 프롬프트에 추가하면 현재 가지고 있는 중첩 수준을 결정하는 데 도움이 됩니다.

sudoers시스템 제공 파일을 편집하는 대신 자체 파일을 만듭니다 .

sudo EDITOR=nano visudo -f /etc/sudoers.d/local

이 줄을 파일에 추가하고 저장하십시오.

# Allow sudo with no args to create a shell
Defaults        shell_noargs

# Allow bash to share its nesting level
Defaults        env_check+="SHLVL"

의 경우 bash귀하 ~/.bashrc(아마도 ~/.bash_profile또는 ~/.profile)로 이동하여 정의된 행을 찾으세요 PS1. 를 포함하도록 수정하세요 $SHLVL. 예를 들어 내 Debian 시스템에서는 다음과 같이 설정되어 있습니다.

PS1='${debian_chroot:+($debian_chroot)}\u@\h:\W\$ '

다음과 같은 내용을 포함하도록 수정하겠습니다 $SHLVL.

PS1='${debian_chroot:+($debian_chroot)}\u@\h[$SHLVL]:\W\$ '

마지막으로 루트 구성 파일 편집을 반복합니다.

사용 중인 쉘이 bash이 기능을 제공하지 않는 경우 $SHLVL구현하는 것이 쉽지 않습니다 .만약에쉘은 시작될 때마다 구성 파일을 실행합니다. ( sh불행히도 POSIX는 그렇지 않습니다.)

관련 정보