이 질문은 완전히 일반적인 것이며 제 경우에만 적용되는 것이 아닙니다. 저는 작은 비지박스 장치를 가지고 있고 루트가 아닌 사용자가 루트 권한으로 특정 스크립트를 실행할 수 있기를 원합니다. 예를 들어, DHCP를 활성화하는 다음과 같은 작은 스크립트가 있습니다. 여기서 $1
cmdline(!!)으로 전송되는 유일한 변수는 전송할 호스트 이름입니다.
#!/bin/bash
udhcpc -b -i eth0 -h $1
/etc/sudoers
udhcpc를 이와 같이 실행하려면 루트 액세스가 필요하므로 다음 줄을 포함하도록 수정할 계획입니다 .
joe ALL = NOPASSWD: /path/to/enable_dhcp.sh
이렇게 하면 "joe"가 다음을 실행하여 루트 권한으로 스크립트를 쉽게 실행할 수 있습니다.
sudo /path/to/enable_dhcp.sh
그리고 비밀번호를 묻지 마세요(저는 Joe가 이 스크립트를 작성할 수 있기를 원하기 때문에 비밀번호를 원합니다).
지금 나는알다(또는 적어도 내 생각에는) $1
루트 권한으로 쉽게 실행할 수 있는 스크립트에 사용하는 것은 끔찍한 아이디어입니다. 원하는 것은 무엇이든 삽입할 수 있기 때문입니다.
그럼... 이 문제를 처리하는 가장 좋은 방법은 무엇입니까? 주입 공격에 취약하지 않고 Joe가 루트 권한으로 원하는 작업을 수행하여 변수를 전달할 수 있도록(또는 환경 변수를 사용하는 것만큼 효율적으로 수행)하려면 어떻게 해야 합니까?
답변1
아래 쉘 스크립트를 실행하는 것이 sudo
안전합니다전제는 sudo
환경을 재설정하도록 구성된다는 것 입니다.. 반대로, sudo
스크립트가 인수를 사용하지 않더라도 환경을 재설정하지 않고 쉘 스크립트를 실행하는 것은 안전하지 않습니다(참조:쉘 스크립트에 setuid 설정 허용). 이 옵션 Defaults env_reset
이 /etc/sudoers
컴파일 시간 기본값인지 확인하십시오 ( sudo sudo -V | grep env
포함되어야 함 Reset the environment to a default set of variables
).
스크립트 매개변수를 사용할 때 특별한 위험은 없습니다. $1
문자열이므로 문자열로 사용해야 합니다. (예를 들어, 이렇게 하지 마세요 eval "$1"
.) 여기서는 변수의 내용에 대해 가정을 하지 않는 것이 특히 중요합니다.모든 변수 대체는 큰따옴표로 묶입니다.(즉, 쓰세요 "$1"
, 쓰지 마세요 $1
). 변수 대체 주위에 큰따옴표를 추가하는 것은 권한으로 실행되는 스크립트에만 국한되지 않지만 항상 수행해야 하는 작업입니다.
udhcpc
호스트 이름처럼 보이지 않는 항목을 처리하는 방법 에 따라 이 매개변수의 유효성을 추가로 확인해야 할 수도 있습니다 . 예를 들어, 첫 번째 구문 검사를 수행합니다.
#!/bin/sh
case "$1" in
*[!:-.0-9A-Za-z]*|-*) echo 1>&2 "Badly formed host name!"; exit 3;;
esac
udhcpc -b -i eth0 -h "$1"
답변2
전달된 입력을 알려진 양호한 패턴과 일치시켜야 합니다.
예를 들어 IP 주소가 유효한 입력일 수 있는 것 같습니다. 따라서 다음과 같이 사용할 수 있습니다.
if [[ "$1" =~ ^[0-9]?[0-9]?[0-9].[0-9]?[0-9]?[0-9].[0-9]?[0-9]?[0-9]$ ]]
then
udhcpc -b -i eth0 -h "$1"
else
echo "Don't mess with me pork chop."
fi
이 정규 표현식은 테스트되지 않았으며 정규 표현식이 위험한 것을 허용하지 않는지 확인하는 것은 귀하의 책임입니다.