쉘에게 항상 어떤 쉘 코드가 실행을하는지 알려주도록 쉘에 지시 할 수 있습니다. 예를 들어 with를 사용하여 후크를 사용하여 환경 변수 zsh
에 해당 정보를 전달 하면 (예를 들어 프로그램에서 사용 ) :$SHELL_CODE
preexec()
printenv
getenv("SHELL_CODE")
$ preexec() export SHELL_CODE=$1
$ printenv SHELL_CODE
printenv SHELL_CODE
$ printenv SHELL_CODE
printenv CODE
$ $(echo printenv SHELL_CODE)
$(echo printenv SHELL_CODE)
$ for i in SHELL_CODE; do printenv "$i"; done
for i in SHELL_CODE; do printenv "$i"; done
$ printenv SHELL_CODE; : other command
printenv SHELL_CODE; : other command
$ f() printenv SHELL_CODE
$ f
f
모든 printenv
것은 다음과 같이 실행 됩니다.
execve("/usr/bin/printenv", ["printenv", "SHELL_CODE"],
["PATH=...", ..., "SHELL_CODE=..."]);
해당 인수로 printenv
실행되는 zsh 코드를 검색 할 수 printenv
있습니다. 그 정보로 당신이하고 싶은 것은 분명하지 않습니다.
와 bash
기능에 가장 가까운, zsh
S는 ' preexec()
그것을 사용하는 것입니다 $BASH_COMMAND
A의 DEBUG
함정,하지만 노트 bash
(잘 일부) (특히 refactors에 구분 기호로 사용되는 공백의 일부 등)와 그의 모든에 적용한다는 점에서 다시 작성 일정 수준의 수행 명령 프롬프트에서 입력 한 전체 명령 줄이 아니라 실행합니다 ( functrace
옵션 참조 ).
$ trap 'export SHELL_CODE="$BASH_COMMAND"' DEBUG
$ printenv SHELL_CODE
printenv SHELL_CODE
$ printenv $(echo 'SHELL_CODE')
printenv $(echo 'SHELL_CODE')
$ for i in SHELL_CODE; do printenv "$i"; done; : other command
printenv "$i"
$ printf '%s\n' "$(printenv "SHELL_CODE")"
printf '%s\n' "$(printenv "SHELL_CODE")"
$ set -o functrace
$ printf '%s\n' "$(printenv "SHELL_CODE")"
printenv "SHELL_CODE"
$ print${-+env } $(echo 'SHELL_CODE')
print${-+env } $(echo 'SHELL_CODE')
쉘 언어 구문에서 분리 문자 인 일부 공백이 1로 압축 된 방법과 전체 명령 행이 항상 명령에 전달되지 않는 방법을보십시오. 따라서 귀하의 경우에는 유용하지 않을 것입니다.
다음과 같이 모든 명령에 민감한 정보가 유출 될 수 있으므로 이런 종류의 작업을 수행하지 않는 것이 좋습니다.
echo very_secret | wc -c | untrustedcmd
wc
그리고 그 비밀을 모두에게 누설 할 것 untrustedcmd
입니다.
물론, 쉘 이외의 다른 언어에 대해서도 이런 종류의 작업을 수행 할 수 있습니다. 예를 들어 C에서는 명령을 실행하는 C 코드를 환경에 내보내는 매크로를 사용할 수 있습니다.
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#define WRAP(x) (setenv("C_CODE", #x, 1), x)
int main(int argc, char *argv[])
{
if (!fork()) WRAP(execlp("printenv", "printenv", "C_CODE", NULL));
wait(NULL);
if (!fork()) WRAP(0 + execlp("printenv", "printenv", "C_CODE", NULL));
wait(NULL);
if (argc > 1 && !fork()) WRAP(execvp(argv[1], &argv[1]));
wait(NULL);
return 0;
}
예:
$ ./a.out printenv C_CODE
execlp("printenv", "printenv", "C_CODE", NULL)
0 + execlp("printenv", "printenv", "C_CODE", NULL)
execvp(argv[1], &argv[1])
Bash 사례와 같이 C 전 처리기에서 일부 공간이 어떻게 압축되었는지 확인하십시오. 모든 언어는 아니지만 대부분의 언어에서 구분 기호에 사용되는 공간의 양에는 차이가 없으므로 컴파일러 / 통역사가 여기에서 자유 로워지는 것은 놀라운 일이 아닙니다.