나는 setuid 바이너리의 보안을 만지작거리고 있습니다(분명히 내가 찾은 모든 것을 작성자에게 공개하기 위해). 쉘 스크립트를 호출하고 환경을 삭제하지 않기 때문에 임의의 코드 실행 취약점이 있다고 확신합니다. Bash를 생각했지만 export -f
실제로 개념 증명을 수행할 수는 없습니다.
기본적인 문제는 어떤 이유로 BASH_FUNC_foobar%%
( foobar
내보낸 함수가 있는 경우) 일부 하위 프로세스의 환경에서 불가사의하게 사라진다는 것입니다. 쉘이 아닌 경우에도 작동합니다.
% env 'BASH_FUNC_foobar%%=() { echo pwd lol; }' env | grep BASH
BASH_FUNC_foobar%%=() { echo pwd lol; }
env | grep BASH
그러나 실제 프로그램 이름으로 바꾸고 환경을 덤프하도록 수정하면 (기본적으로 system("env")
C 소스 코드에서) 변수가 삭제됩니다. sh
호출할 명령을 지정하면 동일한 일이 발생합니다. 하지만 이상하게도 지정하면 bash
함수가 제대로 선택됩니다.
내 테스트 시스템 /bin/sh
에서는 dash
.
도대체 무슨 일이 일어난 걸까요? 이 변수는 왜 사라지나요?
답변1
많은 Linux 시스템에서 /bin/sh
이는 실제로 /bin/dash
.
이미 언급했듯이논평by @MichaelHomer는 /bin/dash
환경을 정리하고 , for를 /^[a-zA-Z_][a-zA-Z_0-9]*=.*/
포함하여 양식의 일부가 아닌 모든 문자열을 제거합니다 .BASH_FUNC_foo%%=...
%%
이는 dash
OpenBSD ksh
(및 이에 기반한 것) mksh
에만 적용됩니다 . 다른 쉘에서는 이 작업을 수행하지 않습니다.
예를 들어 Debian에서는 /bin/sh
다음과 같습니다 dash
.
$ env - '@#%=' 'foo%%=bar' /bin/sh -c /usr/bin/printenv
PWD=/your/cwd
$ env - '@#%=' 'foo%%=bar' /usr/bin/printenv
@#%=
foo%%=bar
$ env - '@#%=' 'foo%%=bar' /bin/bash -c /usr/bin/printenv
[...]
@#%=
foo%%=bar
소스 참조를 위해 확인할 수 있습니다src/var.cdash
소스 에서 :
initvar();
for (envp = environ ; *envp ; envp++) {
p = endofname(*envp);
if (p != *envp && *p == '=') {
setvareq(*envp, VEXPORT|VTEXTFIXED);
}
}
dash
exec가 또 다른 바이너리인 경우 , env
여기에 전달된 인수는 execve
변수 목록에서 ( listvars(VEXPORT, VUNSET, 0)
매크로 호출을 통해 environment()
) 동적으로 구성됩니다.