답변1
문제는 애플리케이션의 콘텐츠가 $x
삭제되지 않았고 공격자가 제어할 수 있는 데이터가 포함된 경우 쉘 코드가 결국 권한 상승 컨텍스트(예: setuid에 의해 호출되는 스크립트) 애플리케이션에서 사용될 수 있다는 것입니다. sudoers 스크립트 또는 직간접적으로 사용됩니다. 오프 그리드 데이터(CGI, DHCP 후크...)를 처리합니다.
만약에:
x='(PATH=2)'
그 다음에:
x=$((1-$x)))
PATH
이를 2
(공격자가 제어할 가능성이 있는 상대 경로)로 설정하면 부작용이 있습니다. 다음 PATH
으로 대체할 수 있습니다 . bash, zsh 또는 ksh (변수에서 숫자 상수만 허용하는 dash 또는 yash 아님) 에서도 동일한 일이 발생합니다 .LD_LIBRARY_PATH
IFS
x=$((1-x))
알아채다:
x=$((1-$x))
$x
(POSIX에 따라 선택 사항) (감소) 연산자를 구현하는 일부 셸에서는 음수 값에 대해 제대로 작동하지 않습니다 --
( 에서와 같이 이는 셸에서 산술 표현식을 x=-1
평가해야 함을 의미함 ). 확장은 산술 평가의 일부로 수행되므로 문제가 없습니다 (이전은 아님).1--1
"$((1-x))"
x
bash
, zsh
및 ksh
( dash
또는 아님 yash
) 에서 다음과 같은 경우 x
:
x='a[0$(uname>&2)]'
$((1-$x))
그런 다음 or 의 확장으로 인해 $((1-x))
명령이 실행됩니다( 의 경우 배열 변수여야 하지만 예를 들어 사용할 수 있습니다).uname
zsh
a
psvar
요약하자면, 초기화되지 않았거나 삭제되지 않은 외부 데이터는 쉘 산술 표현식에 사용되어서는 안 됩니다.
$((...))
$[...]
산술 평가는 ( in 또는 라고도 함)을 통해 수행할 수 있지만 bash
내장 함수 zsh
의 셸 , 배열 인덱싱 및 구성 등에 따라 달라집니다.let
[
test
declare/typeset/export...
return
break
continue
exit
printf
print
((..))
[[...]]
ksh
// 의 배열 인덱싱에서 작동하기 때문에 변수 이름을 인수로 사용하는 모든 내장 함수( / with , , , // , / with , ... ) zsh
에서도 작동합니다.bash
[
test
-v
read
unset
export
typeset
readonly
print
printf
-v
getopts
숫자 테스트 연산자의 피연산자가 내장 함수가 있든 [[...]]
없든 산술 표현식으로 처리된다는 사실은 OR에서 일반적으로 후자가 선호되는 이유 중 하나입니다.[
test
bash
zsh
비교하다:
$ a='x[1$(uname>&2)]' bash -c '[ "$a" -eq "$b" ]'
bash: line 0: [: x[1$(uname>&2)]: integer expression expected
(보안):
$ a='x[1$(uname>&2)]' bash -c '[[ "$a" -eq "$b" ]]'
Linux
( uname
실행되었습니다).
( ksh
, 및 에 문제 [
가 있습니다 .)[[ ... ]]
변수에 리터럴 십진 정수가 포함되어 있는지 확인하려면 POSIXly를 사용할 수 있습니다.
case $var in
("" | - | *[!0123456789-]* | ?*-*) echo >&2 not a valid number; exit 1;;
esac
일부 로케일에서는 [0-9]
및 [[:digit:]]
가 0123456789 이상으로 일치하므로 모든 형태의 입력 유효성 검사/삭제를 피해야 합니다.
또한 어떤 경우에는 앞에 0이 붙은 숫자가 8진수( 010
때때로 10, 때로 8)로 처리된다는 점을 염두에 두십시오. 위 검사에서는 시스템보다 더 큰 시스템이 허용될 수도 있습니다(또는 지원되는 가장 큰 정수를 사용함). 어떤 응용 프로그램이든). 해당 정수를 사용하십시오. 예를 들어 bash는 18446744073709551616 을 0으로 처리합니다. 왜냐하면 2 64 이기 때문입니다 . 따라서 위의 사례 설명에 추가 검사를 추가해야 할 수도 있습니다. 예를 들면 다음과 같습니다.
(0?* | -0?*)
echo >&2 'Only decimal numbers without leading 0 accepted'; exit 1;;
(-??????????* | [!-]?????????*)
echo >&2 'Only numbers from -999999999 to 999999999 supported'; exit 1;;
예:
$ export 'x=psvar[0$(uname>&2)]'
$ ksh93 -c 'echo "$((x))"'
Linux
ksh93: psvar: parameter not set
$ ksh93 -c '[ x -lt 2 ]'
Linux
ksh93: [: psvar: parameter not set
$ bash -c 'echo "$((x))"'
Linux
0
$ bash -c '[[ $x -lt 2 ]]'
Linux
$ bash -c 'typeset -i a; export a="$x"'
Linux
$ bash -c 'typeset -a a=([x]=1)'
Linux
$ bash -c '[ -v "$x" ]'
Linux
$ bash -c 'read "$x"' < /dev/null
Linux
$ env psvar= bash -c 'unset "$x"'
Linux
$ mksh -c '[[ $x -lt 2 ]]'
Linux
$ zsh -c 'echo "$((x))"'
Linux
0
$ zsh -c 'printf %d $x'
Linux
0
$ zsh -c 'integer x'
Linux
$ zsh -c 'exit $x'
Linux
추가 자료:
- http://www.zsh.org/mla/workers/2014/msg01041.html(올리버 키들이
x[0$(...)]
우리에게 이런 질문을 했습니다.) - http://thread.gmane.org/gmane.comp.standards.posix.austin.general/9971(
lynx news://news.gmane.io/gmane.comp.standards.posix.austin.general/9971
gmane의 웹 인터페이스는 이제 중단되었습니다.) - https://lists.gnu.org/archive/html/bug-bash/2014-12/msg00028.html코드 삽입으로 이어질 수 있는 또 다른 설계 오류입니다
bash
. - bash/POSIX 쉘에서 변수를 인용하는 것을 잊어버리는 보안 위험변수를 따옴표로 묶지 않으면 서로가 악화될 수 있습니다.