sudo에서 처리된 백틱에 cmd가 중첩되어 있습니까?

sudo에서 처리된 백틱에 cmd가 중첩되어 있습니까?

`commands`(더 이상 사용되지 않는) 백틱을 사용하여 (명령줄에서) 루트 권한으로 중첩이 수행 되지만 sudo명령 대체는 $(...)수행되지 않습니까?

예를 들어

sudo mount `blkid -u /dev/sda1` ...
sudo mount `sudo blkid -u /dev/sda1` ...

그리고

sudo mount $(blkid -u /dev/sda1) ...
sudo mount $(sudo blkid -u /dev/sda1) ...

방법에 차이가 있나요? 네 줄 중 어느 줄이 올바른 사용법인지조차 확신할 수 없습니다( sudoblkid가 아니라 의사 코드일 뿐입니다). 아니면 쉘에 의존합니까?

답변1

`...`$(...)동일하지만 구문이 다르기 때문에 하나는 Bourne 셸에서, 다른 하나는 Korn 셸에서 옵니다. 전자는 더 이상 사용되지 않지만 고대 Bourne 셸과의 하위 호환성을 위해 Bourne 유사 셸에서 여전히 지원됩니다 .

다른 쉘에는 다른 구문이 있습니다. 예를 들어 fishhas (...)rc/ eshave `cmd또는 `{more complex cmd}`(sep){cmd}다른 분할 동작을 지정합니다. ksh93그리고 (하위 쉘이 없는) 변형 mksh도 있습니다 .${ ...; }

어쨌든 이는 쉘 언어의 구문이므로 이를 해석하고 명령 대체를 수행하려면 쉘이 필요합니다.

존재하다:

sudo cmd1 `cmd2`

Bourne과 같은 껍질에서는 껍질이

  • cmd2출력이 파이프로 리디렉션되는 하위 프로세스에서 실행됩니다.
  • 파이프의 다른 쪽 끝에서 이 cmd의 출력을 읽습니다.
  • 후행 줄 바꿈을 제거하고,
  • 세분화 결과에 따르면$IFS
  • 생성된 단어에 대해 파일 이름 생성을 수행합니다(in 외에도 zsh일부 ksh 변형은 중괄호 확장도 수행함).
  • 그런 다음 결과 단어는 sudo다른 하위 프로세스에서 실행되는 명령에 별도의 인수로 전달됩니다.

sudo그런 다음 uid를 변경하고 인수로 전달된 명령을 실행하십시오.

다른 uid로 실행 하려면 명령 대체를 수행하는 쉘 코드를 해석하기 위해 실행 중인 쉘이 cmd2필요합니다 .sudo

sudo sh -c 'cmd1 $(cmd2)'
sudo fish -c 'cmd1 (cmd2)'
sudo rc -c 'cmd1 `cmd2'

등.

Bourne과 유사한 쉘에서는 명령 대체가 여전히 큰따옴표 내에서 수행되므로아니요하다:

sudo sh -c "cmd1 $(cmd2)"

cmd2첫째, 로 실행되지 않으며 root출력 cmd2(이번에는 따옴표 안에 있기 때문에 분할+glob의 영향을 받지 않음)이 sh코드로 해석되므로 일반적으로 명령 주입 취약점을 구성합니다. 예를 들어, 출력인 경우 호출자 cmd2에게 설명 하고 다시 시작하라는 메시지가 표시됩니다 .$(reboot)shsudocmd1 $(reboot)

마찬가지로 변수의 내용을 전달하려면 sudo sh -c 'cmd1 $(cmd2) '"$var"다음을 수행하지 마세요.sudo sh -c 'cmd1 $(cmd2 '"$var"')'당신의셸( 로 시작한 셸 제외 sudo) 을 cmd1또는 로 변경합니다 cmd2. 대신 이러한 변수의 내용을 추가로 전달하세요.논쟁도착 sh(거기 아님)암호sudo매개변수) 또는 환경 변수를 통해(따라서 실행된 셸의 변수이기도 함):

sudo sh -c 'cmd1 $(cmd2) "$1"' sh "$var"
sudo VAR="$var" sh -c 'cmd1 $(cmd2) "$VAR"'

sudo sh -c 'cmd1 $(cmd2 "$1")' sh "$var"
sudo VAR="$var" sh -c 'cmd1 $(cmd2 "$VAR")'

여기에서 언제든지 다음 작업을 수행할 수도 있습니다.

sudo cmd1 $(sudo cmd2) "$var"
sudo cmd1 $(sudo cmd2 "$var")

즉,당신의셸은 이 두 명령을 별도의 두 호출로 실행하므로 sudo둘 다 높은 권한으로 실행될 수 있습니다.

위에서 언급했듯이 Bourne과 같은 쉘(그러나 이는 다르지만 csh와 같은 쉘에도 적용됨)에서 인용되지 않은 명령 대체는 분할+glob에 의해 제어되므로 분리된 목록을 출력할 때 와일드카드 패턴이 가능한 경우에만 $(cmd2)사용해야 합니다. 인용없이. 출력(후행 개행 없이)을 전체적으로 전달하려는 경우cmd1 $(cmd2)cmd2$IFScmd2하나cmd1원하는 매개변수를 선택 cmd1 "$(cmd2)"하거나 cmd1 -- "$(cmd2)"매개변수가 옵션으로 처리되지 않도록 해야 합니다(옵션 닫는 태그가 지원된다고 가정 cmd1) --.

따라서 특정 사용 사례의 경우 다음과 같습니다.

sudo DEVICE="$device" sh -c 'mount -- "$(blkid -u -- "$DEVICE")"'

mount아니면 그냥 성공을 요청하세요 blkid:

sudo DEVICE="$device" sh -c '
  output=$(blkid -u -- "$DEVICE") &&
    mount -- "$output"
'

관련 정보