호출자의 쉘이 sudo에서 사용되는 것을 방지하는 방법

호출자의 쉘이 sudo에서 사용되는 것을 방지하는 방법

CentOS 6.5에서 sudo-1.8.6을 실행하고 있습니다. 내 질문은 간단합니다. SHELL이 사용자 환경에서 sudo 환경으로 전파되는 것을 방지하는 방법은 무엇입니까?

종종 사람들은 다른 방향으로 갑니다. 그들은 환경 변수를 보존하기를 원합니다. 그러나 사용자 "zabbix"의 셸이 /sbin/nologinsudo를 통해 명령을 실행하려고 할 때 문제가 발생했습니다. Sudo는 /sbin/nologin루트가 하위 쉘을 실행할 수 없도록 유지됩니다 .(업데이트: 이 부분은 맞지만 SHELL 환경 변수가 아닙니다. 문제는 /etc/passwd에서 추출한 쉘 값입니다.)

문제를 설명하는 테스트를 포함했습니다. 실제 사용 사례는 아니지만 호출하는 사용자의 SHELL이 보존된다는 점만 보여줍니다. 사용자로 실행되는 프로그램이 있습니다 zabbix. 호출합니다(프로그래밍 방식으로 daemon 으로 실행되므로 /usr/bin/sudo -u root /tmp/doit비밀번호 파일의 쉘이 이를 차단하지 않습니다). 다음만 포함하는 쉘 스크립트입니다.zabbix/sbin/nologin/tmp/doit

#!/bin/sh
env > /tmp/outfile

(분명히 모드는 755입니다.) outfile내가 볼 수 있는 한 그것은 SHELL이다 /sbin/nologin. 하지만 이 시점에서는 스크립트가 sudo를 통해 루트로 실행 중이므로 이전 사용자의 환경 변수가 없어야겠죠?

이것은 내 /etc/sudoers입니다:

기본값은 필수입니다.
기본값 !visiblepw

기본값은 Always_set_home
기본값 env_reset
기본값 env_keep = "컬러 표시 호스트 이름 HISTSIZE INPUTRC KDEDIR LS_COLORS"
기본값 env_keep += "MAIL PS1 PS2 QTDIR 사용자 이름 LANG LC_ADDRESS LC_CTYPE"
기본값 env_keep += "LC_COLLATE LC_IDENTIFICATION LC_MEASURMENT LC_MESSAGES"
기본값 env_keep += "LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE"
기본값 env_keep += "LC_TIME LC_ALL LANGUAGE LINGUAS _XKB_CHARSET XAUTHORITY"
기본 secure_path = /sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:/usr/local/sbin

## 루트가 어디서나 명령을 실행할 수 있도록 허용
루트올=(모두)모두

#includedir /etc/sudoers.d

이 내 꺼야 /etc/sudoers.d/zabbix:

기본값: zabbix !requiretty

zabbix ALL=(루트) NOPASSWD: /tmp/doit

편집: 추가 정보:

sudo를 실행하는 프로세스는 zabbix_agentdZabbix 모니터링 소프트웨어에서 가져온 것입니다. 파일에 다음 /etc/zabbix/zabbix_agentd.d/userparameter_disk.conf과 같은 항목이 있습니다.

UserParameter=example.disk.discovery,/usr/local/bin/zabbix_raid_discovery

/usr/local/bin/zabbix_raid_discovery파이썬 스크립트입니다. 간단히 이렇게 하도록 수정했습니다.

print subprocess.check_output(['/usr/bin/sudo', '-u', 'root', '/tmp/doit'])

/tmp/doit이렇게 하세요:

#!/bin/sh
환경 >> /tmp/outfile

Zabbix 서버에서 다음 명령을 실행하여 스크립트를 실행합니다 /usr/local/bin/zabbix_raid_discovery.

zabbix_get -s 클라이언트_호스트 이름 -k 'example.disk.discovery'

그런 다음 확인하면 /tmp/outfile다음과 같습니다.

SHELL=/sbin/nologin
용어=리눅스
사용자=루트
SUDO_USER=자빅스
Sudo_UID=497
사용자 이름=루트
경로=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:/usr/local/sbin
메일=/var/mail/root
비밀번호=/
LANG=en_US.UTF-8
SLVL=1
SUDO_COMMAND=/tmp/doit
홈페이지=/루트 디렉토리
로그 이름=루트
SUDO_GID=497
_=/빈/환경

SHELL대사가 정말 거슬리네요. 파일은 루트가 소유하므로 루트가 생성한 것으로 알고 있지만 쉘은 호출하는 사용자( zabbix)로부터 온 것입니다.

답변1

대답은 sudo버그가 있다는 것입니다. 첫째, 해결책: 나는 이것을 내 안에 넣었습니다 /etc/sudoers.d/zabbix file.

zabbix ALL=(루트) NOPASSWD: /bin/env SHELL=/bin/sh /usr/local/bin/zabbix_raid_discovery

이제 zabbix_raid_discovery작업 내에서 하위 명령을 호출하십시오.

이 문제를 해결하기 위한 패치는 sudo 1.8.15에서 출시될 예정입니다. 관리자 Todd Miller의 말:

그것은 단지 "항상 이런 식이었습니다." 아니요
이것은 참으로 타당한 이유입니다. 다음과 같은 차이로 인해 동작이 이루어져야 합니다.
문서와 일치합니다.

 - 토드

diff -r adb927ad5e86 플러그인/sudoers/env.c
--- a/plugins/sudoers/env.c 2015년 10월 6일 화요일 -0600
+++ b/plugins/sudoers/env.c 2015년 10월 6일 화요일 10:04:03 -0600
@@ -939,8 +939,6 @@
            CHECK_SETENV2("사용자 이름", runas_pw->pw_name,
                ISSET(didvar, DID_USERNAME), true);
        } 다른 {
- if (!ISSET(didvar, DID_SHELL))
- CHECK_SETENV2("SHELL", sudo_user.pw->pw_shell, false, true);
            /* def_set_logname의 경우 나중에 LOGNAME을 설정합니다. */
            if (!def_set_logname) {
                if (!ISSET(didvar, DID_LOGNAME))
@@ -984,6 +982,8 @@
            if (!env_should_delete(*ep)) {
                if (strncmp(*ep, "SUDO_PS1=", 9) == 0)
                    ps1 = *ep + 5;
+ else if (strncmp(*ep, "SHELL=", 6) == 0)
+ SET(didvar, DID_SHELL);
                그렇지 않은 경우 (strncmp(*ep, "PATH=", 5) == 0)
                    SET(didvar, DID_PATH);
                그렇지 않은 경우 (strncmp(*ep, "TERM=", 5) == 0)
@@ -1039,7 +1039,9 @@
     if (홈페이지 재설정)
        CHECK_SETENV2("홈", runas_pw->pw_dir, true, true);

- /* $TERM 및 $PATH가 설정되지 않은 경우 기본값을 제공합니다. */
+ /* 설정되지 않은 경우 $SHELL, $TERM 및 $PATH에 대한 기본값을 제공합니다. */
+ if (!ISSET(didvar, DID_SHELL))
+ CHECK_SETENV2("SHELL", runas_pw->pw_shell, false, false);
     if (!ISSET(didvar, DID_TERM))
        CHECK_PUTENV("TERM=알 수 없음", false, false);
     if (!ISSET(didvar, DID_PATH))

답변2

문제는 내가 문제라고 생각한 것이었지만 문제는 SHELL 변수에 발생한 것이 아니라 sudo가 실제로 무엇을 했는지에 있는 것으로 나타났습니다. 예를 들어:

-bash-4.1$ whoami
테스트 친구
-bash-4.1$ grep testdude /etc/passwd
testdude:x:1001:10:테스트 친구:/tmp:/bin/bash
-bash-4.1$ sudo 환경
[sudo] testdude의 비밀번호:
...
쉘=/bin/bash
...

여태까지는 그런대로 잘됐다. ...하지만 문제는 문서와 달리 sudo가 호출 수신자가 아닌 호출자의 셸을 사용한다는 것입니다. 실제로 /etc/passwd를 편집하여 셸을 변경하면 sudo가 대신 호출자의 셸을 따르는 것을 볼 수 있습니다 SHELL.

-bash-4.1$ grep root /etc/passwd
루트:x:0:0:루트:/루트:/bin/bash
-bash-4.1$ sudo sed -i -e '/testdude/s/bash/sh/' /etc/passwd
-bash-4.1$ grep testdude /etc/passwd
testdude:x:1001:10:테스트 친구:/tmp:/bin/sh
-bash-4.1$ sudo 환경
...
쉘=/bin/sh
...
-bash-4.1$ 내보내기 SHELL=/완전/의미 없음/경로
-bash-4.1$ sudo 환경
...
쉘=/bin/sh
...

sudo -i초기 로그인을 시뮬레이션하고 싶지 않기 때문에 사용할 수 없습니다 . sudo -ssudoers 파일에 올바른 명령이 있으면 작동합니다. 그러나 예상되는 동작(맨 페이지: " The new environment contains the TERM, PATH, HOME, MAIL, SHELL, LOGNAME, USER, USERNAME and SUDO_* variables"에 반영된 대로)은 쉘이 호출 수신자의 것입니다. sudo env의 PATH, HOME, LOGNAME변수 를 보면 USERroot의 내용을 볼 수 있습니다. SHELL또한 루트 쉘이어야 합니다.

관련 정보