셸/Bash 스크립트: 권한을 올바르게 제거

셸/Bash 스크립트: 권한을 올바르게 제거

글쎄요, 우선 이 질문을 여러 번 받았지만 주어진 답변이 완전히 만족스럽지는 않다는 것을 압니다. 상황은 다음과 같습니다. 저는 완전히 자동화되고 일단 시작되면 상호 작용이 필요하지 않다는 목표를 가지고 다양한 유지 관리 작업을 자동화하기 위해 많은 스크립트를 작성합니다. 이제 다양한 작업(예: 물건 설치 등)에 루트 권한이 필요한 경우가 많지만, 명령이나 전체 블록(예: wget 또는 네트워크에서 가져온 아카이브 추출 등)을 실행하는 것을 좋아하지 않는 경우가 많습니다. 이벤트에서 최악의 피해를 제한하는 슈퍼유저 권한. 분명히 내 목표를 달성하려면 또는 명령을 기반으로 권한을 제거하고 다시 획득하여 sudo스크립트를 호출해야 합니다 .su

이제 몇 가지 옵션을 고려했지만 완전히 만족스럽지 않으므로 여기 전문가와 상담하여 어느 것이 가장 좋은 솔루션인지 알아보고 싶습니다(다른 사람들도 코드를 이해하기 쉽고 논리적으로 구조화하려는 목적으로). 게시됨):

1.) 루트가 아닌 사용자로 실행될 비트를 외부 파일로 분리하고 를 사용하여 기본 스크립트에서 해당 파일을 실행합니다 su <user> -c /path/to/file. 그러나 이 접근 방식에는 몇 가지 단점이 있습니다. 첫째, 스크립트의 논리적 구조가 깨지고, 이해하고 읽기가 더 어려워지며, 변수를 정의하고 사용할 때 문제가 발생합니다.

2.) 단축할 별칭이나 함수를 정의합니다 su <user> -c "command". 스크립트의 80%가 이 권한 접두어를 갖고 있으므로 이는 매우 나쁜 생각입니다. 그 외에도 여러 줄 명령은 문제가 있습니다(루트로 실행하고 싶지 않은 명령이 포함된 구조와 같은 경우).

su <user> << EOF << ... EOF3.) 전체 코드 블록을 올바르게 처리하려면 이와 같은 것이 필요합니다 . 이것은 나를 괴롭히는 한 가지 문제인 구문 강조가 없는 가장 우아한 솔루션(스크립트의 논리적 구조가 파괴되지 않기 때문에)이 될 것입니다. 내가 시도한 모든 주요 편집자들은 여기 문서 내의 전체 블록에 대해 하나의 색상을 사용합니다. 구문 강조 없이 스크립트의 80%를 읽는 것은 좋지 않습니다.

이것을 처리하는 정말 우아한 방법이 있지 않습니까? 따옴표 없이 그런 것은 su <user> -c ( ...)멋질 것입니다. 아니면 다른 쉘로 전환해야 합니까? (이제 bash를 사용하니 zsh에 EUID 변수 또는 이와 유사한 설정을 허용하는 기능이 있다고 들었습니다.) 우아한 솔루션이 없다면 어떤 접근 방식이 더 좋습니까?

답변1

with zsh, as로 실행하고 root설정한 경우

EUID=1000

euid는 1000으로 설정됩니다. 실제 uid는 여전히 0으로 설정되므로 EUID 0으로 돌아갈 수 있습니다. 실행하는 모든 프로그램은 를 실행하여 권한을 다시 얻을 수도 있지만, setuid()맬웨어로부터 보호하기보다는 부주의한 손상을 방지하는 것이 목표라면 이것으로 충분할 수 있습니다.

#! /bin/zsh -
GID=1000 # optional
EUID=1000 # drop *effective* privileges

some-potentially-harmful-command-that-doesnt-need-superuser

and-another

EUID=0 some-command-that-needs-superuser

more-non-privileged-commands

EUID=0 UID=1000 # now drop privileges with no coming back 
# alternatively:
# USERNAME=stephane # sets uid, gid, supplementary groups... based on the user db

명령 기간 동안 EUID/UID를 설정할 수 있습니다.

UID=1000 the-command

하지만 그렇지 않거나 UID내장 또는 기능인 경우 USERNAME에는 다른 프로세스가 포크되지 않으므로 실제 사용자 ID를 복구할 수 없습니다.the-commandzsh

// 서브셸에 설정할 수도 있습니다 EUID.UIDUSERNAME

(EUID=0 USERNAME=stephane; untrusted-application)

(나중에 사용자를 전환할 수 있도록 EUID를 0으로 설정했습니다.)

답변2

한 가지 해결책은메타프로그래밍: 권한이 없는 다양한 코드 조각을 별도의 파일로 생성하고 전처리기를 사용하여 최종 파일을 생성합니다. 이런 방식으로 프로그램은 이를 개별 비트 또는 전체로 쉽게 읽을 수 있습니다. 프로세스 간 통신은 파일을 사용하여 수행되어야 하는데 이는 약간 번거롭지만 권한 있는 정보가 권한 없는 파일에 누출될 가능성이 훨씬 적습니다(모든 정보를 명시적으로 "누출"해야 하기 때문에).

privileged.sh:

echo "Privileged user: $(whoami)"
su - somebody <<'EOF'
%unprivileged.sh%
EOF

unprivileged.sh:

echo "Unprivileged user: $(whoami)"

preprocessor.sh:

while IFS= read -r line
do
    if [[ $line =~ ^%([^%]*)%$ ]]
    then
        cat "${BASH_REMATCH[1]}"
    else
        printf '%s\n' "$line"
    fi
done < privileged.sh > program.sh

테스트 실행:

$ bash preprocessor.sh 
$ sudo bash program.sh 
Privileged user: root
Unprivileged user: somebody

답변3

3.) su << EOF << ... EOF는 전체 코드 블록을 올바르게 처리합니다. 이것은 나를 괴롭히는 한 가지 문제인 구문 강조가 없는 가장 우아한 솔루션(스크립트의 논리적 구조가 파괴되지 않기 때문에)이 될 것입니다. 내가 시도한 모든 주요 편집자들은 여기 문서 내의 전체 블록에 대해 하나의 색상을 사용합니다. 구문 강조 없이 스크립트의 80%를 읽는 것은 좋지 않습니다.

다음에서 사용자 정의 구문 강조를 정의할 수 있어야 합니다.네가 원하는 대로 하게 놔둬이 기사기사도 흥미로울 수 있습니다.

관련 정보