script.sh에서:
#!/bin/bash
func(){
echo "I am here a func."
}
export -f func
export variable="I am here a variable"
sudo -E bash -c "func ; echo $variable"
출력은 다음과 같습니다.
bash: func: command not found
I am here a variable
- 왜?
- 초기 쉘에서 sudo를 통해 [script.sh에 선언된] 함수를 호출할 수 있는 솔루션이 있습니까?
사실 저는 다음과 같은 방법을 알고 있습니다.
#!/bin/bash
func(){
echo "I am here a func."
}
FUNC=$(declare -f func)
export variable="I am here a variable"
sudo -E bash -c "$FUNC; func ; echo $variable"
그런데 이렇게 모든 기능을 등록해야 하니 너무 무겁다는 생각이 듭니다.
답변1
export -f func
내 환경에서 다음을 확인한 후:
$ env | grep func
BASH_FUNC_func%%=() …
Bash는 와 같은 이름 BASH_FUNC_foo%%
과 로 시작하는 값을 가진 변수로 함수를 내보냅니다 ()
.쉘 쇼크이름에는 접두어( )가 없습니다 foo=() …
. Apple 접두사는 __BASH_FUNC<
. 어쨌든 값은 ()
.
sudo
이러한 이름과 환경 전체에 매우 주의를 기울이십시오. sudo
Bash 스크립트를 실행하기 위해 스크립트를 사용할 수 있다고 상상해 보세요 . 스크립트가 합법적으로 사용된다고 상상해 보세요 cat
. 귀하라는 이름의 셸 함수를 내보내면 cat
스크립트를 효과적으로 변경하고 임의의 코드를 실행할 수 있습니다.
당신은 당신 자신의 것을 사용할 수 있습니다 $PATH
(그리고이것을 할 수 있는 방법이 있나요?; 그러나 관리자는 이를 방지하는 방법도 있습니다. 또는 사용할 수 있는 경우 $LD_PRELOAD
(그리 쉽지는 않습니다. 참조)man 5 sudoers
) 을 언급했다 LD_
.
내보낸 쉘 함수로 돌아가 보겠습니다. 먼저 sudo -V
루트( sudo sudo -V
일반 사용자) 로 실행 하면 출력의 일부는 다음과 같습니다.
Environment variables to remove:
*=()*
아니면:
Environment variables to remove:
__BASH_FUNC<*
BASH_FUNC_*
버전에 따라 다르다고 생각합니다 sudo
.
다음 줄을 사용하여 목록에서 이러한 패턴을 제거할 수 있습니다 sudoers
(그러나 이렇게 하지 말고 먼저 전체 답변을 읽으십시오).
Defaults env_delete -= "*=()* BASH_FUNC_* __BASH_FUNC<*"
"유지" 목록에 추가할 수도 있습니다(추가하지 않아도 됨).
Defaults env_keep += "*=()* BASH_FUNC_* __BASH_FUNC<*"
그러나 내보낸 함수가 반드시 와 함께 작동하는 것은 아닙니다 sudo
. 그 이유는 패턴이 *=()*
하드 코딩될 수 있고 sudo
거부 변수의 일부 버전 값이 로 시작하기 때문 입니다 ()
. 이 행동은 진화되었습니다. 사용 가능한 솔루션은 sudo
사용 중인 버전에 따라 다릅니다.
~에서man 5 sudoers
:
명령 환경
환경 변수는 프로그램 동작에 영향을 미칠 수 있으므로
sudoers
실행 중인 명령에 의해 상속되는 사용자 환경의 변수를 제한하는 방법이 제공됩니다. sudoers에는 환경 변수를 처리하는 두 가지 방법이 있습니다.기본적으로 이
env_reset
옵션은 활성화되어 있습니다. [...]HOME
,SHELL
환경 변수는 대상 사용자를 기준으로 초기화되고LOGNAME
변수는 호출 사용자를 기준으로 설정됩니다. 또는 옵션이 허용되면 , 및 같은 다른 변수는 호출하는 사용자 환경에서 보존됩니다. 이것은 실제로 환경 변수의 화이트리스트입니다. [...] 값이 or 로 시작하는 환경 변수는 이름과 값 부분이 모두 or 와 일치하지 않는 한 제거됩니다. 이는 bash 셸에서 함수로 해석될 수 있기 때문입니다. 버전 1.8.11 이전에는 이러한 변수가 항상 제거되었습니다.USER
SUDO_*
DISPLAY
PATH
TERM
env_check
env_keep
()
env_keep
env_check
그러나
env_reset
이 옵션이 비활성화된 경우env_check
및 옵션env_delete
에 의해 명시적으로 거부되지 않은 모든 변수는 호출 프로세스에 의해 상속됩니다. 이 경우env_check
동작은env_delete
블랙리스트와 같습니다. 버전 1.8.21 이전에는()
값이 로 시작하는 환경 변수가 항상 제거되었습니다. 버전 1.8.21부터 패턴을 사용하여env_delete
bash 쉘 기능을 일치시킵니다. 잠재적으로 위험한 환경 변수를 모두 블랙리스트에 올리는 것은 불가능하므로env_reset
기본 동작이 권장됩니다.
env_check
, 또는 로env_delete
지정된 환경 변수에는 0개 이상의 문자와 일치하는env_keep
하나 이상의 문자가 포함될 수 있습니다 .*
다른 와일드카드 문자는 지원되지 않습니다.기본적으로 환경 변수는 이름으로 일치됩니다. 단, 패턴에 등호(
=
)가 포함된 경우에는 변수명과 값이 모두 일치해야 합니다. 예를 들어 bash 쉘 함수는 다음과 같이 일치될 수 있습니다.env_keep += "BASH_FUNC_my_func%%=()*"
=()*
접미사가 없으면 bash 쉘 기능이 기본적으로 유지되지 않으므로 이는 일치하지 않습니다.
보시다시피 env_reset
이것은 중요합니다. 아마도 활성화되어 있을 것입니다. -E
option()의 요점 은 sudo -E
요청 시 비활성화하는 것입니다.env_reset
내 Kubuntu 18.04.3 LTS에서 내 sudo
버전은 1.8.21입니다. 기본적으로 *=()*
삭제할 변수 목록에 배치됩니다 . 다음 줄은 sudoers
이를 중지시킵니다.
Defaults env_delete -= "*=()*"
그러면 sudo -E
내보낸 쉘 기능은 모두 보존됩니다.이것이 나의 주요 대답입니다.
내 데비안 9 sudo
버전은 1.8.19입니다. 기본적으로 제거할 변수 목록에 BASH_FUNC_*
및 가 배치됩니다 . __BASH_FUNC<*
이러한 항목을 제거해도 아무런 효과가 없습니다 ()
. 이 동작이 하드 코딩된 것처럼 보이는 값이 무엇이든 이 도구는 거의 항상 변수를 거부하기 때문입니다.
이 버전의 매뉴얼은 몇 가지 단서를 제공합니다. 해결책을 찾았습니다.
Defaults env_keep += "BASH_FUNC_func%%=()*"
그 다음에sudo
아니요 -E
func
내보내면 이 특정 셸 기능( )이 유지됩니다. 단점(어떤 경우에는 장점일 수도 있음):
- 이는 적용되지 않으므로
sudo -E
필요에 따라 나머지 환경을 간단히 유지할 수는 없습니다. - 와일드카드 없이 변수의 전체 이름을 명시적으로 지정해야 합니다.
BASH_FUNC_*%%=()*
그렇지 않으면BASH_FUNC_*
작동*=()*
하지 않습니다.
이 방법은 1.8.21에서도 작동합니다.
매뉴얼에 따르면 1.8.11 버전 이전에는 로 시작하는 변수가 ()
항상 제거되었습니다. 당신이 sudo
그 나이라면 질문에 사용한 트릭(또는 유사한 트릭) 외에는 해결책이 없습니다.
노트:
sudoers
다른 파일처럼 편집 하지 마십시오visudo
. 만일의 경우를 대비한 기타 예방 조치:- 별도의 "대체" 셸을 루트( )로 시작합니다
sudo -i
.sudoers
메인 쉘에서 어리석은 짓을 했다면, 이 파일에 의존하지 않고도 루트로 실행할 수 있습니다 . - SSH를 통해 연결하는 경우 상승된 셸을 생성하기 전에 또는 를 사용하세요
tmux
.screen
어리석은 일을 하여sudoers
(우연히) 연결이 실패하면 관리자 권한 쉘은 일반 사용자가 종료하는 대신 다시 연결될 때까지 기다립니다. cp -a
특히 실험 중인 경우 먼저 파일의 백업 복사본을 만듭니다( ).- 작업이 완료되었다고 생각되면 "대체" 상승된 셸을 종료하기 전에 루트 액세스 권한을 다시 얻을 수 있는지 확인하세요.
- 별도의 "대체" 셸을 루트( )로 시작합니다
sudo
당신이 유일한 사용자이고 sudoer가 임의의 코드를 실행하도록 허용하는 트릭에 대한 방어를 강화하는 데 별 의미가 없더라도(당신은sudo
어떤 트릭 없이도 임의의 코드를 자유롭게 실행할 수 있고 그것을 원하기 때문에) 너무 많은 것을 허용하기 전에 두 번 생각하십시오. . 쉘 기능을 그대로 유지 하면sudo
지금 당장은 아니지만 미래에는 쉽게 공격을 받을 수 있습니다.